<commit_before>/*************************************************************************
 *
 *  $RCSfile: drviewsh.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: aw $ $Date: 2002-04-12 12:44:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library 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.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _AEITEM_HXX //autogen
#include <svtools/aeitem.hxx>
#endif
#ifndef _SFXITEMSET_HXX //autogen
#include <svtools/itemset.hxx>
#endif
#ifndef _SFXREQUEST_HXX //autogen
#include <sfx2/request.hxx>
#endif
#ifndef _SVXIDS_HRC
#include <svx/svxids.hrc>
#endif

#pragma hdrstop

#ifndef _SVX_FMSHELL_HXX            // XXX nur temp (dg)
#include <svx/fmshell.hxx>
#endif
#ifndef _SFXDISPATCH_HXX //autogen
#include <sfx2/dispatch.hxx>
#endif

#include "app.hrc"
#include "strings.hrc"
#include "sdpage.hxx"
#include "frmview.hxx"
#include "sdresid.hxx"
#include "drawdoc.hxx"
#include "docshell.hxx"
#include "sdwindow.hxx"
#include "drviewsh.hxx"
#include "grviewsh.hxx"
#include "drawview.hxx"

#define TABCONTROL_INITIAL_SIZE     500

/*************************************************************************
|*
|* Sprung zu Bookmark
|*
\************************************************************************/

BOOL SdDrawViewShell::GotoBookmark(const String& rBookmark)
{
    return (pDocSh->GotoBookmark(rBookmark));
}

/*************************************************************************
|*
|* Bereich sichtbar machen (Bildausschnitt scrollen)
|*
\************************************************************************/

void SdDrawViewShell::MakeVisible(const Rectangle& rRect, Window& rWin)
{
    // #98568# In older versions, if in X or Y the size of the object was smaller than the
    // visible area, the user-defined zoom was changed. This was decided to be a bug for 6.x,
    // thus I developed a version which instead handles X/Y bigger/smaller and visibility
    // questions seperately. The new behaviour is triggered with the bZoomAllowed parameter
    // which for old behaviour should be set to sal_True. I looked at all uses of MakeVisible()
    // in the application and found no valid reason for really changing the zoom factor, thus
    // I decided to NOT expand (incompatible) this virtual method to get one more parameter. If
    // this is wanted in later versions, feel free to add that bool to the parameter list.
    sal_Bool bZoomAllowed(sal_False);
    Size aLogicSize(rRect.GetSize());

    // Sichtbarer Bereich
    Size aVisSizePixel(rWin.GetOutputSizePixel());
    Rectangle aVisArea(rWin.PixelToLogic(Rectangle(Point(0,0), aVisSizePixel)));
    Size aVisAreaSize(aVisArea.GetSize());

    if(!aVisArea.IsInside(rRect) && !pFuSlideShow)
    {
        // Objekt liegt nicht komplett im sichtbaren Bereich
        sal_Int32 nFreeSpaceX(aVisAreaSize.Width() - aLogicSize.Width());
        sal_Int32 nFreeSpaceY(aVisAreaSize.Height() - aLogicSize.Height());

        if(bZoomAllowed && (nFreeSpaceX < 0 || nFreeSpaceY < 0))
        {
            // Objekt passt nicht in sichtbaren Bereich -> auf Objektgroesse zoomen
            SetZoomRect(rRect);
        }
        else
        {
            // #98568# allow a mode for move-only visibility without zooming.
            const sal_Int32 nPercentBorder(30);
            const Rectangle aInnerRectangle(
                aVisArea.Left() + ((aVisAreaSize.Width() * nPercentBorder) / 200),
                aVisArea.Top() + ((aVisAreaSize.Height() * nPercentBorder) / 200),
                aVisArea.Right() - ((aVisAreaSize.Width() * nPercentBorder) / 200),
                aVisArea.Bottom() - ((aVisAreaSize.Height() * nPercentBorder) / 200)
                );
            Point aNewPos(aVisArea.TopLeft());

            if(nFreeSpaceX < 0)
            {
                if(aInnerRectangle.Left() > rRect.Right())
                {
                    // object moves out to the left
                    aNewPos.X() -= aVisAreaSize.Width() / 2;
                }

                if(aInnerRectangle.Right() < rRect.Left())
                {
                    // object moves out to the right
                    aNewPos.X() += aVisAreaSize.Width() / 2;
                }
            }
            else
            {
                if(nFreeSpaceX > rRect.GetWidth())
                    nFreeSpaceX = rRect.GetWidth();

                while(rRect.Right() > aNewPos.X() + aVisAreaSize.Width())
                    aNewPos.X() += nFreeSpaceX;

                while(rRect.Left() < aNewPos.X())
                    aNewPos.X() -= nFreeSpaceX;
            }

            if(nFreeSpaceY < 0)
            {
                if(aInnerRectangle.Top() > rRect.Bottom())
                {
                    // object moves out to the top
                    aNewPos.Y() -= aVisAreaSize.Height() / 2;
                }

                if(aInnerRectangle.Bottom() < rRect.Top())
                {
                    // object moves out to the right
                    aNewPos.Y() += aVisAreaSize.Height() / 2;
                }
            }
            else
            {
                if(nFreeSpaceY > rRect.GetHeight())
                    nFreeSpaceY = rRect.GetHeight();

                while(rRect.Bottom() > aNewPos.Y() + aVisAreaSize.Height())
                    aNewPos.Y() += nFreeSpaceY;

                while(rRect.Top() < aNewPos.Y())
                    aNewPos.Y() -= nFreeSpaceY;
            }

            // did position change? Does it need to be set?
            if(aNewPos != aVisArea.TopLeft())
            {
                aVisArea.SetPos(aNewPos);
                SetZoomRect(aVisArea);
            }
        }
    }
}

<commit_msg>INTEGRATION: CWS impress1 (1.4.226); FILE MERGED 2004/01/09 16:32:57 af 1.4.226.2: #111996# Renamed header files DrawView.hxx, Fader.hxx, and ShowView.hxx back to lowercase version. 2003/09/17 08:10:10 af 1.4.226.1: #111996# Transition to stacked sub-shells. Introduction of namespace sd.<commit_after>/*************************************************************************
 *
 *  $RCSfile: drviewsh.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2004-01-20 12:48:48 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library 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.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "DrawViewShell.hxx"

#ifndef _AEITEM_HXX //autogen
#include <svtools/aeitem.hxx>
#endif
#ifndef _SFXITEMSET_HXX //autogen
#include <svtools/itemset.hxx>
#endif
#ifndef _SFXREQUEST_HXX //autogen
#include <sfx2/request.hxx>
#endif
#ifndef _SVXIDS_HRC
#include <svx/svxids.hrc>
#endif

#pragma hdrstop

#ifndef _SVX_FMSHELL_HXX            // XXX nur temp (dg)
#include <svx/fmshell.hxx>
#endif
#ifndef _SFXDISPATCH_HXX //autogen
#include <sfx2/dispatch.hxx>
#endif

#include "app.hrc"
#include "strings.hrc"
#include "sdpage.hxx"
#ifndef SD_FRAME_VIEW
#include "FrameView.hxx"
#endif
#include "sdresid.hxx"
#include "drawdoc.hxx"
#include "DrawDocShell.hxx"
#ifndef SD_WINDOW_HXX
#include "Window.hxx"
#endif
#ifndef SD_GRAPHIC_VIEW_SHELL_HXX
#include "GraphicViewShell.hxx"
#endif
#ifndef SD_DRAW_VIEW_HXX
#include "drawview.hxx"
#endif

namespace sd {

#define TABCONTROL_INITIAL_SIZE     500

/*************************************************************************
|*
|* Sprung zu Bookmark
|*
\************************************************************************/

BOOL DrawViewShell::GotoBookmark(const String& rBookmark)
{
    return (GetDocSh()->GotoBookmark(rBookmark));
}

/*************************************************************************
|*
|* Bereich sichtbar machen (Bildausschnitt scrollen)
|*
\************************************************************************/

void DrawViewShell::MakeVisible(const Rectangle& rRect, Window& rWin)
{
    // #98568# In older versions, if in X or Y the size of the object was smaller than the
    // visible area, the user-defined zoom was changed. This was decided to be a bug for 6.x,
    // thus I developed a version which instead handles X/Y bigger/smaller and visibility
    // questions seperately. The new behaviour is triggered with the bZoomAllowed parameter
    // which for old behaviour should be set to sal_True. I looked at all uses of MakeVisible()
    // in the application and found no valid reason for really changing the zoom factor, thus
    // I decided to NOT expand (incompatible) this virtual method to get one more parameter. If
    // this is wanted in later versions, feel free to add that bool to the parameter list.
    sal_Bool bZoomAllowed(sal_False);
    Size aLogicSize(rRect.GetSize());

    // Sichtbarer Bereich
    Size aVisSizePixel(rWin.GetOutputSizePixel());
    Rectangle aVisArea(rWin.PixelToLogic(Rectangle(Point(0,0), aVisSizePixel)));
    Size aVisAreaSize(aVisArea.GetSize());

    if(!aVisArea.IsInside(rRect) && !pFuSlideShow)
    {
        // Objekt liegt nicht komplett im sichtbaren Bereich
        sal_Int32 nFreeSpaceX(aVisAreaSize.Width() - aLogicSize.Width());
        sal_Int32 nFreeSpaceY(aVisAreaSize.Height() - aLogicSize.Height());

        if(bZoomAllowed && (nFreeSpaceX < 0 || nFreeSpaceY < 0))
        {
            // Objekt passt nicht in sichtbaren Bereich -> auf Objektgroesse zoomen
            SetZoomRect(rRect);
        }
        else
        {
            // #98568# allow a mode for move-only visibility without zooming.
            const sal_Int32 nPercentBorder(30);
            const Rectangle aInnerRectangle(
                aVisArea.Left() + ((aVisAreaSize.Width() * nPercentBorder) / 200),
                aVisArea.Top() + ((aVisAreaSize.Height() * nPercentBorder) / 200),
                aVisArea.Right() - ((aVisAreaSize.Width() * nPercentBorder) / 200),
                aVisArea.Bottom() - ((aVisAreaSize.Height() * nPercentBorder) / 200)
                );
            Point aNewPos(aVisArea.TopLeft());

            if(nFreeSpaceX < 0)
            {
                if(aInnerRectangle.Left() > rRect.Right())
                {
                    // object moves out to the left
                    aNewPos.X() -= aVisAreaSize.Width() / 2;
                }

                if(aInnerRectangle.Right() < rRect.Left())
                {
                    // object moves out to the right
                    aNewPos.X() += aVisAreaSize.Width() / 2;
                }
            }
            else
            {
                if(nFreeSpaceX > rRect.GetWidth())
                    nFreeSpaceX = rRect.GetWidth();

                while(rRect.Right() > aNewPos.X() + aVisAreaSize.Width())
                    aNewPos.X() += nFreeSpaceX;

                while(rRect.Left() < aNewPos.X())
                    aNewPos.X() -= nFreeSpaceX;
            }

            if(nFreeSpaceY < 0)
            {
                if(aInnerRectangle.Top() > rRect.Bottom())
                {
                    // object moves out to the top
                    aNewPos.Y() -= aVisAreaSize.Height() / 2;
                }

                if(aInnerRectangle.Bottom() < rRect.Top())
                {
                    // object moves out to the right
                    aNewPos.Y() += aVisAreaSize.Height() / 2;
                }
            }
            else
            {
                if(nFreeSpaceY > rRect.GetHeight())
                    nFreeSpaceY = rRect.GetHeight();

                while(rRect.Bottom() > aNewPos.Y() + aVisAreaSize.Height())
                    aNewPos.Y() += nFreeSpaceY;

                while(rRect.Top() < aNewPos.Y())
                    aNewPos.Y() -= nFreeSpaceY;
            }

            // did position change? Does it need to be set?
            if(aNewPos != aVisArea.TopLeft())
            {
                aVisArea.SetPos(aNewPos);
                SetZoomRect(aVisArea);
            }
        }
    }
}

}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2005-2007 by the FIFE Team                              *
 *   fife-public@lists.sourceforge.net                                     *
 *   This file is part of FIFE.                                            *
 *                                                                         *
 *   FIFE is free software; you can redistribute it and/or modify          *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA              *
 ***************************************************************************/

// Standard C++ library includes

// 3rd party library includes

// FIFE includes
// These includes are split up in two parts, separated by one empty line
// First block: files included from the FIFE root src directory
// Second block: files included from the same folder
#include "model/structures/instance.h"

#include "instancetree.h"

namespace FIFE {

	InstanceTree::InstanceTree(): FifeClass() {
	}

	InstanceTree::~InstanceTree() {
	}

	bool InstanceTree::addInstance(Instance* instance) {
		ModelCoordinate coords = instance->getLocation().getLayerCoordinates();
		InstanceList& list = m_tree.find_container(coords.x,coords.y,0,0)->data();
		list.push_back(instance);
		return true;
	}

	bool InstanceTree::removeInstance(Instance* instance) {
		ModelCoordinate coords = instance->getLocation().getLayerCoordinates();
		InstanceList& list = m_tree.find_container(coords.x,coords.y, 0, 0)->data();

		for(InstanceList::iterator i = list.begin(); i != list.end(); ++i) {
			if((*i) == instance) {
				list.erase(i);
				return true;
			}
		}

		return false;
	}

	class InstanceListCollector {
		public:
			InstanceTree::InstanceList& instanceList;
			InstanceListCollector(InstanceTree::InstanceList& a_instanceList) : instanceList(a_instanceList) {
			}
			bool visit(InstanceTree::InstanceTreeNode* node, int d);
	};

	bool InstanceListCollector::visit(InstanceTree::InstanceTreeNode* node, int d) {
		InstanceTree::InstanceList& list = node->data();
		std::copy(list.begin(),list.end(),std::back_inserter(instanceList));
		return true;
	}

	void InstanceTree::findInstances(const ModelCoordinate& point, int w, int h, InstanceTree::InstanceList& list) {
		InstanceTreeNode * node = m_tree.find_container(point.x, point.y, w, h);
		InstanceListCollector collector(list);
		node->apply_visitor(collector);

		node = node->parent();
		while( node ) {
			std::copy(node->data().begin(),node->data().end(),std::back_inserter(list));
			node = node->parent();
		}
	}

}
<commit_msg>QuadTree: Part II. Check parent tree nodes for intersection.<commit_after>/***************************************************************************
 *   Copyright (C) 2005-2007 by the FIFE Team                              *
 *   fife-public@lists.sourceforge.net                                     *
 *   This file is part of FIFE.                                            *
 *                                                                         *
 *   FIFE is free software; you can redistribute it and/or modify          *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA              *
 ***************************************************************************/

// Standard C++ library includes

// 3rd party library includes

// FIFE includes
// These includes are split up in two parts, separated by one empty line
// First block: files included from the FIFE root src directory
// Second block: files included from the same folder
#include "model/structures/instance.h"
#include "util/rect.h"

#include "instancetree.h"

namespace FIFE {

	InstanceTree::InstanceTree(): FifeClass() {
	}

	InstanceTree::~InstanceTree() {
	}

	bool InstanceTree::addInstance(Instance* instance) {
		ModelCoordinate coords = instance->getLocation().getLayerCoordinates();
		InstanceList& list = m_tree.find_container(coords.x,coords.y,0,0)->data();
		list.push_back(instance);
		return true;
	}

	bool InstanceTree::removeInstance(Instance* instance) {
		ModelCoordinate coords = instance->getLocation().getLayerCoordinates();
		InstanceList& list = m_tree.find_container(coords.x,coords.y, 0, 0)->data();

		for(InstanceList::iterator i = list.begin(); i != list.end(); ++i) {
			if((*i) == instance) {
				list.erase(i);
				return true;
			}
		}

		return false;
	}

	class InstanceListCollector {
		public:
			InstanceTree::InstanceList& instanceList;
			InstanceListCollector(InstanceTree::InstanceList& a_instanceList) : instanceList(a_instanceList) {
			}
			bool visit(InstanceTree::InstanceTreeNode* node, int d);
	};

	bool InstanceListCollector::visit(InstanceTree::InstanceTreeNode* node, int d) {
		InstanceTree::InstanceList& list = node->data();
		std::copy(list.begin(),list.end(),std::back_inserter(instanceList));
		return true;
	}

	void InstanceTree::findInstances(const ModelCoordinate& point, int w, int h, InstanceTree::InstanceList& list) {
		InstanceTreeNode * node = m_tree.find_container(point.x, point.y, w, h);
		InstanceListCollector collector(list);
		node->apply_visitor(collector);

		Rect rect(point.x, point.y, w, h);
		node = node->parent();
		while( node ) {
			for(InstanceList::const_iterator it(node->data().begin()); it != node->data().end(); ++it) {
				ModelCoordinate coords = (*it)->getLocation().getLayerCoordinates();
				if( rect.contains(Point(coords.x,coords.y)) ) {
					list.push_back(*it);
				}
			}
			node = node->parent();
		}
	}

}
<|endoftext|>


<commit_before>// Ouzel by Elviss Strazdins

#ifndef OUZEL_GRAPHICS_OGLPROCEDUREGETTER_HPP
#define OUZEL_GRAPHICS_OGLPROCEDUREGETTER_HPP

#include "../../core/Setup.h"

#if OUZEL_COMPILE_OPENGL

#include <algorithm>
#include <stdexcept>

#include "OGL.h"

#if OUZEL_OPENGLES
#  include "GLES/gl.h"
#  include "GLES2/gl2.h"
#  include "GLES2/gl2ext.h"
#  include "GLES3/gl3.h"
#else
#  include "GL/glcorearb.h"
#  include "GL/glext.h"
#endif

#if OUZEL_OPENGL_INTERFACE_EGL
#  include "EGL/egl.h"
#elif OUZEL_OPENGL_INTERFACE_WGL
#  include "GL/wglext.h"
#  include "../../platform/winapi/Library.hpp"
#endif

#include "../../core/Engine.hpp"
#include "../../utils/Utils.hpp"

namespace ouzel::graphics::opengl
{
    class ProcedureGetter final
    {
    public:
        ProcedureGetter(ApiVersion version):
            apiVersion{version}
        {
            const auto glGetErrorProc = getProcAddress<PFNGLGETERRORPROC>("glGetError", ApiVersion{1, 0});

            if (apiVersion >= ApiVersion{3, 0})
            {
                const auto glGetIntegervProc = getProcAddress<PFNGLGETINTEGERVPROC>("glGetIntegerv", ApiVersion{1, 0});
                const auto glGetStringiProc = getProcAddress<PFNGLGETSTRINGIPROC>("glGetStringi", ApiVersion{3, 0});

                GLint extensionCount;
                glGetIntegervProc(GL_NUM_EXTENSIONS, &extensionCount);

                if (const auto error = glGetErrorProc(); error != GL_NO_ERROR)
                    logger.log(Log::Level::warning) << "Failed to get OpenGL extension count, error: " + std::to_string(error);
                else
                    for (GLuint i = 0; i < static_cast<GLuint>(extensionCount); ++i)
                    {
                        const auto extensionPtr = glGetStringiProc(GL_EXTENSIONS, i);

                        if (const auto getStringError = glGetErrorProc(); getStringError != GL_NO_ERROR)
                            logger.log(Log::Level::warning) << "Failed to get OpenGL extension, error: " + std::to_string(getStringError);
                        else if (!extensionPtr)
                            logger.log(Log::Level::warning) << "Failed to get OpenGL extension";
                        else
                            extensions.emplace_back(reinterpret_cast<const char*>(extensionPtr));
                    }
            }
            else
            {
                const auto glGetStringProc = getProcAddress<PFNGLGETSTRINGPROC>("glGetString", ApiVersion{1, 0});
                const auto extensionsPtr = glGetStringProc(GL_EXTENSIONS);

                if (const auto error = glGetErrorProc(); error != GL_NO_ERROR)
                    logger.log(Log::Level::warning) << "Failed to get OpenGL extensions, error: " + std::to_string(error);
                else if (!extensionsPtr)
                    logger.log(Log::Level::warning) << "Failed to get OpenGL extensions";
                else
                    extensions = explodeString(reinterpret_cast<const char*>(extensionsPtr), ' ');
            }

            logger.log(Log::Level::all) << "Supported OpenGL extensions: " << extensions;
        }

        template <typename T>
        T get(const char* name, ApiVersion procApiVersion) const noexcept
        {
            return (apiVersion >= procApiVersion) ? getProcAddress<T>(name, procApiVersion) : nullptr;
        }

        template <typename T>
        T get(const char* name, const char* extension) const noexcept
        {
            return hasExtension(extension) ? getProcAddress<T>(name) : nullptr;
        }

        template <typename T>
        T get(const char* name,
              ApiVersion procApiVersion,
              const std::map<const char*, const char*>& procExtensions) const noexcept
        {
            if (apiVersion >= procApiVersion)
                return getProcAddress<T>(name, procApiVersion);
            else
                for (const auto& extension : procExtensions)
                    if (auto result = get<T>(extension.first, extension.second))
                        return result;

            return nullptr;
        }

        bool hasExtension(const char* ext) const noexcept
        {
            return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
        }

    private:
        template <typename T>
        T getProcAddress(const char* name, ApiVersion procApiVersion) const noexcept
        {
#if OUZEL_OPENGL_INTERFACE_EGL
#  if OUZEL_OPENGLES
            return procApiVersion >= ApiVersion{3, 0} ?
                reinterpret_cast<T>(eglGetProcAddress(name)) :
                reinterpret_cast<T>(reinterpret_cast<std::uintptr_t>(dlsym(RTLD_DEFAULT, name)));
#  else
            (void)procApiVersion;
            return reinterpret_cast<T>(eglGetProcAddress(name));
#  endif
#elif OUZEL_OPENGL_INTERFACE_WGL
            return procApiVersion > ApiVersion{1, 1} ?
                reinterpret_cast<T>(wglGetProcAddress(name)) :
                reinterpret_cast<T>(GetProcAddress(library.get(), name));
#else
            (void)procApiVersion;
            return reinterpret_cast<T>(reinterpret_cast<std::uintptr_t>(dlsym(RTLD_DEFAULT, name)));
#endif
        }

        template <typename T>
        T getProcAddress(const char* name) const noexcept
        {
#if OUZEL_OPENGL_INTERFACE_EGL
            return reinterpret_cast<T>(eglGetProcAddress(name));
#elif OUZEL_OPENGL_INTERFACE_WGL
            return reinterpret_cast<T>(wglGetProcAddress(name));
#else
            return reinterpret_cast<T>(reinterpret_cast<std::uintptr_t>(dlsym(RTLD_DEFAULT, name)));
#endif
        }

        ApiVersion apiVersion;
        std::vector<std::string> extensions;
#if OUZEL_OPENGL_INTERFACE_WGL
        platform::winapi::Library library{"opengl32.dll"};
#endif
    };
}
#endif

#endif // OUZEL_GRAPHICS_OGLPROCEDUREGETTER_HPP
<commit_msg>Use structured bindings for procedure getter<commit_after>// Ouzel by Elviss Strazdins

#ifndef OUZEL_GRAPHICS_OGLPROCEDUREGETTER_HPP
#define OUZEL_GRAPHICS_OGLPROCEDUREGETTER_HPP

#include "../../core/Setup.h"

#if OUZEL_COMPILE_OPENGL

#include <algorithm>
#include <stdexcept>

#include "OGL.h"

#if OUZEL_OPENGLES
#  include "GLES/gl.h"
#  include "GLES2/gl2.h"
#  include "GLES2/gl2ext.h"
#  include "GLES3/gl3.h"
#else
#  include "GL/glcorearb.h"
#  include "GL/glext.h"
#endif

#if OUZEL_OPENGL_INTERFACE_EGL
#  include "EGL/egl.h"
#elif OUZEL_OPENGL_INTERFACE_WGL
#  include "GL/wglext.h"
#  include "../../platform/winapi/Library.hpp"
#endif

#include "../../core/Engine.hpp"
#include "../../utils/Utils.hpp"

namespace ouzel::graphics::opengl
{
    class ProcedureGetter final
    {
    public:
        ProcedureGetter(ApiVersion version):
            apiVersion{version}
        {
            const auto glGetErrorProc = getProcAddress<PFNGLGETERRORPROC>("glGetError", ApiVersion{1, 0});

            if (apiVersion >= ApiVersion{3, 0})
            {
                const auto glGetIntegervProc = getProcAddress<PFNGLGETINTEGERVPROC>("glGetIntegerv", ApiVersion{1, 0});
                const auto glGetStringiProc = getProcAddress<PFNGLGETSTRINGIPROC>("glGetStringi", ApiVersion{3, 0});

                GLint extensionCount;
                glGetIntegervProc(GL_NUM_EXTENSIONS, &extensionCount);

                if (const auto error = glGetErrorProc(); error != GL_NO_ERROR)
                    logger.log(Log::Level::warning) << "Failed to get OpenGL extension count, error: " + std::to_string(error);
                else
                    for (GLuint i = 0; i < static_cast<GLuint>(extensionCount); ++i)
                    {
                        const auto extensionPtr = glGetStringiProc(GL_EXTENSIONS, i);

                        if (const auto getStringError = glGetErrorProc(); getStringError != GL_NO_ERROR)
                            logger.log(Log::Level::warning) << "Failed to get OpenGL extension, error: " + std::to_string(getStringError);
                        else if (!extensionPtr)
                            logger.log(Log::Level::warning) << "Failed to get OpenGL extension";
                        else
                            extensions.emplace_back(reinterpret_cast<const char*>(extensionPtr));
                    }
            }
            else
            {
                const auto glGetStringProc = getProcAddress<PFNGLGETSTRINGPROC>("glGetString", ApiVersion{1, 0});
                const auto extensionsPtr = glGetStringProc(GL_EXTENSIONS);

                if (const auto error = glGetErrorProc(); error != GL_NO_ERROR)
                    logger.log(Log::Level::warning) << "Failed to get OpenGL extensions, error: " + std::to_string(error);
                else if (!extensionsPtr)
                    logger.log(Log::Level::warning) << "Failed to get OpenGL extensions";
                else
                    extensions = explodeString(reinterpret_cast<const char*>(extensionsPtr), ' ');
            }

            logger.log(Log::Level::all) << "Supported OpenGL extensions: " << extensions;
        }

        template <typename T>
        T get(const char* name, ApiVersion procApiVersion) const noexcept
        {
            return (apiVersion >= procApiVersion) ? getProcAddress<T>(name, procApiVersion) : nullptr;
        }

        template <typename T>
        T get(const char* name, const char* extension) const noexcept
        {
            return hasExtension(extension) ? getProcAddress<T>(name) : nullptr;
        }

        template <typename T>
        T get(const char* name,
              ApiVersion procApiVersion,
              const std::map<const char*, const char*>& procExtensions) const noexcept
        {
            if (apiVersion >= procApiVersion)
                return getProcAddress<T>(name, procApiVersion);
            else
                for (const auto [procName, extension] : procExtensions)
                    if (auto result = get<T>(procName, extension))
                        return result;

            return nullptr;
        }

        bool hasExtension(const char* ext) const noexcept
        {
            return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
        }

    private:
        template <typename T>
        T getProcAddress(const char* name, ApiVersion procApiVersion) const noexcept
        {
#if OUZEL_OPENGL_INTERFACE_EGL
#  if OUZEL_OPENGLES
            return procApiVersion >= ApiVersion{3, 0} ?
                reinterpret_cast<T>(eglGetProcAddress(name)) :
                reinterpret_cast<T>(reinterpret_cast<std::uintptr_t>(dlsym(RTLD_DEFAULT, name)));
#  else
            (void)procApiVersion;
            return reinterpret_cast<T>(eglGetProcAddress(name));
#  endif
#elif OUZEL_OPENGL_INTERFACE_WGL
            return procApiVersion > ApiVersion{1, 1} ?
                reinterpret_cast<T>(wglGetProcAddress(name)) :
                reinterpret_cast<T>(GetProcAddress(library.get(), name));
#else
            (void)procApiVersion;
            return reinterpret_cast<T>(reinterpret_cast<std::uintptr_t>(dlsym(RTLD_DEFAULT, name)));
#endif
        }

        template <typename T>
        T getProcAddress(const char* name) const noexcept
        {
#if OUZEL_OPENGL_INTERFACE_EGL
            return reinterpret_cast<T>(eglGetProcAddress(name));
#elif OUZEL_OPENGL_INTERFACE_WGL
            return reinterpret_cast<T>(wglGetProcAddress(name));
#else
            return reinterpret_cast<T>(reinterpret_cast<std::uintptr_t>(dlsym(RTLD_DEFAULT, name)));
#endif
        }

        ApiVersion apiVersion;
        std::vector<std::string> extensions;
#if OUZEL_OPENGL_INTERFACE_WGL
        platform::winapi::Library library{"opengl32.dll"};
#endif
    };
}
#endif

#endif // OUZEL_GRAPHICS_OGLPROCEDUREGETTER_HPP
<|endoftext|>


<commit_before>#include "multiverso/server.h"

#include <algorithm>
#include <sstream>
#include <string>
#include <vector>

#include "multiverso/actor.h"
#include "multiverso/dashboard.h"
#include "multiverso/multiverso.h"
#include "multiverso/table_interface.h"
#include "multiverso/io/io.h"
#include "multiverso/util/configure.h"
#include "multiverso/util/mt_queue.h"
#include "multiverso/zoo.h"

namespace multiverso {

MV_DEFINE_bool(sync, false, "sync or async");
MV_DEFINE_int(backup_worker_ratio, 0, "ratio% of backup workers, set 20 means 20%");

Server::Server() : Actor(actor::kServer) {
  RegisterHandler(MsgType::Request_Get, std::bind(
    &Server::ProcessGet, this, std::placeholders::_1));
  RegisterHandler(MsgType::Request_Add, std::bind(
    &Server::ProcessAdd, this, std::placeholders::_1));
}

int Server::RegisterTable(ServerTable* server_table) {
  int id = static_cast<int>(store_.size());
  store_.push_back(server_table);
  return id;
}

void Server::ProcessGet(MessagePtr& msg) {
  MONITOR_BEGIN(SERVER_PROCESS_GET);
  if (msg->data().size() != 0) {
    MessagePtr reply(msg->CreateReplyMessage());
    int table_id = msg->table_id();
    CHECK(table_id >= 0 && table_id < store_.size());
    store_[table_id]->ProcessGet(msg->data(), &reply->data());
    SendTo(actor::kCommunicator, reply);
  }
  MONITOR_END(SERVER_PROCESS_GET);
}

void Server::ProcessAdd(MessagePtr& msg) {
  MONITOR_BEGIN(SERVER_PROCESS_ADD)
  if (msg->data().size() != 0) {
    MessagePtr reply(msg->CreateReplyMessage());
    int table_id = msg->table_id();
    CHECK(table_id >= 0 && table_id < store_.size());
    store_[table_id]->ProcessAdd(msg->data());
    SendTo(actor::kCommunicator, reply);
  }
  MONITOR_END(SERVER_PROCESS_ADD)
}

// The Sync Server implement logic to support Sync SGD training
// The implementation assumes all the workers will call same number
// of Add and/or Get requests
// The server promise all workers i-th Get will get the same parameters
// If worker k has add delta to server j times when its i-th Get
// then the server will return the parameter after all K
// workers finished their j-th update

class SyncServer : public Server {
public:
  SyncServer() : Server() {
    RegisterHandler(MsgType::Server_Finish_Train, std::bind(
      &SyncServer::ProcessFinishTrain, this, std::placeholders::_1));
    int num_worker = Zoo::Get()->num_workers();
    worker_get_clocks_.reset(new VectorClock(num_worker));
    worker_add_clocks_.reset(new VectorClock(num_worker));
  }

  // make some modification to suit to the sync server
  // please not use in other place, may different with the general vector clock
  class VectorClock {
  public:
    explicit VectorClock(int n) :
      local_clock_(n, 0), global_clock_(0), size_(0) {}

    static bool except_max_int_compare(int a, int b) {
      return (b == std::numeric_limits<int>::max() ? false : a < b);
    }

    // Return true when all clock reach a same number
    virtual bool Update(int i) {
      ++local_clock_[i];
      if (global_clock_ < *(std::min_element(std::begin(local_clock_),
        std::end(local_clock_)))) {
        ++global_clock_;
        if (global_clock_ == *(std::max_element(std::begin(local_clock_),
          std::end(local_clock_), except_max_int_compare))) {
          return true;
        }
      }
      return false;
    }

    virtual bool FinishTrain(int i) {
      local_clock_[i] = std::numeric_limits<int>::max();
      if (global_clock_ < *(std::min_element(std::begin(local_clock_),
        std::end(local_clock_)))) {
        ++global_clock_;
        if (global_clock_ == *(std::max_element(std::begin(local_clock_),
          std::end(local_clock_), except_max_int_compare))) {
          return true;
        }
      }
      return false;
    }

    std::string DebugString() {
      std::string os = "global ";
      os += std::to_string(global_clock_) + " local: ";
      for (auto i : local_clock_) os += std::to_string(i) + " ";
      return os;
    }

    int local_clock(int i) const { return local_clock_[i]; }
    int global_clock() const { return global_clock_; }

  protected:
    std::vector<int> local_clock_;
    int global_clock_;
    int size_;
  };
protected:
  void ProcessAdd(MessagePtr& msg) override {
    // 1. Before add: cache faster worker
    int worker = Zoo::Get()->rank_to_worker_id(msg->src());
    if (worker_get_clocks_->local_clock(worker) >
        worker_get_clocks_->global_clock()) {
      msg_add_cache_.Push(msg);
      return;
    }
    // 2. Process Add
    Server::ProcessAdd(msg);
    // 3. After add: process cached process get if necessary
    if (worker_add_clocks_->Update(worker)) {
      CHECK(msg_add_cache_.Empty());
      while (!msg_get_cache_.Empty()) {
        MessagePtr get_msg;
        CHECK(msg_get_cache_.TryPop(get_msg));
        int get_worker = Zoo::Get()->rank_to_worker_id(get_msg->src());
        Server::ProcessGet(get_msg);
        CHECK(!worker_get_clocks_->Update(get_worker));
      }
    }
  }

  void ProcessGet(MessagePtr& msg) override {
    // 1. Before get: cache faster worker
    int worker = Zoo::Get()->rank_to_worker_id(msg->src());
    if (worker_add_clocks_->local_clock(worker) >
        worker_add_clocks_->global_clock() ||
        worker_get_clocks_->local_clock(worker) >
        worker_get_clocks_->global_clock()) {
      // Will wait for other worker finished Add
      msg_get_cache_.Push(msg);
      return;
    }
    // 2. Process Get
    Server::ProcessGet(msg);
    // 3. After get: process cached process add if necessary
    if (worker_get_clocks_->Update(worker)) {
      while (!msg_add_cache_.Empty()) {
        MessagePtr add_msg;
        CHECK(msg_add_cache_.TryPop(add_msg));
        int add_worker = Zoo::Get()->rank_to_worker_id(add_msg->src());
        Server::ProcessAdd(add_msg);
        CHECK(!worker_add_clocks_->Update(add_worker));
      }
    }
  }

  void ProcessFinishTrain(MessagePtr& msg) {
    int worker = Zoo::Get()->rank_to_worker_id(msg->src());
    Log::Debug("[ProcessFinishTrain] Server %d, worker %d has finished training.\n",
               Zoo::Get()->server_rank(), worker);
    if (worker_get_clocks_->FinishTrain(worker)) {
      CHECK(msg_get_cache_.Empty());
      while (!msg_add_cache_.Empty()) {
        MessagePtr add_msg;
        CHECK(msg_add_cache_.TryPop(add_msg));
        int add_worker = Zoo::Get()->rank_to_worker_id(add_msg->src());
        Server::ProcessAdd(add_msg);
        worker_add_clocks_->Update(add_worker);
      }
    }
    if (worker_add_clocks_->FinishTrain(worker)) {
      CHECK(msg_add_cache_.Empty());
      while (!msg_get_cache_.Empty()) {
        MessagePtr get_msg;
        CHECK(msg_get_cache_.TryPop(get_msg));
        int get_worker = Zoo::Get()->rank_to_worker_id(get_msg->src());
        Server::ProcessGet(get_msg);
        worker_get_clocks_->Update(get_worker);
      }
    }
  }

private:
  std::unique_ptr<VectorClock> worker_get_clocks_;
  std::unique_ptr<VectorClock> worker_add_clocks_;

  MtQueue<MessagePtr> msg_add_cache_;
  MtQueue<MessagePtr> msg_get_cache_;
};

Server* Server::GetServer() {
  if (!MV_CONFIG_sync) {
    Log::Info("Create a async server\n");
    return new Server();
  }
  // if (MV_CONFIG_backup_worker_ratio > 0.0) {
  Log::Info("Create a sync server\n");
  return new SyncServer();
  // }
}

}  // namespace multiverso
<commit_msg>fix sync server bug<commit_after>#include "multiverso/server.h"

#include <algorithm>
#include <sstream>
#include <string>
#include <vector>

#include "multiverso/actor.h"
#include "multiverso/dashboard.h"
#include "multiverso/multiverso.h"
#include "multiverso/table_interface.h"
#include "multiverso/io/io.h"
#include "multiverso/util/configure.h"
#include "multiverso/util/mt_queue.h"
#include "multiverso/zoo.h"

namespace multiverso {

MV_DEFINE_bool(sync, false, "sync or async");
MV_DEFINE_int(backup_worker_ratio, 0, "ratio% of backup workers, set 20 means 20%");

Server::Server() : Actor(actor::kServer) {
  RegisterHandler(MsgType::Request_Get, std::bind(
    &Server::ProcessGet, this, std::placeholders::_1));
  RegisterHandler(MsgType::Request_Add, std::bind(
    &Server::ProcessAdd, this, std::placeholders::_1));
}

int Server::RegisterTable(ServerTable* server_table) {
  int id = static_cast<int>(store_.size());
  store_.push_back(server_table);
  return id;
}

void Server::ProcessGet(MessagePtr& msg) {
  MONITOR_BEGIN(SERVER_PROCESS_GET);
  if (msg->data().size() != 0) {
    MessagePtr reply(msg->CreateReplyMessage());
    int table_id = msg->table_id();
    CHECK(table_id >= 0 && table_id < store_.size());
    store_[table_id]->ProcessGet(msg->data(), &reply->data());
    SendTo(actor::kCommunicator, reply);
  }
  MONITOR_END(SERVER_PROCESS_GET);
}

void Server::ProcessAdd(MessagePtr& msg) {
  MONITOR_BEGIN(SERVER_PROCESS_ADD)
  if (msg->data().size() != 0) {
    MessagePtr reply(msg->CreateReplyMessage());
    int table_id = msg->table_id();
    CHECK(table_id >= 0 && table_id < store_.size());
    store_[table_id]->ProcessAdd(msg->data());
    SendTo(actor::kCommunicator, reply);
  }
  MONITOR_END(SERVER_PROCESS_ADD)
}

// The Sync Server implement logic to support Sync SGD training
// The implementation assumes all the workers will call same number
// of Add and/or Get requests
// The server promise all workers i-th Get will get the same parameters
// If worker k has add delta to server j times when its i-th Get
// then the server will return the parameter after all K
// workers finished their j-th update

class SyncServer : public Server {
public:
  SyncServer() : Server() {
    RegisterHandler(MsgType::Server_Finish_Train, std::bind(
      &SyncServer::ProcessFinishTrain, this, std::placeholders::_1));
    int num_worker = Zoo::Get()->num_workers();
    worker_get_clocks_.reset(new VectorClock(num_worker));
    worker_add_clocks_.reset(new VectorClock(num_worker));
    num_waited_add_.resize(num_worker, 0);
  }

  // make some modification to suit to the sync server
  // please not use in other place, may different with the general vector clock
  class VectorClock {
  public:
    explicit VectorClock(int n) :
      local_clock_(n, 0), global_clock_(0), size_(0) {}

    static bool except_max_int_compare(int a, int b) {
      return (b == std::numeric_limits<int>::max() ? false : a < b);
    }

    // Return true when all clock reach a same number
    virtual bool Update(int i) {
      ++local_clock_[i];
      if (global_clock_ < *(std::min_element(std::begin(local_clock_),
        std::end(local_clock_)))) {
        ++global_clock_;
        if (global_clock_ == *(std::max_element(std::begin(local_clock_),
          std::end(local_clock_), except_max_int_compare))) {
          return true;
        }
      }
      return false;
    }

    virtual bool FinishTrain(int i) {
      local_clock_[i] = std::numeric_limits<int>::max();
      if (global_clock_ < *(std::min_element(std::begin(local_clock_),
        std::end(local_clock_)))) {
        ++global_clock_;
        if (global_clock_ == *(std::max_element(std::begin(local_clock_),
          std::end(local_clock_), except_max_int_compare))) {
          return true;
        }
      }
      return false;
    }

    std::string DebugString() {
      std::string os = "global ";
      os += std::to_string(global_clock_) + " local: ";
      for (auto i : local_clock_) os += std::to_string(i) + " ";
      return os;
    }

    int local_clock(int i) const { return local_clock_[i]; }
    int global_clock() const { return global_clock_; }

  protected:
    std::vector<int> local_clock_;
    int global_clock_;
    int size_;
  };
protected:
  void ProcessAdd(MessagePtr& msg) override {
    // 1. Before add: cache faster worker
    int worker = Zoo::Get()->rank_to_worker_id(msg->src());
    if (worker_get_clocks_->local_clock(worker) >
        worker_get_clocks_->global_clock()) {
      msg_add_cache_.Push(msg);
      ++num_waited_add_[worker];
      return;
    }
    // 2. Process Add
    Server::ProcessAdd(msg);
    // 3. After add: process cached process get if necessary
    if (worker_add_clocks_->Update(worker)) {
      CHECK(msg_add_cache_.Empty());
      while (!msg_get_cache_.Empty()) {
        MessagePtr get_msg;
        CHECK(msg_get_cache_.TryPop(get_msg));
        int get_worker = Zoo::Get()->rank_to_worker_id(get_msg->src());
        Server::ProcessGet(get_msg);
        CHECK(!worker_get_clocks_->Update(get_worker));
      }
    }
  }

  void ProcessGet(MessagePtr& msg) override {
    // 1. Before get: cache faster worker
    int worker = Zoo::Get()->rank_to_worker_id(msg->src());
    if (worker_add_clocks_->local_clock(worker) >
        worker_add_clocks_->global_clock() ||
        num_waited_add_[worker] > 0) {
      // Will wait for other worker finished Add
      msg_get_cache_.Push(msg);
      return;
    }
    // 2. Process Get
    Server::ProcessGet(msg);
    // 3. After get: process cached process add if necessary
    if (worker_get_clocks_->Update(worker)) {
      while (!msg_add_cache_.Empty()) {
        MessagePtr add_msg;
        CHECK(msg_add_cache_.TryPop(add_msg));
        int add_worker = Zoo::Get()->rank_to_worker_id(add_msg->src());
        Server::ProcessAdd(add_msg);
        CHECK(!worker_add_clocks_->Update(add_worker));
        --num_waited_add_[add_worker];
      }
    }
  }

  void ProcessFinishTrain(MessagePtr& msg) {
    int worker = Zoo::Get()->rank_to_worker_id(msg->src());
    Log::Debug("[ProcessFinishTrain] Server %d, worker %d has finished training.\n",
               Zoo::Get()->server_rank(), worker);
    if (worker_get_clocks_->FinishTrain(worker)) {
      CHECK(msg_get_cache_.Empty());
      while (!msg_add_cache_.Empty()) {
        MessagePtr add_msg;
        CHECK(msg_add_cache_.TryPop(add_msg));
        int add_worker = Zoo::Get()->rank_to_worker_id(add_msg->src());
        Server::ProcessAdd(add_msg);
        worker_add_clocks_->Update(add_worker);
      }
    }
    if (worker_add_clocks_->FinishTrain(worker)) {
      CHECK(msg_add_cache_.Empty());
      while (!msg_get_cache_.Empty()) {
        MessagePtr get_msg;
        CHECK(msg_get_cache_.TryPop(get_msg));
        int get_worker = Zoo::Get()->rank_to_worker_id(get_msg->src());
        Server::ProcessGet(get_msg);
        worker_get_clocks_->Update(get_worker);
      }
    }
  }

private:
  std::unique_ptr<VectorClock> worker_get_clocks_;
  std::unique_ptr<VectorClock> worker_add_clocks_;
  std::vector<int> num_waited_add_;

  MtQueue<MessagePtr> msg_add_cache_;
  MtQueue<MessagePtr> msg_get_cache_;
};

Server* Server::GetServer() {
  if (!MV_CONFIG_sync) {
    Log::Info("Create a async server\n");
    return new Server();
  }
  // if (MV_CONFIG_backup_worker_ratio > 0.0) {
  Log::Info("Create a sync server\n");
  return new SyncServer();
  // }
}

}  // namespace multiverso
<|endoftext|>


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

namespace iox
{
namespace cxx
{
///@brief specialization for  uint8_t and int8_t is required  since uint8_t is unsigned char and int8_t is signed char
/// and stringstream will not convert these to string as it is already a character.
template <>
inline typename std::enable_if<!std::is_convertible<uint8_t, std::string>::value, std::string>::type
convert::toString(const uint8_t& t) noexcept
{
    return toString(static_cast<uint16_t>(t));
}

template <>
inline typename std::enable_if<!std::is_convertible<int8_t, std::string>::value, std::string>::type
convert::toString(const int8_t& t) noexcept
{
    return toString(static_cast<int16_t>(t));
}

template <typename Source>
inline typename std::enable_if<!std::is_convertible<Source, std::string>::value, std::string>::type
convert::toString(const Source& t) noexcept
{
    std::stringstream ss;
    ss << t;
    return ss.str();
}

template <typename Source>
inline typename std::enable_if<std::is_convertible<Source, std::string>::value, std::string>::type
convert::toString(const Source& t) noexcept
{
    return t;
}

template <typename Destination>
inline typename std::enable_if<std::is_convertible<const char*, Destination>::value, bool>::type
fromString(const char* v, Destination& dest) noexcept
{
    dest = Destination(v);
    return true;
}

template <>
inline bool convert::fromString<std::string>(const char* v, std::string& dest) noexcept
{
    dest = std::string(v);
    return true;
}

template <>
inline bool convert::fromString<char>(const char* v, char& dest) noexcept
{
    if (strlen(v) != 1u)
    {
        std::cerr << v << " is not a char" << std::endl;
        return false;
    }
    dest = v[0];
    return true;
}

template <>
inline bool convert::fromString<string<100>>(const char* v, string<100>& dest) noexcept
{
    dest = string<100>(TruncateToCapacity, v);
    return true;
}

inline bool convert::stringIsNumber(const char* v, const NumberType type) noexcept
{
    if (v[0] == '\0')
        return false;

    bool hasDot = false;

    for (uint32_t i = 0u; v[i] != '\0'; ++i)
    {
        if (v[i] >= 48 && v[i] <= 57) // 48 == ascii 0, 57 == ascii 9
        {
            continue;
        }
        else if (type != NumberType::UNSIGNED_INTEGER && i == 0u
                 && (v[i] == 43 || v[i] == 45)) // 43 == ascii +, 45 == ascii -
        {
            continue;
        }
        else if (type == NumberType::FLOAT && !hasDot && v[i] == 46) // 46 == ascii .
        {
            hasDot = true;
        }
        else
        {
            return false;
        }
    }

    return true;
}

inline bool convert::stringIsNumberWithErrorMessage(const char* v, const NumberType type) noexcept
{
    if (!stringIsNumber(v, type))
    {
        std::cerr << v << " is not ";
        switch (type)
        {
        case NumberType::FLOAT:
        {
            std::cerr << "a float";
            break;
        }
        case NumberType::INTEGER:
        {
            std::cerr << "a signed integer";
            break;
        }
        case NumberType::UNSIGNED_INTEGER:
        {
            std::cerr << "an unsigned integer";
            break;
        }
        }
        std::cerr << std::endl;
        return false;
    }
    return true;
}

template <>
inline bool convert::fromString<float>(const char* v, float& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::FLOAT))
    {
        return false;
    }

    return !posix::posixCall(strtof)(v, nullptr)
                .failureReturnValue(HUGE_VALF, -HUGE_VALF)
                .evaluate()
                .and_then([&](auto& r) { dest = r.value; })
                .has_error();
}

template <>
inline bool convert::fromString<double>(const char* v, double& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::FLOAT))
    {
        return false;
    }

    return !posix::posixCall(strtod)(v, nullptr)
                .failureReturnValue(HUGE_VAL, -HUGE_VAL)
                .evaluate()
                .and_then([&](auto& r) { dest = r.value; })
                .has_error();
}

template <>
inline bool convert::fromString<long double>(const char* v, long double& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::FLOAT))
    {
        return false;
    }

    return !posix::posixCall(strtold)(v, nullptr)
                .failureReturnValue(HUGE_VALL, -HUGE_VALL)
                .evaluate()
                .and_then([&](auto& r) { dest = r.value; })
                .has_error();
}

template <>
inline bool convert::fromString<uint64_t>(const char* v, uint64_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtoull)(v, nullptr, STRTOULL_BASE).failureReturnValue(ULLONG_MAX).evaluate();

    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<uint64_t>::max())
    {
        std::cerr << call->value << " too large, uint64_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<uint64_t>(call->value);
    return true;
}

#ifdef __APPLE__
/// introduced for mac os since unsigned long is not uint64_t despite it has the same size
/// who knows why ¯\_(ツ)_/¯
template <>
inline bool convert::fromString<unsigned long>(const char* v, unsigned long& dest) noexcept
{
    uint64_t temp{0};
    bool retVal = fromString(v, temp);
    dest = temp;
    return retVal;
}
#endif

template <>
inline bool convert::fromString<uint32_t>(const char* v, uint32_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtoull)(v, nullptr, STRTOULL_BASE).failureReturnValue(ULLONG_MAX).evaluate();

    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<uint32_t>::max())
    {
        std::cerr << call->value << " too large, uint32_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<uint32_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<uint16_t>(const char* v, uint16_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtoul)(v, nullptr, STRTOULL_BASE).failureReturnValue(ULONG_MAX).evaluate();

    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<uint16_t>::max())
    {
        std::cerr << call->value << " too large, uint16_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<uint16_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<uint8_t>(const char* v, uint8_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtoul)(v, nullptr, STRTOULL_BASE).failureReturnValue(ULONG_MAX).evaluate();

    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<uint8_t>::max())
    {
        std::cerr << call->value << " too large, uint8_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<uint8_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<int64_t>(const char* v, int64_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::INTEGER))
    {
        return false;
    }

    auto call =
        posix::posixCall(strtoll)(v, nullptr, STRTOULL_BASE).failureReturnValue(LLONG_MAX, LLONG_MIN).evaluate();
    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<int64_t>::max() || call->value < std::numeric_limits<int64_t>::min())
    {
        std::cerr << call->value << " is out of range, int64_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<int64_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<int32_t>(const char* v, int32_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::INTEGER))
    {
        return false;
    }

    auto call =
        posix::posixCall(strtoll)(v, nullptr, STRTOULL_BASE).failureReturnValue(LLONG_MAX, LLONG_MIN).evaluate();
    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<int32_t>::max() || call->value < std::numeric_limits<int32_t>::min())
    {
        std::cerr << call->value << " is out of range, int32_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<int32_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<int16_t>(const char* v, int16_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtol)(v, nullptr, STRTOULL_BASE).failureReturnValue(LONG_MAX, LONG_MIN).evaluate();
    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<int16_t>::max() || call->value < std::numeric_limits<int16_t>::min())
    {
        std::cerr << call->value << " is out of range, int16_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<int16_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<int8_t>(const char* v, int8_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtol)(v, nullptr, STRTOULL_BASE).failureReturnValue(LONG_MAX, LONG_MIN).evaluate();
    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<int8_t>::max() || call->value < std::numeric_limits<int8_t>::min())
    {
        std::cerr << call->value << " is out of range, int8_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<int8_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<bool>(const char* v, bool& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    return !posix::posixCall(strtoul)(v, nullptr, STRTOULL_BASE)
                .failureReturnValue(ULONG_MAX)
                .evaluate()
                .and_then([&](auto& r) { dest = static_cast<bool>(r.value); })
                .has_error();
}

} // namespace cxx
} // namespace iox

#endif // IOX_HOOFS_CXX_CONVERT_INL
<commit_msg>iox-#1196 Fix warnings in convert inl<commit_after>// Copyright (c) 2019, 2021 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_HOOFS_CXX_CONVERT_INL
#define IOX_HOOFS_CXX_CONVERT_INL

#include "iceoryx_hoofs/cxx/convert.hpp"

namespace iox
{
namespace cxx
{
///@brief specialization for  uint8_t and int8_t is required  since uint8_t is unsigned char and int8_t is signed char
/// and stringstream will not convert these to string as it is already a character.
template <>
inline typename std::enable_if<!std::is_convertible<uint8_t, std::string>::value, std::string>::type
convert::toString(const uint8_t& t) noexcept
{
    return toString(static_cast<uint16_t>(t));
}

template <>
inline typename std::enable_if<!std::is_convertible<int8_t, std::string>::value, std::string>::type
convert::toString(const int8_t& t) noexcept
{
    return toString(static_cast<int16_t>(t));
}

template <typename Source>
inline typename std::enable_if<!std::is_convertible<Source, std::string>::value, std::string>::type
convert::toString(const Source& t) noexcept
{
    std::stringstream ss;
    ss << t;
    return ss.str();
}

template <typename Source>
inline typename std::enable_if<std::is_convertible<Source, std::string>::value, std::string>::type
convert::toString(const Source& t) noexcept
{
    return t;
}

template <typename Destination>
inline typename std::enable_if<std::is_convertible<const char*, Destination>::value, bool>::type
fromString(const char* v, Destination& dest) noexcept
{
    dest = Destination(v);
    return true;
}

template <>
inline bool convert::fromString<std::string>(const char* v, std::string& dest) noexcept
{
    dest = std::string(v);
    return true;
}

template <>
inline bool convert::fromString<char>(const char* v, char& dest) noexcept
{
    if (strlen(v) != 1U)
    {
        std::cerr << v << " is not a char" << std::endl;
        return false;
    }

    /// @NOLINTJUSTIFICATION encapsulated in abstraction
    /// @NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    dest = v[0];
    return true;
}

/// @NOLINTJUSTIFICATION iox-#1196 todo convert must be refactored
/// @NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
template <>
inline bool convert::fromString<string<100>>(const char* v, string<100>& dest) noexcept
{
    dest = string<100>(TruncateToCapacity, v);
    return true;
}
/// @NOLINTEND(cppcoreguidelines-avoid-magic-numbers)

inline bool convert::stringIsNumber(const char* v, const NumberType type) noexcept
{
    /// @NOLINTJUSTIFICATION encapsulated in abstraction
    /// @NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    if (v[0] == '\0')
    {
        return false;
    }

    bool hasDot = false;

    for (uint32_t i = 0U; v[i] != '\0'; ++i)
    {
        if (v[i] >= '0' && v[i] <= '9')
        {
            continue;
        }

        if (type != NumberType::UNSIGNED_INTEGER && i == 0U && (v[i] == '+' || v[i] == '-'))
        {
            continue;
        }

        if (type == NumberType::FLOAT && !hasDot && v[i] == '.')
        {
            hasDot = true;
        }
        else
        {
            return false;
        }
    }
    /// @NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)

    return true;
}

inline bool convert::stringIsNumberWithErrorMessage(const char* v, const NumberType type) noexcept
{
    if (!stringIsNumber(v, type))
    {
        std::cerr << v << " is not ";
        switch (type)
        {
        case NumberType::FLOAT:
        {
            std::cerr << "a float";
            break;
        }
        case NumberType::INTEGER:
        {
            std::cerr << "a signed integer";
            break;
        }
        case NumberType::UNSIGNED_INTEGER:
        {
            std::cerr << "an unsigned integer";
            break;
        }
        }
        std::cerr << std::endl;
        return false;
    }
    return true;
}

template <>
inline bool convert::fromString<float>(const char* v, float& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::FLOAT))
    {
        return false;
    }

    return !posix::posixCall(strtof)(v, nullptr)
                .failureReturnValue(HUGE_VALF, -HUGE_VALF)
                .evaluate()
                .and_then([&](auto& r) { dest = r.value; })
                .has_error();
}

template <>
inline bool convert::fromString<double>(const char* v, double& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::FLOAT))
    {
        return false;
    }

    return !posix::posixCall(strtod)(v, nullptr)
                .failureReturnValue(HUGE_VAL, -HUGE_VAL)
                .evaluate()
                .and_then([&](auto& r) { dest = r.value; })
                .has_error();
}

template <>
inline bool convert::fromString<long double>(const char* v, long double& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::FLOAT))
    {
        return false;
    }

    return !posix::posixCall(strtold)(v, nullptr)
                .failureReturnValue(HUGE_VALL, -HUGE_VALL)
                .evaluate()
                .and_then([&](auto& r) { dest = r.value; })
                .has_error();
}

template <>
inline bool convert::fromString<uint64_t>(const char* v, uint64_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtoull)(v, nullptr, STRTOULL_BASE).failureReturnValue(ULLONG_MAX).evaluate();

    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<uint64_t>::max())
    {
        std::cerr << call->value << " too large, uint64_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<uint64_t>(call->value);
    return true;
}

#ifdef __APPLE__
/// introduced for mac os since unsigned long is not uint64_t despite it has the same size
/// who knows why ¯\_(ツ)_/¯
template <>
inline bool convert::fromString<unsigned long>(const char* v, unsigned long& dest) noexcept
{
    uint64_t temp{0};
    bool retVal = fromString(v, temp);
    dest = temp;
    return retVal;
}
#endif

template <>
inline bool convert::fromString<uint32_t>(const char* v, uint32_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtoull)(v, nullptr, STRTOULL_BASE).failureReturnValue(ULLONG_MAX).evaluate();

    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<uint32_t>::max())
    {
        std::cerr << call->value << " too large, uint32_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<uint32_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<uint16_t>(const char* v, uint16_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtoul)(v, nullptr, STRTOULL_BASE).failureReturnValue(ULONG_MAX).evaluate();

    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<uint16_t>::max())
    {
        std::cerr << call->value << " too large, uint16_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<uint16_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<uint8_t>(const char* v, uint8_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtoul)(v, nullptr, STRTOULL_BASE).failureReturnValue(ULONG_MAX).evaluate();

    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<uint8_t>::max())
    {
        std::cerr << call->value << " too large, uint8_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<uint8_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<int64_t>(const char* v, int64_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::INTEGER))
    {
        return false;
    }

    auto call =
        posix::posixCall(strtoll)(v, nullptr, STRTOULL_BASE).failureReturnValue(LLONG_MAX, LLONG_MIN).evaluate();
    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<int64_t>::max() || call->value < std::numeric_limits<int64_t>::min())
    {
        std::cerr << call->value << " is out of range, int64_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<int64_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<int32_t>(const char* v, int32_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::INTEGER))
    {
        return false;
    }

    auto call =
        posix::posixCall(strtoll)(v, nullptr, STRTOULL_BASE).failureReturnValue(LLONG_MAX, LLONG_MIN).evaluate();
    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<int32_t>::max() || call->value < std::numeric_limits<int32_t>::min())
    {
        std::cerr << call->value << " is out of range, int32_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<int32_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<int16_t>(const char* v, int16_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtol)(v, nullptr, STRTOULL_BASE).failureReturnValue(LONG_MAX, LONG_MIN).evaluate();
    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<int16_t>::max() || call->value < std::numeric_limits<int16_t>::min())
    {
        std::cerr << call->value << " is out of range, int16_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<int16_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<int8_t>(const char* v, int8_t& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::INTEGER))
    {
        return false;
    }

    auto call = posix::posixCall(strtol)(v, nullptr, STRTOULL_BASE).failureReturnValue(LONG_MAX, LONG_MIN).evaluate();
    if (call.has_error())
    {
        return false;
    }

    if (call->value > std::numeric_limits<int8_t>::max() || call->value < std::numeric_limits<int8_t>::min())
    {
        std::cerr << call->value << " is out of range, int8_t overflow" << std::endl;
        return false;
    }

    dest = static_cast<int8_t>(call->value);
    return true;
}

template <>
inline bool convert::fromString<bool>(const char* v, bool& dest) noexcept
{
    if (!stringIsNumberWithErrorMessage(v, NumberType::UNSIGNED_INTEGER))
    {
        return false;
    }

    return !posix::posixCall(strtoul)(v, nullptr, STRTOULL_BASE)
                .failureReturnValue(ULONG_MAX)
                .evaluate()
                .and_then([&](auto& r) { dest = static_cast<bool>(r.value); })
                .has_error();
}

} // namespace cxx
} // namespace iox

#endif // IOX_HOOFS_CXX_CONVERT_INL
<|endoftext|>


<commit_before>/* based on http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/example/cpp03/echo/blocking_tcp_echo_client.cpp */

#include <iostream>
#include <boost/asio.hpp>
#include "../HttpParser.hpp"

using boost::asio::ip::tcp;
using namespace http;

int main(int argc, char* argv[])
{
	try {
		if (argc != 2) {
			std::cerr << "Usage: " << argv[0] << " <URL>" << std::endl;
			return 1;
		}

		Url url;
		bool urlParsedOk = false;
		try {
			url = parseUrl(argv[1]);
			urlParsedOk = true;
		} catch (const UrlParseError&) {
		}
		if (!urlParsedOk || url.host.empty()) {
			std::cerr << "This does not appear to be a valid URL of a HTTP resource: "
			<< argv[1] << std::endl;
			return 1;
		}
		if (url.schema != "http") {
			std::cerr << "This program only supports plain HTTP." << std::endl;
			return 1;
		}
		if (0 == url.port) { // no port specified explicitly in the URL
			url.port = 80; // good as long as we only support http://
		}
		//std::cout << url << std::endl;

		std::ostringstream ss;
		ss << "GET " << url.path;
		if (!url.query.empty()) {
			ss << '?' << url.query;
		}
		ss << " HTTP/1.1\r\n"
				<< "Host: " << url.host << "\r\n"
				<< "Connection: close\r\n"
				<< "\r\n";
		const std::string request = ss.str();
		std::cout << request << std::endl;

		boost::asio::io_service ioService;

		tcp::resolver resolver(ioService);
		tcp::resolver::query query(tcp::v4(), url.host, std::to_string(url.port));
		tcp::resolver::iterator it = resolver.resolve(query);

		tcp::socket socket(ioService);
		std::cout << "Connecting to " << url.host << ':' << url.port << "... "
				<< std::flush;
		boost::asio::connect(socket, it);
		std::cout << "done\nSending request." << std::endl;
		boost::asio::write(socket, boost::asio::buffer(request));

		std::cout << "Reading response." << std::endl;
		// TODO: use BigResponseParser to save the response body to a file.
		// TODO: determine file name (may want to get response headers first
		char reply[2048];
		size_t reply_length = boost::asio::read(socket,
				boost::asio::buffer(reply, sizeof(reply)));
		std::cout << "Reply is:\n";
		std::cout.write(reply, reply_length);
		std::cout << "\n";
	} catch (const std::runtime_error &e) {
		std::cerr << "Interrupted by exception: " << e.what() << std::endl;
		return 1;
	}
	return 0;
}
<commit_msg>Still working on the BigResponseParser usage example<commit_after>/* based on http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/example/cpp03/echo/blocking_tcp_echo_client.cpp */

#include <iostream>
#include <fstream>
#include <libgen.h> /* for basename */
#include <boost/asio.hpp>
#include "../HttpParser.hpp"

using boost::asio::ip::tcp;
using namespace http;

std::string determineFileName(const std::string& urlPath,
		const http::Response& response)
{
	// TODO this obviously needs refinement
	return basename((char*) urlPath.c_str());
}

int main(int argc, char* argv[])
{
	try {
		if (argc != 2) {
			std::cerr << "Usage: " << argv[0] << " <URL>" << std::endl;
			return 1;
		}

		Url url;
		bool urlParsedOk = false;
		try {
			url = parseUrl(argv[1]);
			urlParsedOk = true;
		} catch (const UrlParseError&) {
		}
		if (!urlParsedOk || url.host.empty()) {
			std::cerr << "This does not appear to be a valid URL of a HTTP resource: "
			<< argv[1] << std::endl;
			return 1;
		}
		if (url.schema != "http") {
			std::cerr << "This program only supports plain HTTP." << std::endl;
			return 1;
		}
		if (0 == url.port) { // no port specified explicitly in the URL
			url.port = 80; // good as long as we only support http://
		}

		std::ostringstream ss;
		ss << "GET " << url.path;
		if (!url.query.empty()) {
			ss << '?' << url.query;
		}
		ss << " HTTP/1.1\r\n"
				<< "Host: " << url.host << "\r\n"
				<< "Connection: close\r\n"
				<< "\r\n";
		const std::string request = ss.str();
		std::cout << request << std::endl;

		boost::asio::io_service ioService;

		tcp::resolver resolver(ioService);
		tcp::resolver::query query(tcp::v4(), url.host, std::to_string(url.port));
		tcp::resolver::iterator it = resolver.resolve(query);

		tcp::socket socket(ioService);
		std::cout << "Connecting to " << url.host << ':' << url.port << "... "
				<< std::flush;
		boost::asio::connect(socket, it);
		std::cout << "done\nSending request." << std::endl;
		boost::asio::write(socket, boost::asio::buffer(request));

		std::cout << "Reading response." << std::endl;
		std::string fileName;
		std::ofstream outputFile;
		outputFile.exceptions(std::ofstream::failbit | std::ofstream::badbit);
		bool completed = false;
		auto myCallback = [&] (const http::Response& response,
				const char *bodyPart, std::size_t bodyPartLength, bool finished) {
			if (!outputFile.is_open()) {
				fileName = determineFileName(url.path, response);
				std::cout << "Saving to " << fileName << std::endl;
				outputFile.open(fileName,
						std::ios::out | std::ios::trunc | std::ios::binary);
			}
			outputFile.write(bodyPart, bodyPartLength);
			completed = finished;
			if (completed) {
				std::cout << "Done." << std::endl;
			}
		};
		http::BigResponseParser parser(myCallback);
		parser.setMaxHeadersLength(1024 * 1024);
		while (!completed) {
			boost::system::error_code ec;
			char reply[2048];
				size_t reply_length = boost::asio::read(socket,
						boost::asio::buffer(reply, sizeof(reply)), ec);
				if (!ec) {
					parser.feed(reply, reply_length);
				} else if (boost::asio::error::eof == ec) {
					parser.feed(reply, reply_length);
					parser.feedEof();
				} else {
					throw boost::system::system_error(ec);
				}
		}
	} catch (const std::runtime_error& e) {
		std::cerr << "Interrupted by exception: " << e.what() << std::endl;
		return 1;
	}
	return 0;
}
<|endoftext|>