<commit_before>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/focushandler.hpp"

#include "guichan/focuslistener.hpp"
#include "guichan/exception.hpp"
#include "guichan/widget.hpp"

namespace gcn
{
    FocusHandler::FocusHandler()
    {
        mFocusedWidget = NULL;
        mToBeFocused = NULL;
        mModalFocusedWidget = NULL;
        mModalMouseInputFocusedWidget = NULL;
    }

    void FocusHandler::requestFocus(Widget* widget)
    {
        mToBeFocused = widget;
    }

    void FocusHandler::requestModalFocus(Widget* widget)
    {
        if (mModalFocusedWidget != NULL && mModalFocusedWidget != widget)
        {
            throw GCN_EXCEPTION("Another widget allready has modal focus.");
        }

        mModalFocusedWidget = widget;

        if (mFocusedWidget != NULL && !mFocusedWidget->hasModalFocus())
        {
            focusNone();
        }
    }

    void FocusHandler::requestModalMouseInputFocus(Widget* widget)
    {
        if (mModalMouseInputFocusedWidget != NULL
            && mModalMouseInputFocusedWidget != widget)
        {
            throw GCN_EXCEPTION("Another widget allready has modal input focus.");
        }

        mModalMouseInputFocusedWidget = widget;
    }

    void FocusHandler::releaseModalFocus(Widget* widget)
    {
        if (mModalFocusedWidget == widget)
        {
            mModalFocusedWidget = NULL;
        }
    }

    void FocusHandler::releaseModalMouseInputFocus(Widget* widget)
    {
        if (mModalMouseInputFocusedWidget == widget)
        {
            mModalMouseInputFocusedWidget = NULL;
        }
    }

    Widget* FocusHandler::getFocused() const
    {
        return mFocusedWidget;
    }

    Widget* FocusHandler::getModalFocused() const
    {
        return mModalFocusedWidget;
    }

    Widget* FocusHandler::getModalMouseInputFocused() const
    {
        return mModalMouseInputFocusedWidget;
    }

    void FocusHandler::focusNext()
    {
        int i;
        int focusedWidget = -1;
        for (i = 0; i < (int)mWidgets.size(); ++i)
        {
            if (mWidgets[i] == mFocusedWidget)
            {
                focusedWidget = i;
            }
        }
        int focused = focusedWidget;

        // i is a counter that ensures that the following loop
        // won't get stuck in an infinite loop
        i = (int)mWidgets.size();
        do
        {
            ++focusedWidget;

            if (i==0)
            {
                focusedWidget = -1;
                break;
            }

            --i;

            if (focusedWidget >= (int)mWidgets.size())
            {
                focusedWidget = 0;
            }

            if (focusedWidget == focused)
            {
                return;
            }
        }
        while (!mWidgets.at(focusedWidget)->isFocusable());

        if (focusedWidget >= 0)
        {
            mFocusedWidget = mWidgets.at(focusedWidget);

            Event focusEvent(mFocusedWidget);
            distributeFocusGainedEvent(focusEvent);
            //mWidgets.at(focusedWidget)->focusGained();
        }

        if (focused >= 0)
        {
            Event focusEvent(mWidgets.at(focused));
            distributeFocusLostEvent(focusEvent);
           // mWidgets.at(focused)->focusLost();
        }
    }

    void FocusHandler::focusPrevious()
    {
        if (mWidgets.size() == 0)
        {
            mFocusedWidget = NULL;
            return;
        }

        int i;
        int focusedWidget = -1;
        for (i = 0; i < (int)mWidgets.size(); ++i)
        {
            if (mWidgets[i] == mFocusedWidget)
            {
                focusedWidget = i;
            }
        }
        int focused = focusedWidget;

        // i is a counter that ensures that the following loop
        // won't get stuck in an infinite loop
        i = (int)mWidgets.size();
        do
        {
            --focusedWidget;

            if (i==0)
            {
                focusedWidget = -1;
                break;
            }

            --i;

            if (focusedWidget <= 0)
            {
                focusedWidget = mWidgets.size() - 1;
            }

            if (focusedWidget == focused)
            {
                return;
            }
        }
        while (!mWidgets.at(focusedWidget)->isFocusable());

        if (focusedWidget >= 0)
        {
            mFocusedWidget = mWidgets.at(focusedWidget);
            Event focusEvent(mFocusedWidget);
            distributeFocusGainedEvent(focusEvent);
            //mWidgets.at(focusedWidget)->focusGained();
        }

        if (focused >= 0)
        {
            Event focusEvent(mWidgets.at(focused));
            distributeFocusLostEvent(focusEvent);
            //mWidgets.at(focused)->focusLost();
        }
    }

    bool FocusHandler::isFocused(const Widget* widget) const
    {
        return mFocusedWidget == widget;
    }

    void FocusHandler::add(Widget* widget)
    {
        mWidgets.push_back(widget);
    }

    void FocusHandler::remove(Widget* widget)
    {
        if (widget == mToBeFocused)
        {
            mToBeFocused = NULL;
        }

        if (isFocused(widget))
        {
            mFocusedWidget = NULL;
            mToBeFocused = NULL;
        }

        WidgetIterator iter;

        for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter)
        {
            if ((*iter) == widget)
            {
                mWidgets.erase(iter);
                return;
            }
        }
    }

    void FocusHandler::focusNone()
    {

        if (mFocusedWidget != NULL)
        {
            Widget* focused = mFocusedWidget;
            mFocusedWidget = NULL;

            Event focusEvent(focused);
            distributeFocusLostEvent(focusEvent);
            //focused->focusLost();
        }

        mToBeFocused = NULL;
    }

    void FocusHandler::tabNext()
    {
        if (mFocusedWidget != NULL)
        {
            if (!mFocusedWidget->isTabOutEnabled())
            {
                return;
            }
        }

        if (mWidgets.size() == 0)
        {
            mFocusedWidget = NULL;
            return;
        }

        int i;
        int focusedWidget = -1;
        for (i = 0; i < (int)mWidgets.size(); ++i)
        {
            if (mWidgets[i] == mFocusedWidget)
            {
                focusedWidget = i;
            }
        }
        int focused = focusedWidget;
        bool done = false;

        // i is a counter that ensures that the following loop
        // won't get stuck in an infinite loop
        i = (int)mWidgets.size();
        do
        {
            ++focusedWidget;

            if (i==0)
            {
                focusedWidget = -1;
                break;
            }

            --i;

            if (focusedWidget >= (int)mWidgets.size())
            {
                focusedWidget = 0;
            }

            if (focusedWidget == focused)
            {
                return;
            }

            if (mWidgets.at(focusedWidget)->isFocusable() &&
                mWidgets.at(focusedWidget)->isTabInEnabled() &&
                (mModalFocusedWidget == NULL ||
                 mWidgets.at(focusedWidget)->hasModalFocus()))
            {
                done = true;
            }
        }
        while (!done);

        if (focusedWidget >= 0)
        {
            mFocusedWidget = mWidgets.at(focusedWidget);
            Event focusEvent(mFocusedWidget);
            distributeFocusGainedEvent(focusEvent);
            //mWidgets.at(focusedWidget)->focusGained();
        }

        if (focused >= 0)
        {
            Event focusEvent(mWidgets.at(focused));
            distributeFocusLostEvent(focusEvent);
            //mWidgets.at(focused)->focusLost();
        }
    }

    void FocusHandler::tabPrevious()
    {
        if (mFocusedWidget != NULL)
        {
            if (!mFocusedWidget->isTabOutEnabled())
            {
                return;
            }
        }

        if (mWidgets.size() == 0)
        {
            mFocusedWidget = NULL;
            return;
        }

        int i;
        int focusedWidget = -1;
        for (i = 0; i < (int)mWidgets.size(); ++i)
        {
            if (mWidgets[i] == mFocusedWidget)
            {
                focusedWidget = i;
            }
        }
        int focused = focusedWidget;
        bool done = false;

        // i is a counter that ensures that the following loop
        // won't get stuck in an infinite loop
        i = (int)mWidgets.size();
        do
        {
            --focusedWidget;

            if (i==0)
            {
                focusedWidget = -1;
                break;
            }

            --i;

            if (focusedWidget <= 0)
            {
                focusedWidget = mWidgets.size() - 1;
            }

            if (focusedWidget == focused)
            {
                return;
            }

            if (mWidgets.at(focusedWidget)->isFocusable() &&
                mWidgets.at(focusedWidget)->isTabInEnabled() &&
                (mModalFocusedWidget == NULL ||
                 mWidgets.at(focusedWidget)->hasModalFocus()))
            {
                done = true;
            }
        }
        while (!done);

        if (focusedWidget >= 0)
        {
            mFocusedWidget = mWidgets.at(focusedWidget);
            Event focusEvent(mFocusedWidget);
            distributeFocusGainedEvent(focusEvent);
            //mWidgets.at(focusedWidget)->focusGained();
        }

        if (focused >= 0)
        {
            Event focusEvent(mWidgets.at(focused));
            distributeFocusLostEvent(focusEvent);
            //mWidgets.at(focused)->focusLost();
        }
    }

    void FocusHandler::applyChanges()
    {
        if (mToBeFocused == mFocusedWidget)
        {
            return;
        }

        if (mToBeFocused != NULL)
        {
            unsigned int i = 0;
            int toBeFocusedIndex = -1;
            for (i = 0; i < mWidgets.size(); ++i)
            {
                if (mWidgets[i] == mToBeFocused)
                {
                    toBeFocusedIndex = i;
                    break;
                }
            }

            if (toBeFocusedIndex < 0)
            {
                throw GCN_EXCEPTION("Trying to focus a none existing widget.");
            }

            Widget *oldFocused = mFocusedWidget;

            if (oldFocused != mToBeFocused)
            {
                mFocusedWidget = mWidgets.at(toBeFocusedIndex);

                if (oldFocused != NULL)
                {
                    Event focusEvent(oldFocused);
                    distributeFocusLostEvent(focusEvent);
                    //oldFocused->focusLost();
                }

                Event focusEvent(mWidgets.at(toBeFocusedIndex));
                distributeFocusGainedEvent(focusEvent);
                //mWidgets.at(toBeFocusedIndex)->focusGained();
            }

            mToBeFocused = NULL;
        }
    }

    void FocusHandler::distributeFocusLostEvent(const Event& focusEvent)
    {
        Widget* sourceWidget = focusEvent.getSource();

        std::list<FocusListener*> focusListeners = sourceWidget->_getFocusListeners();

        // Send the event to all focus listeners of the widget.
        for (std::list<FocusListener*>::iterator it = focusListeners.begin();
             it != focusListeners.end();
             ++it)
        {
            (*it)->focusLost(focusEvent);
        }
    }

    void FocusHandler::distributeFocusGainedEvent(const Event& focusEvent)
    {
        Widget* sourceWidget = focusEvent.getSource();

        std::list<FocusListener*> focusListeners = sourceWidget->_getFocusListeners();

        // Send the event to all focus listeners of the widget.
        for (std::list<FocusListener*>::iterator it = focusListeners.begin();
             it != focusListeners.end();
             ++it)
        {
            (*it)->focusGained(focusEvent);
        }
    }
}
<commit_msg>Out commented code has been removed.<commit_after>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/focushandler.hpp"

#include "guichan/focuslistener.hpp"
#include "guichan/exception.hpp"
#include "guichan/widget.hpp"

namespace gcn
{
    FocusHandler::FocusHandler()
    {
        mFocusedWidget = NULL;
        mToBeFocused = NULL;
        mModalFocusedWidget = NULL;
        mModalMouseInputFocusedWidget = NULL;
    }

    void FocusHandler::requestFocus(Widget* widget)
    {
        mToBeFocused = widget;
    }

    void FocusHandler::requestModalFocus(Widget* widget)
    {
        if (mModalFocusedWidget != NULL && mModalFocusedWidget != widget)
        {
            throw GCN_EXCEPTION("Another widget allready has modal focus.");
        }

        mModalFocusedWidget = widget;

        if (mFocusedWidget != NULL && !mFocusedWidget->hasModalFocus())
        {
            focusNone();
        }
    }

    void FocusHandler::requestModalMouseInputFocus(Widget* widget)
    {
        if (mModalMouseInputFocusedWidget != NULL
            && mModalMouseInputFocusedWidget != widget)
        {
            throw GCN_EXCEPTION("Another widget allready has modal input focus.");
        }

        mModalMouseInputFocusedWidget = widget;
    }

    void FocusHandler::releaseModalFocus(Widget* widget)
    {
        if (mModalFocusedWidget == widget)
        {
            mModalFocusedWidget = NULL;
        }
    }

    void FocusHandler::releaseModalMouseInputFocus(Widget* widget)
    {
        if (mModalMouseInputFocusedWidget == widget)
        {
            mModalMouseInputFocusedWidget = NULL;
        }
    }

    Widget* FocusHandler::getFocused() const
    {
        return mFocusedWidget;
    }

    Widget* FocusHandler::getModalFocused() const
    {
        return mModalFocusedWidget;
    }

    Widget* FocusHandler::getModalMouseInputFocused() const
    {
        return mModalMouseInputFocusedWidget;
    }

    void FocusHandler::focusNext()
    {
        int i;
        int focusedWidget = -1;
        for (i = 0; i < (int)mWidgets.size(); ++i)
        {
            if (mWidgets[i] == mFocusedWidget)
            {
                focusedWidget = i;
            }
        }
        int focused = focusedWidget;

        // i is a counter that ensures that the following loop
        // won't get stuck in an infinite loop
        i = (int)mWidgets.size();
        do
        {
            ++focusedWidget;

            if (i==0)
            {
                focusedWidget = -1;
                break;
            }

            --i;

            if (focusedWidget >= (int)mWidgets.size())
            {
                focusedWidget = 0;
            }

            if (focusedWidget == focused)
            {
                return;
            }
        }
        while (!mWidgets.at(focusedWidget)->isFocusable());

        if (focusedWidget >= 0)
        {
            mFocusedWidget = mWidgets.at(focusedWidget);

            Event focusEvent(mFocusedWidget);
            distributeFocusGainedEvent(focusEvent);
        }

        if (focused >= 0)
        {
            Event focusEvent(mWidgets.at(focused));
            distributeFocusLostEvent(focusEvent);
        }
    }

    void FocusHandler::focusPrevious()
    {
        if (mWidgets.size() == 0)
        {
            mFocusedWidget = NULL;
            return;
        }

        int i;
        int focusedWidget = -1;
        for (i = 0; i < (int)mWidgets.size(); ++i)
        {
            if (mWidgets[i] == mFocusedWidget)
            {
                focusedWidget = i;
            }
        }
        int focused = focusedWidget;

        // i is a counter that ensures that the following loop
        // won't get stuck in an infinite loop
        i = (int)mWidgets.size();
        do
        {
            --focusedWidget;

            if (i==0)
            {
                focusedWidget = -1;
                break;
            }

            --i;

            if (focusedWidget <= 0)
            {
                focusedWidget = mWidgets.size() - 1;
            }

            if (focusedWidget == focused)
            {
                return;
            }
        }
        while (!mWidgets.at(focusedWidget)->isFocusable());

        if (focusedWidget >= 0)
        {
            mFocusedWidget = mWidgets.at(focusedWidget);
            Event focusEvent(mFocusedWidget);
            distributeFocusGainedEvent(focusEvent);
        }

        if (focused >= 0)
        {
            Event focusEvent(mWidgets.at(focused));
            distributeFocusLostEvent(focusEvent);
        }
    }

    bool FocusHandler::isFocused(const Widget* widget) const
    {
        return mFocusedWidget == widget;
    }

    void FocusHandler::add(Widget* widget)
    {
        mWidgets.push_back(widget);
    }

    void FocusHandler::remove(Widget* widget)
    {
        if (widget == mToBeFocused)
        {
            mToBeFocused = NULL;
        }

        if (isFocused(widget))
        {
            mFocusedWidget = NULL;
            mToBeFocused = NULL;
        }

        WidgetIterator iter;

        for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter)
        {
            if ((*iter) == widget)
            {
                mWidgets.erase(iter);
                return;
            }
        }
    }

    void FocusHandler::focusNone()
    {

        if (mFocusedWidget != NULL)
        {
            Widget* focused = mFocusedWidget;
            mFocusedWidget = NULL;

            Event focusEvent(focused);
            distributeFocusLostEvent(focusEvent);
        }

        mToBeFocused = NULL;
    }

    void FocusHandler::tabNext()
    {
        if (mFocusedWidget != NULL)
        {
            if (!mFocusedWidget->isTabOutEnabled())
            {
                return;
            }
        }

        if (mWidgets.size() == 0)
        {
            mFocusedWidget = NULL;
            return;
        }

        int i;
        int focusedWidget = -1;
        for (i = 0; i < (int)mWidgets.size(); ++i)
        {
            if (mWidgets[i] == mFocusedWidget)
            {
                focusedWidget = i;
            }
        }
        int focused = focusedWidget;
        bool done = false;

        // i is a counter that ensures that the following loop
        // won't get stuck in an infinite loop
        i = (int)mWidgets.size();
        do
        {
            ++focusedWidget;

            if (i==0)
            {
                focusedWidget = -1;
                break;
            }

            --i;

            if (focusedWidget >= (int)mWidgets.size())
            {
                focusedWidget = 0;
            }

            if (focusedWidget == focused)
            {
                return;
            }

            if (mWidgets.at(focusedWidget)->isFocusable() &&
                mWidgets.at(focusedWidget)->isTabInEnabled() &&
                (mModalFocusedWidget == NULL ||
                 mWidgets.at(focusedWidget)->hasModalFocus()))
            {
                done = true;
            }
        }
        while (!done);

        if (focusedWidget >= 0)
        {
            mFocusedWidget = mWidgets.at(focusedWidget);
            Event focusEvent(mFocusedWidget);
            distributeFocusGainedEvent(focusEvent);
        }

        if (focused >= 0)
        {
            Event focusEvent(mWidgets.at(focused));
            distributeFocusLostEvent(focusEvent);
        }
    }

    void FocusHandler::tabPrevious()
    {
        if (mFocusedWidget != NULL)
        {
            if (!mFocusedWidget->isTabOutEnabled())
            {
                return;
            }
        }

        if (mWidgets.size() == 0)
        {
            mFocusedWidget = NULL;
            return;
        }

        int i;
        int focusedWidget = -1;
        for (i = 0; i < (int)mWidgets.size(); ++i)
        {
            if (mWidgets[i] == mFocusedWidget)
            {
                focusedWidget = i;
            }
        }
        int focused = focusedWidget;
        bool done = false;

        // i is a counter that ensures that the following loop
        // won't get stuck in an infinite loop
        i = (int)mWidgets.size();
        do
        {
            --focusedWidget;

            if (i==0)
            {
                focusedWidget = -1;
                break;
            }

            --i;

            if (focusedWidget <= 0)
            {
                focusedWidget = mWidgets.size() - 1;
            }

            if (focusedWidget == focused)
            {
                return;
            }

            if (mWidgets.at(focusedWidget)->isFocusable() &&
                mWidgets.at(focusedWidget)->isTabInEnabled() &&
                (mModalFocusedWidget == NULL ||
                 mWidgets.at(focusedWidget)->hasModalFocus()))
            {
                done = true;
            }
        }
        while (!done);

        if (focusedWidget >= 0)
        {
            mFocusedWidget = mWidgets.at(focusedWidget);
            Event focusEvent(mFocusedWidget);
            distributeFocusGainedEvent(focusEvent);
        }

        if (focused >= 0)
        {
            Event focusEvent(mWidgets.at(focused));
            distributeFocusLostEvent(focusEvent);
        }
    }

    void FocusHandler::applyChanges()
    {
        if (mToBeFocused == mFocusedWidget)
        {
            return;
        }

        if (mToBeFocused != NULL)
        {
            unsigned int i = 0;
            int toBeFocusedIndex = -1;
            for (i = 0; i < mWidgets.size(); ++i)
            {
                if (mWidgets[i] == mToBeFocused)
                {
                    toBeFocusedIndex = i;
                    break;
                }
            }

            if (toBeFocusedIndex < 0)
            {
                throw GCN_EXCEPTION("Trying to focus a none existing widget.");
            }

            Widget *oldFocused = mFocusedWidget;

            if (oldFocused != mToBeFocused)
            {
                mFocusedWidget = mWidgets.at(toBeFocusedIndex);

                if (oldFocused != NULL)
                {
                    Event focusEvent(oldFocused);
                    distributeFocusLostEvent(focusEvent);
                }

                Event focusEvent(mWidgets.at(toBeFocusedIndex));
                distributeFocusGainedEvent(focusEvent);
            }

            mToBeFocused = NULL;
        }
    }

    void FocusHandler::distributeFocusLostEvent(const Event& focusEvent)
    {
        Widget* sourceWidget = focusEvent.getSource();

        std::list<FocusListener*> focusListeners = sourceWidget->_getFocusListeners();

        // Send the event to all focus listeners of the widget.
        for (std::list<FocusListener*>::iterator it = focusListeners.begin();
             it != focusListeners.end();
             ++it)
        {
            (*it)->focusLost(focusEvent);
        }
    }

    void FocusHandler::distributeFocusGainedEvent(const Event& focusEvent)
    {
        Widget* sourceWidget = focusEvent.getSource();

        std::list<FocusListener*> focusListeners = sourceWidget->_getFocusListeners();

        // Send the event to all focus listeners of the widget.
        for (std::list<FocusListener*>::iterator it = focusListeners.begin();
             it != focusListeners.end();
             ++it)
        {
            (*it)->focusGained(focusEvent);
        }
    }
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef LTAC_INSTRUCTION_H
#define LTAC_INSTRUCTION_H

#include <memory>
#include <vector>
#include <string>

#include <boost/optional.hpp>

#include "ltac/Operator.hpp"
#include "ltac/Register.hpp"
#include "ltac/FloatRegister.hpp"
#include "ltac/PseudoRegister.hpp"
#include "ltac/PseudoFloatRegister.hpp"
#include "ltac/Address.hpp"
#include "ltac/Argument.hpp"

namespace eddic {

class Function;

namespace ltac {

enum class Size : char {
    DEFAULT,
    BYTE,
    WORD,
    DOUBLE_WORD,
    QUAD_WORD
};

struct Instruction {
    private:
        std::size_t _uid;

    public:
        ltac::Operator op;
        boost::optional<Argument> arg1;
        boost::optional<Argument> arg2;
        boost::optional<Argument> arg3;
        ltac::Size size = ltac::Size::DEFAULT;

        std::string label;                      //Only if jump
        eddic::Function* target_function;       //Only if a call

        std::vector<ltac::PseudoRegister> uses;
        std::vector<ltac::PseudoFloatRegister> float_uses;

        std::vector<ltac::Register> hard_uses;
        std::vector<ltac::FloatRegister> hard_float_uses;

        std::vector<ltac::PseudoRegister> kills;
        std::vector<ltac::PseudoFloatRegister> float_kills;

        std::vector<ltac::Register> hard_kills;
        std::vector<ltac::FloatRegister> hard_float_kills;

        //Instruction should never get copied
        Instruction(const Instruction& rhs) = delete;
        Instruction& operator=(const Instruction& rhs) = delete;

        //Default constructor
        Instruction();

        //Instructions no param
        Instruction(Operator op);

        //Instructions with unary operator
        Instruction(Operator op, Argument arg1);

        //Instructions with binary operator
        Instruction(Operator op, Argument arg1, Argument arg2);

        //Instructions with ternary operator
        Instruction(Operator op, Argument arg1, Argument arg2, Argument arg3);

        //Jump, calls and labels
        Instruction(std::string label, Operator op);

        std::size_t uid() const {
            return _uid;
        }

        bool is_jump() const;
        bool is_label() const;
};

} //end of ltac

} //end of eddic

#endif
<commit_msg>Add possibility to move and copy Instruction<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef LTAC_INSTRUCTION_H
#define LTAC_INSTRUCTION_H

#include <memory>
#include <vector>
#include <string>

#include <boost/optional.hpp>

#include "ltac/Operator.hpp"
#include "ltac/Register.hpp"
#include "ltac/FloatRegister.hpp"
#include "ltac/PseudoRegister.hpp"
#include "ltac/PseudoFloatRegister.hpp"
#include "ltac/Address.hpp"
#include "ltac/Argument.hpp"

namespace eddic {

class Function;

namespace ltac {

enum class Size : char {
    DEFAULT,
    BYTE,
    WORD,
    DOUBLE_WORD,
    QUAD_WORD
};

struct Instruction {
    private:
        std::size_t _uid;

    public:
        ltac::Operator op;
        boost::optional<Argument> arg1;
        boost::optional<Argument> arg2;
        boost::optional<Argument> arg3;
        ltac::Size size = ltac::Size::DEFAULT;

        std::string label;                      //Only if jump
        eddic::Function* target_function;       //Only if a call

        std::vector<ltac::PseudoRegister> uses;
        std::vector<ltac::PseudoFloatRegister> float_uses;

        std::vector<ltac::Register> hard_uses;
        std::vector<ltac::FloatRegister> hard_float_uses;

        std::vector<ltac::PseudoRegister> kills;
        std::vector<ltac::PseudoFloatRegister> float_kills;

        std::vector<ltac::Register> hard_kills;
        std::vector<ltac::FloatRegister> hard_float_kills;

        //Default constructor
        Instruction();

        //Instructions no param
        Instruction(Operator op);

        //Instructions with unary operator
        Instruction(Operator op, Argument arg1);

        //Instructions with binary operator
        Instruction(Operator op, Argument arg1, Argument arg2);

        //Instructions with ternary operator
        Instruction(Operator op, Argument arg1, Argument arg2, Argument arg3);

        //Jump, calls and labels
        Instruction(std::string label, Operator op);

        //Instruction should never get copied
        Instruction(const Instruction& rhs) = default;
        Instruction& operator=(const Instruction& rhs) = default;

        Instruction(Instruction&& rhs) = default;
        Instruction& operator=(Instruction&& rhs) = default;

        std::size_t uid() const {
            return _uid;
        }

        bool is_jump() const;
        bool is_label() const;
};

} //end of ltac

} //end of eddic

#endif
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright 2014 Cloudius Systems
 */

#pragma once

#include <seastar/core/future.hh>
#include <seastar/util/std-compat.hh>
#include <exception>

namespace seastar {

/// \addtogroup fiber-module
/// @{

/// Exception thrown when a \ref gate object has been closed
/// by the \ref gate::close() method.
class gate_closed_exception : public std::exception {
public:
    virtual const char* what() const noexcept override {
        return "gate closed";
    }
};

/// Facility to stop new requests, and to tell when existing requests are done.
///
/// When stopping a service that serves asynchronous requests, we are faced with
/// two problems: preventing new requests from coming in, and knowing when existing
/// requests have completed.  The \c gate class provides a solution.
class gate {
    size_t _count = 0;
    std::optional<promise<>> _stopped;
public:
    /// Tries to register an in-progress request.
    ///
    /// If the gate is not closed, the request is registered and the function returns `true`,
    /// Otherwise the function just returns `false` and has no other effect.
    bool try_enter() noexcept {
        bool opened = !_stopped;
        if (opened) {
            ++_count;
        }
        return opened;
    }
    /// Registers an in-progress request.
    ///
    /// If the gate is not closed, the request is registered.  Otherwise,
    /// a \ref gate_closed_exception is thrown.
    void enter() {
        if (!try_enter()) {
            throw gate_closed_exception();
        }
    }
    /// Unregisters an in-progress request.
    ///
    /// If the gate is closed, and there are no more in-progress requests,
    /// the \ref closed() promise will be fulfilled.
    void leave() {
        --_count;
        if (!_count && _stopped) {
            _stopped->set_value();
        }
    }
    /// Potentially stop an in-progress request.
    ///
    /// If the gate is already closed, a \ref gate_closed_exception is thrown.
    /// By using \ref enter() and \ref leave(), the program can ensure that
    /// no further requests are serviced. However, long-running requests may
    /// continue to run. The check() method allows such a long operation to
    /// voluntarily stop itself after the gate is closed, by making calls to
    /// check() in appropriate places. check() with throw an exception and
    /// bail out of the long-running code if the gate is closed.
    void check() {
        if (_stopped) {
            throw gate_closed_exception();
        }
    }
    /// Closes the gate.
    ///
    /// Future calls to \ref enter() will fail with an exception, and when
    /// all current requests call \ref leave(), the returned future will be
    /// made ready.
    future<> close() {
        assert(!_stopped && "seastar::gate::close() cannot be called more than once");
        _stopped = std::make_optional(promise<>());
        if (!_count) {
            _stopped->set_value();
        }
        return _stopped->get_future();
    }

    /// Returns a current number of registered in-progress requests.
    size_t get_count() const {
        return _count;
    }

    /// Returns whether the gate is closed.
    bool is_closed() const {
        return bool(_stopped);
    }
};

namespace internal {

template <typename Func>
inline
auto
invoke_func_with_gate(gate& g, Func&& func) noexcept {
    return futurize_invoke(std::forward<Func>(func)).finally([&g] { g.leave(); });
}

} // namespace intgernal

/// Executes the function \c func making sure the gate \c g is properly entered
/// and later on, properly left.
///
/// \param func function to be executed
/// \param g the gate. Caller must make sure that it outlives this function.
/// \returns whatever \c func returns
///
/// \relates gate
template <typename Func>
inline
auto
with_gate(gate& g, Func&& func) {
    g.enter();
    return internal::invoke_func_with_gate(g, std::forward<Func>(func));
}

/// Executes the function \c func if the gate \c g can be entered
/// and later on, properly left.
///
/// \param func function to be executed
/// \param g the gate. Caller must make sure that it outlives this function.
///
/// If the gate is already closed, an exception future holding
/// \ref gate_closed_exception is returned, otherwise
/// \returns whatever \c func returns.
///
/// \relates gate
template <typename Func>
inline
auto
try_with_gate(gate& g, Func&& func) noexcept {
    if (!g.try_enter()) {
        using futurator = futurize<std::result_of_t<Func()>>;
        return futurator::make_exception_future(gate_closed_exception());
    }
    return internal::invoke_func_with_gate(g, std::forward<Func>(func));
}
/// @}

}
<commit_msg>gate: specify trivial methods as noexcept<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright 2014 Cloudius Systems
 */

#pragma once

#include <seastar/core/future.hh>
#include <seastar/util/std-compat.hh>
#include <exception>

namespace seastar {

/// \addtogroup fiber-module
/// @{

/// Exception thrown when a \ref gate object has been closed
/// by the \ref gate::close() method.
class gate_closed_exception : public std::exception {
public:
    virtual const char* what() const noexcept override {
        return "gate closed";
    }
};

/// Facility to stop new requests, and to tell when existing requests are done.
///
/// When stopping a service that serves asynchronous requests, we are faced with
/// two problems: preventing new requests from coming in, and knowing when existing
/// requests have completed.  The \c gate class provides a solution.
class gate {
    size_t _count = 0;
    std::optional<promise<>> _stopped;
public:
    /// Tries to register an in-progress request.
    ///
    /// If the gate is not closed, the request is registered and the function returns `true`,
    /// Otherwise the function just returns `false` and has no other effect.
    bool try_enter() noexcept {
        bool opened = !_stopped;
        if (opened) {
            ++_count;
        }
        return opened;
    }
    /// Registers an in-progress request.
    ///
    /// If the gate is not closed, the request is registered.  Otherwise,
    /// a \ref gate_closed_exception is thrown.
    void enter() {
        if (!try_enter()) {
            throw gate_closed_exception();
        }
    }
    /// Unregisters an in-progress request.
    ///
    /// If the gate is closed, and there are no more in-progress requests,
    /// the \ref closed() promise will be fulfilled.
    void leave() noexcept {
        --_count;
        if (!_count && _stopped) {
            _stopped->set_value();
        }
    }
    /// Potentially stop an in-progress request.
    ///
    /// If the gate is already closed, a \ref gate_closed_exception is thrown.
    /// By using \ref enter() and \ref leave(), the program can ensure that
    /// no further requests are serviced. However, long-running requests may
    /// continue to run. The check() method allows such a long operation to
    /// voluntarily stop itself after the gate is closed, by making calls to
    /// check() in appropriate places. check() with throw an exception and
    /// bail out of the long-running code if the gate is closed.
    void check() {
        if (_stopped) {
            throw gate_closed_exception();
        }
    }
    /// Closes the gate.
    ///
    /// Future calls to \ref enter() will fail with an exception, and when
    /// all current requests call \ref leave(), the returned future will be
    /// made ready.
    future<> close() {
        assert(!_stopped && "seastar::gate::close() cannot be called more than once");
        _stopped = std::make_optional(promise<>());
        if (!_count) {
            _stopped->set_value();
        }
        return _stopped->get_future();
    }

    /// Returns a current number of registered in-progress requests.
    size_t get_count() const noexcept {
        return _count;
    }

    /// Returns whether the gate is closed.
    bool is_closed() const noexcept {
        return bool(_stopped);
    }
};

namespace internal {

template <typename Func>
inline
auto
invoke_func_with_gate(gate& g, Func&& func) noexcept {
    return futurize_invoke(std::forward<Func>(func)).finally([&g] { g.leave(); });
}

} // namespace intgernal

/// Executes the function \c func making sure the gate \c g is properly entered
/// and later on, properly left.
///
/// \param func function to be executed
/// \param g the gate. Caller must make sure that it outlives this function.
/// \returns whatever \c func returns
///
/// \relates gate
template <typename Func>
inline
auto
with_gate(gate& g, Func&& func) {
    g.enter();
    return internal::invoke_func_with_gate(g, std::forward<Func>(func));
}

/// Executes the function \c func if the gate \c g can be entered
/// and later on, properly left.
///
/// \param func function to be executed
/// \param g the gate. Caller must make sure that it outlives this function.
///
/// If the gate is already closed, an exception future holding
/// \ref gate_closed_exception is returned, otherwise
/// \returns whatever \c func returns.
///
/// \relates gate
template <typename Func>
inline
auto
try_with_gate(gate& g, Func&& func) noexcept {
    if (!g.try_enter()) {
        using futurator = futurize<std::result_of_t<Func()>>;
        return futurator::make_exception_future(gate_closed_exception());
    }
    return internal::invoke_func_with_gate(g, std::forward<Func>(func));
}
/// @}

}
<|endoftext|>


<commit_before>#ifndef SHRINKWRAP_STDIO_HPP
#define SHRINKWRAP_STDIO_HPP

#include <streambuf>
#include <cstdio>
#include <vector>
#include <iostream>

namespace shrinkwrap
{
  namespace stdio
  {
    class filebuf : public std::streambuf
    {
    private:
      std::FILE* fp_;
    public:
      typedef filebuf self_type;

      filebuf(std::FILE* fp) :
        fp_(fp)
      { }

      filebuf(self_type&& src) :
        std::streambuf(std::move(src)),
        fp_(src.fp_)
      {
        src.fp_ = nullptr;
      }

      self_type& operator=(self_type&& src)
      {
        if (this != &src)
        {
          std::streambuf::operator=(std::move(src));
          this->destroy();
          std::swap(fp_, src.fp_);
        }
        return *this;
      }

      void swap(self_type& src)
      {
        std::streambuf::swap(src);
        std::swap(fp_, src.fp_);
      }

      ~filebuf()
      {
        this->destroy();
      }

      void destroy()
      {
        if (fp_)
        {
          std::fclose(fp_);
          fp_ = nullptr;
        }
      }

      bool is_open() const
      {
        return fp_ != nullptr;
      }
    protected:
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
      // buffer management and positioning virtual methods
      virtual std::streambuf::pos_type seekoff(std::streambuf::off_type off, std::ios_base::seekdir way, std::ios_base::openmode which)
      {
        int origin;
        if (way == std::ios::cur)
          origin = SEEK_CUR;
        else if (way == std::ios::end)
          origin = SEEK_END;
        else
          origin = SEEK_SET;

        if (fseek(fp_, off, origin))
          return pos_type(off_type(-1));
        return pos_type(off_type(std::ftell(fp_)));
      }

      virtual std::streambuf::pos_type seekpos(std::streambuf::pos_type pos, std::ios_base::openmode which)
      {
        if (fseek(fp_, pos, SEEK_SET))
          return pos_type(off_type(-1));
        assert(pos == pos_type(off_type(std::ftell(fp_))));
        return pos;
      }

      virtual int sync()
      {
        return std::fflush(fp_);
      }
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
      // input virtual methods
      virtual std::streamsize xsgetn(char* data, std::streamsize sz)
      {
        std::streamsize ret = std::fread(data, 1, sz, fp_);

        if (std::ferror(fp_))
        {
          // TODO: throw exception
        }

        return ret;
      }

      virtual int underflow() // This supports istream::peek()
      {
        int ret = std::getc(fp_);
        return std::ungetc(ret, fp_);
      }

      virtual int uflow() // This supports istream::get()
      {
        return std::getc(fp_);
      }

      virtual int pbackfail(int c)
      {
        return std::ungetc(c, fp_); // Does not support istream::unget(), which is indicated by c equaling EOF
      }
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
      // output virtual methods
      virtual std::streamsize xsputn(const char* data, std::streamsize sz)
      {
        std::streamsize ret = std::fwrite(data, 1, sz, fp_);

        if (ret != sz)
        {
          // TODO throw exception
        }

        return ret;
      }

      virtual int overflow(int c)
      {
        if (!traits_type::eq_int_type(c, traits_type::eof()))
          return std::putc(c, fp_);
        return traits_type::not_eof(c);
      }
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
    };

    class istream : public std::istream
    {
    public:
      istream(const std::string& file_path) :
        std::istream(&sbuf_),
        sbuf_(std::fopen(file_path.c_str(), "rb"))
      {
        if (!sbuf_.is_open())
          setstate(rdstate() | std::ios::badbit);
      }

#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4
      istream(istream&& src)
        :
        std::istream(&sbuf_),
        sbuf_(std::move(src.sbuf_))
      {
      }

      istream& operator=(istream&& src)
      {
        if (&src != this)
        {
          std::istream::operator=(std::move(src));
          sbuf_ = std::move(src.sbuf_);
        }
        return *this;
      }
#endif
    private:
      ::shrinkwrap::stdio::filebuf sbuf_;
    };

    class ostream : public std::ostream
    {
    public:
      ostream(const std::string& file_path)
        :
        std::ostream(&sbuf_),
        sbuf_(std::fopen(file_path.c_str(), "wb"))
      {
        if (!sbuf_.is_open())
          setstate(rdstate() | std::ios::badbit);
      }

#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4
      ostream(ostream&& src)
        :
        std::ostream(&sbuf_),
        sbuf_(std::move(src.sbuf_))
      {
      }

      ostream& operator=(ostream&& src)
      {
        if (&src != this)
        {
          std::ostream::operator=(std::move(src));
          sbuf_ = std::move(src.sbuf_);
        }
        return *this;
      }
#endif
    private:
      ::shrinkwrap::stdio::filebuf sbuf_;
    };
  }
}

#endif //SHRINKWRAP_STDIO_HPP<commit_msg>Fixes missing include.<commit_after>#ifndef SHRINKWRAP_STDIO_HPP
#define SHRINKWRAP_STDIO_HPP

#include <streambuf>
#include <cstdio>
#include <vector>
#include <iostream>
#include <cassert>

namespace shrinkwrap
{
  namespace stdio
  {
    class filebuf : public std::streambuf
    {
    private:
      std::FILE* fp_;
    public:
      typedef filebuf self_type;

      filebuf(std::FILE* fp) :
        fp_(fp)
      { }

      filebuf(self_type&& src) :
        std::streambuf(std::move(src)),
        fp_(src.fp_)
      {
        src.fp_ = nullptr;
      }

      self_type& operator=(self_type&& src)
      {
        if (this != &src)
        {
          std::streambuf::operator=(std::move(src));
          this->destroy();
          std::swap(fp_, src.fp_);
        }
        return *this;
      }

      void swap(self_type& src)
      {
        std::streambuf::swap(src);
        std::swap(fp_, src.fp_);
      }

      ~filebuf()
      {
        this->destroy();
      }

      void destroy()
      {
        if (fp_)
        {
          std::fclose(fp_);
          fp_ = nullptr;
        }
      }

      bool is_open() const
      {
        return fp_ != nullptr;
      }
    protected:
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
      // buffer management and positioning virtual methods
      virtual std::streambuf::pos_type seekoff(std::streambuf::off_type off, std::ios_base::seekdir way, std::ios_base::openmode which)
      {
        int origin;
        if (way == std::ios::cur)
          origin = SEEK_CUR;
        else if (way == std::ios::end)
          origin = SEEK_END;
        else
          origin = SEEK_SET;

        if (fseek(fp_, off, origin))
          return pos_type(off_type(-1));
        return pos_type(off_type(std::ftell(fp_)));
      }

      virtual std::streambuf::pos_type seekpos(std::streambuf::pos_type pos, std::ios_base::openmode which)
      {
        if (fseek(fp_, pos, SEEK_SET))
          return pos_type(off_type(-1));
        assert(pos == pos_type(off_type(std::ftell(fp_))));
        return pos;
      }

      virtual int sync()
      {
        return std::fflush(fp_);
      }
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
      // input virtual methods
      virtual std::streamsize xsgetn(char* data, std::streamsize sz)
      {
        std::streamsize ret = std::fread(data, 1, sz, fp_);

        if (std::ferror(fp_))
        {
          // TODO: throw exception
        }

        return ret;
      }

      virtual int underflow() // This supports istream::peek()
      {
        int ret = std::getc(fp_);
        return std::ungetc(ret, fp_);
      }

      virtual int uflow() // This supports istream::get()
      {
        return std::getc(fp_);
      }

      virtual int pbackfail(int c)
      {
        return std::ungetc(c, fp_); // Does not support istream::unget(), which is indicated by c equaling EOF
      }
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
      // output virtual methods
      virtual std::streamsize xsputn(const char* data, std::streamsize sz)
      {
        std::streamsize ret = std::fwrite(data, 1, sz, fp_);

        if (ret != sz)
        {
          // TODO throw exception
        }

        return ret;
      }

      virtual int overflow(int c)
      {
        if (!traits_type::eq_int_type(c, traits_type::eof()))
          return std::putc(c, fp_);
        return traits_type::not_eof(c);
      }
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
    };

    class istream : public std::istream
    {
    public:
      istream(const std::string& file_path) :
        std::istream(&sbuf_),
        sbuf_(std::fopen(file_path.c_str(), "rb"))
      {
        if (!sbuf_.is_open())
          setstate(rdstate() | std::ios::badbit);
      }

#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4
      istream(istream&& src)
        :
        std::istream(&sbuf_),
        sbuf_(std::move(src.sbuf_))
      {
      }

      istream& operator=(istream&& src)
      {
        if (&src != this)
        {
          std::istream::operator=(std::move(src));
          sbuf_ = std::move(src.sbuf_);
        }
        return *this;
      }
#endif
    private:
      ::shrinkwrap::stdio::filebuf sbuf_;
    };

    class ostream : public std::ostream
    {
    public:
      ostream(const std::string& file_path)
        :
        std::ostream(&sbuf_),
        sbuf_(std::fopen(file_path.c_str(), "wb"))
      {
        if (!sbuf_.is_open())
          setstate(rdstate() | std::ios::badbit);
      }

#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4
      ostream(ostream&& src)
        :
        std::ostream(&sbuf_),
        sbuf_(std::move(src.sbuf_))
      {
      }

      ostream& operator=(ostream&& src)
      {
        if (&src != this)
        {
          std::ostream::operator=(std::move(src));
          sbuf_ = std::move(src.sbuf_);
        }
        return *this;
      }
#endif
    private:
      ::shrinkwrap::stdio::filebuf sbuf_;
    };
  }
}

#endif //SHRINKWRAP_STDIO_HPP<|endoftext|>


<commit_before>/** ==========================================================================
 * 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
 * with no warranties. This code is yours to share, use and modify with no
 * strings attached and no restrictions or obligations.
 *
 * For more information see g3log/LICENSE or refer refer to http://unlicense.org
 * ============================================================================
 * Filename:g2logmessage.hpp  Part of Framework for Logging and Design By Contract
 * Created: 2012 by Kjell Hedström
 *
 * PUBLIC DOMAIN and Not copywrited. First published at KjellKod.cc
 * ********************************************* */

#pragma once

#include <string>
#include <sstream>
#include <chrono>
#include <thread>

#include "g2loglevels.hpp"
#include "g2time.hpp"
#include "g2moveoncopy.hpp"
#include "crashhandler.hpp"
#include <memory>
namespace g2 {

   /** LogMessage contains all the data collected from the LOG(...) call.
   * If the sink receives a std::string it will be the std::string toString()... function
   * that will format the data into a string
   *
   * For sinks that receive a LogMessage they can either use the toString() function, or use
   * the helper functions or even the public raw data to format the saved log message any
   * desired way.
   */
   struct LogMessage {
      std::string file() const { return _file; }
      std::string line() const { return std::to_string(_line); }
      std::string function() const { return _function; }
      std::string level() const { return _level.text; }

      /// use a different format string to get a different look on the time.
      //  default look is Y/M/D H:M:S
      std::string timestamp(const std::string& time_format = {internal::date_formatted + " " + internal::time_formatted}) const;
      std::string microseconds() const { return std::to_string(_microseconds); }

      std::string message() const  {  return _message; }
      std::string& write() const {  return _message; }

      std::string expression() const  { return _expression; }
      bool wasFatal() const { return internal::wasFatal(_level); }

      std::string threadID() const;

      std::string toString() const;
      void setExpression(const std::string expression) { _expression = expression; }

      LogMessage(const std::string &file, const int line, const std::string& function, const LEVELS& level);
      explicit LogMessage(const std::string& fatalOsSignalCrashMessage);

      LogMessage(const LogMessage&);
      LogMessage(LogMessage&& other);
      virtual ~LogMessage(){};

      //
      // Complete access to the raw data in case the helper functions above
      // are not enough.
      //
      std::time_t _timestamp;
      std::thread::id _call_thread_id;
      int64_t _microseconds;
      std::string _file;
      int _line;
      std::string _function;
      LEVELS _level;
      std::string _expression; // only with content for CHECK(...) calls
      mutable std::string _message;
   };

   /** Trigger for flushing the message queue and exiting the application
    * A thread that causes a FatalMessage will sleep forever until the
    * application has exited (after message flush) */
   struct FatalMessage : public LogMessage {
      FatalMessage(const LogMessage& details, g2::SignalType signal_id);
      FatalMessage(const FatalMessage&);
      virtual ~FatalMessage(){};

      LogMessage copyToLogMessage() const;
      std::string reason() const;

      const SignalType _signal_id;
   };

   typedef MoveOnCopy<std::unique_ptr<FatalMessage>> FatalMessagePtr;
   typedef MoveOnCopy<std::unique_ptr<LogMessage>> LogMessagePtr;
   typedef MoveOnCopy<LogMessage> LogMessageMover;
} // g2
<commit_msg>Remove trailing spaces.<commit_after>/** ==========================================================================
 * 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
 * with no warranties. This code is yours to share, use and modify with no
 * strings attached and no restrictions or obligations.
 *
 * For more information see g3log/LICENSE or refer refer to http://unlicense.org
 * ============================================================================
 * Filename:g2logmessage.hpp  Part of Framework for Logging and Design By Contract
 * Created: 2012 by Kjell Hedström
 *
 * PUBLIC DOMAIN and Not copywrited. First published at KjellKod.cc
 * ********************************************* */

#pragma once

#include <string>
#include <sstream>
#include <chrono>
#include <thread>

#include "g2loglevels.hpp"
#include "g2time.hpp"
#include "g2moveoncopy.hpp"
#include "crashhandler.hpp"
#include <memory>
namespace g2 {

   /** LogMessage contains all the data collected from the LOG(...) call.
   * If the sink receives a std::string it will be the std::string toString()... function
   * that will format the data into a string
   *
   * For sinks that receive a LogMessage they can either use the toString() function, or use
   * the helper functions or even the public raw data to format the saved log message any
   * desired way.
   */
   struct LogMessage {
      std::string file() const { return _file; }
      std::string line() const { return std::to_string(_line); }
      std::string function() const { return _function; }
      std::string level() const { return _level.text; }

      /// use a different format string to get a different look on the time.
      //  default look is Y/M/D H:M:S
      std::string timestamp(const std::string& time_format = {internal::date_formatted + " " + internal::time_formatted}) const;
      std::string microseconds() const { return std::to_string(_microseconds); }

      std::string message() const  {  return _message; }
      std::string& write() const {  return _message; }

      std::string expression() const  { return _expression; }
      bool wasFatal() const { return internal::wasFatal(_level); }

      std::string threadID() const;

      std::string toString() const;
      void setExpression(const std::string expression) { _expression = expression; }

      LogMessage(const std::string &file, const int line, const std::string& function, const LEVELS& level);
      explicit LogMessage(const std::string& fatalOsSignalCrashMessage);

      LogMessage(const LogMessage&);
      LogMessage(LogMessage&& other);
      virtual ~LogMessage(){};

      //
      // Complete access to the raw data in case the helper functions above
      // are not enough.
      //
      std::time_t _timestamp;
      std::thread::id _call_thread_id;
      int64_t _microseconds;
      std::string _file;
      int _line;
      std::string _function;
      LEVELS _level;
      std::string _expression; // only with content for CHECK(...) calls
      mutable std::string _message;
   };

   /** Trigger for flushing the message queue and exiting the application
    * A thread that causes a FatalMessage will sleep forever until the
    * application has exited (after message flush) */
   struct FatalMessage : public LogMessage {
      FatalMessage(const LogMessage& details, g2::SignalType signal_id);
      FatalMessage(const FatalMessage&);
      virtual ~FatalMessage(){};

      LogMessage copyToLogMessage() const;
      std::string reason() const;

      const SignalType _signal_id;
   };

   typedef MoveOnCopy<std::unique_ptr<FatalMessage>> FatalMessagePtr;
   typedef MoveOnCopy<std::unique_ptr<LogMessage>> LogMessagePtr;
   typedef MoveOnCopy<LogMessage> LogMessageMover;
} // g2
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file  test_helper.hpp
//----------------------------------------------------------------------------
/// \brief Unit test helping routines.
//----------------------------------------------------------------------------
// Author:  Serge Aleynikov
// Created: 2010-01-06
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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

This 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

***** END LICENSE BLOCK *****
*/

#pragma once

#include <boost/test/unit_test.hpp>
#include <utxx/get_option.hpp>

#define BOOST_CURRENT_TEST_NAME \
  boost::unit_test::framework::current_test_case().p_name->c_str()

#define UTXX_REQUIRE_NO_THROW(Expr)     \
    try { Expr; }                       \
    catch (std::exception const& e) {   \
      BOOST_TEST_MESSAGE(e.what());     \
      BOOST_REQUIRE_NO_THROW(Expr);     \
    }

#define UTXX_CHECK_NO_THROW(Expr)       \
    try { Expr; }                       \
    catch (std::exception const& e) {   \
      BOOST_TEST_MESSAGE(e.what());     \
      BOOST_CHECK_NO_THROW(Expr);       \
    }

namespace utxx {

inline bool get_test_argv(const std::string& a_opt,
                          const std::string& a_long_opt = "") {
    int    argc = boost::unit_test::framework::master_test_suite().argc;
    char** argv = boost::unit_test::framework::master_test_suite().argv;

    return get_opt(argc, argv, (int*)nullptr, a_opt, a_long_opt);
}

template <typename T>
inline bool get_test_argv(const std::string& a_opt,
                          const std::string& a_long_opt,
                          T& a_value) {
    int    argc = boost::unit_test::framework::master_test_suite().argc;
    char** argv = boost::unit_test::framework::master_test_suite().argv;

    return get_opt(argc, argv, &a_value, a_opt, a_long_opt);
}

/// Prevent variable optimization by the compiler
#ifdef _MSC_VER
#pragma optimize("", off)
template <class T> void dont_optimize_var(T&& v) { v = v; }
#pragma optimize("", on)
#else
template <class T> void dont_optimize_var(T&& v) { asm volatile("":"+r" (v)); }
#endif

} // namespace utxx::test
<commit_msg>Portable boost log_level runtime checking<commit_after>//----------------------------------------------------------------------------
/// \file  test_helper.hpp
//----------------------------------------------------------------------------
/// \brief Unit test helping routines.
//----------------------------------------------------------------------------
// Author:  Serge Aleynikov
// Created: 2010-01-06
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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

This 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

***** END LICENSE BLOCK *****
*/

#pragma once

#include <boost/test/unit_test.hpp>
#include <utxx/get_option.hpp>

#define BOOST_CURRENT_TEST_NAME \
  boost::unit_test::framework::current_test_case().p_name->c_str()

#define UTXX_REQUIRE_NO_THROW(Expr)     \
    try { Expr; }                       \
    catch (std::exception const& e) {   \
      BOOST_TEST_MESSAGE(e.what());     \
      BOOST_REQUIRE_NO_THROW(Expr);     \
    }

#define UTXX_CHECK_NO_THROW(Expr)       \
    try { Expr; }                       \
    catch (std::exception const& e) {   \
      BOOST_TEST_MESSAGE(e.what());     \
      BOOST_CHECK_NO_THROW(Expr);       \
    }

#if BOOST_VERSION < 105900
#  define BOOST_LOG_LEVEL boost::unit_test::runtime_config::log_level()
#else
#  define BOOST_LOG_LEVEL \
    boost::unit_test::runtime_config::get<boost::unit_test::log_level>( \
        boost::unit_test::runtime_config::LOG_LEVEL )
#endif

namespace utxx {

inline bool get_test_argv(const std::string& a_opt,
                          const std::string& a_long_opt = "") {
    int    argc = boost::unit_test::framework::master_test_suite().argc;
    char** argv = boost::unit_test::framework::master_test_suite().argv;

    return get_opt(argc, argv, (int*)nullptr, a_opt, a_long_opt);
}

template <typename T>
inline bool get_test_argv(const std::string& a_opt,
                          const std::string& a_long_opt,
                          T& a_value) {
    int    argc = boost::unit_test::framework::master_test_suite().argc;
    char** argv = boost::unit_test::framework::master_test_suite().argv;

    return get_opt(argc, argv, &a_value, a_opt, a_long_opt);
}

/// Prevent variable optimization by the compiler
#ifdef _MSC_VER
#pragma optimize("", off)
template <class T> void dont_optimize_var(T&& v) { v = v; }
#pragma optimize("", on)
#else
template <class T> void dont_optimize_var(T&& v) { asm volatile("":"+r" (v)); }
#endif

} // namespace utxx::test
<|endoftext|>


<commit_before>//============================================================================
// vSMC/include/vsmc/rng/rng_set.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013,2014, Yan Zhou
// 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.
//
// 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 HOLDER 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.
//============================================================================

#ifndef VSMC_RNG_RNG_SET_HPP
#define VSMC_RNG_RNG_SET_HPP

#include <vsmc/rng/internal/common.hpp>
#include <vsmc/rng/seed.hpp>
#if VSMC_HAS_AES_NI
#include <vsmc/rng/aes.hpp>
#include <vsmc/rng/ars.hpp>
#endif
#include <vsmc/rng/philox.hpp>
#include <vsmc/rng/threefry.hpp>

/// \brief Default RNG set type
/// \ingroup Config
#ifndef VSMC_RNG_SET_TYPE
#define VSMC_RNG_SET_TYPE ::vsmc::RngSet< ::vsmc::Threefry4x64, ::vsmc::Vector>
#endif

namespace vsmc {

template <typename, typename> class RngSet;

/// \brief Scalar RNG set
/// \ingroup RNG
template <typename RngType>
class RngSet<RngType, Scalar>
{
    public :

    typedef RngType rng_type;
    typedef std::size_t size_type;

    explicit RngSet (size_type N) : size_(N) {seed();}

    size_type size () const {return size_;}

    void resize (std::size_t) {}

    void seed () {rng_.seed(Seed::instance().get());}

    rng_type &operator[] (size_type) {return rng_;}

    private :

    std::size_t size_;
    rng_type rng_;
}; // class RngSet

/// \brief Vector RNG set
/// \ingroup RNG
template <typename RngType>
class RngSet<RngType, Vector>
{
    public :

    typedef RngType rng_type;
    typedef typename std::vector<rng_type, AlignedAllocator<rng_type> >::
        size_type size_type;

    explicit RngSet (size_type N) : rng_(N, rng_type()) {seed();}

    size_type size () const {return rng_.size();}

    void resize (std::size_t n)
    {
        if (n == rng_.size())
            return;

        if (n < rng_.size())
            rng_.resize(n);

        rng_.reserve(n);
        rng_type rng;
        for (std::size_t i = rng_.size(); i != n; ++i) {
            rng.seed(Seed::instance().get());
            rng_.push_back(rng);
        }
    }

    void seed ()
    {
        for (size_type i = 0; i != rng_.size(); ++i)
            rng_[i].seed(Seed::instance().get());
    }

    rng_type &operator[] (size_type id) {return rng_[id];}

    private :

    std::vector<rng_type, AlignedAllocator<rng_type> > rng_;
}; // class RngSet

namespace traits {

/// \brief Particle::rng_set_type trait
/// \ingroup Traits
VSMC_DEFINE_TYPE_DISPATCH_TRAIT(RngSetType, rng_set_type, VSMC_RNG_SET_TYPE)

} // namespace vsmc::traits

} // namespace vsmc

#endif // VSMC_RNG_RNG_SET_HPP
<commit_msg>RngSet now has default args<commit_after>//============================================================================
// vSMC/include/vsmc/rng/rng_set.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013,2014, Yan Zhou
// 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.
//
// 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 HOLDER 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.
//============================================================================

#ifndef VSMC_RNG_RNG_SET_HPP
#define VSMC_RNG_RNG_SET_HPP

#include <vsmc/rng/internal/common.hpp>
#include <vsmc/rng/seed.hpp>
#if VSMC_HAS_AES_NI
#include <vsmc/rng/aes.hpp>
#include <vsmc/rng/ars.hpp>
#endif
#include <vsmc/rng/philox.hpp>
#include <vsmc/rng/threefry.hpp>

/// \brief Default RNG set type
/// \ingroup Config
#ifndef VSMC_RNG_SET_TYPE
#define VSMC_RNG_SET_TYPE ::vsmc::RngSet< ::vsmc::Threefry4x64, ::vsmc::Vector>
#endif

namespace vsmc {

template <typename = Threefry4x64, typename = Vector> class RngSet;

/// \brief Scalar RNG set
/// \ingroup RNG
template <typename RngType>
class RngSet<RngType, Scalar>
{
    public :

    typedef RngType rng_type;
    typedef std::size_t size_type;

    explicit RngSet (size_type N = 0) : size_(N) {seed();}

    size_type size () const {return size_;}

    void resize (std::size_t) {}

    void seed () {rng_.seed(Seed::instance().get());}

    rng_type &operator[] (size_type) {return rng_;}

    private :

    std::size_t size_;
    rng_type rng_;
}; // class RngSet

/// \brief Vector RNG set
/// \ingroup RNG
template <typename RngType>
class RngSet<RngType, Vector>
{
    public :

    typedef RngType rng_type;
    typedef typename std::vector<rng_type, AlignedAllocator<rng_type> >::
        size_type size_type;

    explicit RngSet (size_type N = 0) : rng_(N, rng_type()) {seed();}

    size_type size () const {return rng_.size();}

    void resize (std::size_t n)
    {
        if (n == rng_.size())
            return;

        if (n < rng_.size())
            rng_.resize(n);

        rng_.reserve(n);
        rng_type rng;
        for (std::size_t i = rng_.size(); i != n; ++i) {
            rng.seed(Seed::instance().get());
            rng_.push_back(rng);
        }
    }

    void seed ()
    {
        for (size_type i = 0; i != rng_.size(); ++i)
            rng_[i].seed(Seed::instance().get());
    }

    rng_type &operator[] (size_type id) {return rng_[id];}

    private :

    std::vector<rng_type, AlignedAllocator<rng_type> > rng_;
}; // class RngSet

namespace traits {

/// \brief Particle::rng_set_type trait
/// \ingroup Traits
VSMC_DEFINE_TYPE_DISPATCH_TRAIT(RngSetType, rng_set_type, VSMC_RNG_SET_TYPE)

} // namespace vsmc::traits

} // namespace vsmc

#endif // VSMC_RNG_RNG_SET_HPP
<|endoftext|>


<commit_before>// @(#)root/main:$Id$
// Author: Fons Rademakers   15/02/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// PMain                                                                //
//                                                                      //
// Main program used to create PROOF server application.                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <errno.h>

#ifdef WIN32
#include <io.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

#include "RConfigure.h"
#ifdef R__AFS
#include "TAFS.h"
#endif
#include "TApplication.h"
#include "TInterpreter.h"
#include "TROOT.h"
#include "TSystem.h"

// Special type for the hook to the TXProofServ constructor, needed to avoid
// using the plugin manager
typedef TApplication *(*TProofServ_t)(Int_t *argc, char **argv, FILE *flog);
#ifdef R__AFS
// Special type for the hook to the TAFS constructor, needed to avoid
// using the plugin manager
typedef TAFS *(*TAFS_t)(const char *, const char *, Int_t);
// Instance of the AFS token class
static TAFS *gAFS = 0;
#endif

//______________________________________________________________________________
static void ReadPutEnvs(const char *envfile)
{
   // Read envs from file 'envfile' and add them to the env space

   // Check inputs
   if (!envfile || strlen(envfile) <= 0) return;

   // Open the file
   FILE *fenv = fopen(envfile, "r");
   if (!fenv) return;

   // Read lines
   char ln[4096];
   while (fgets(ln, sizeof(ln), fenv)) {
      int l = strlen(ln);
      // Strip '\n'
      if (l > 0 && ln[l-1] == '\n') { ln[l-1] = '\0'; l--; }
      // Skip comments or empty line
      if (l <= 0 || ln[0] == '#') continue;
      // Skip lines not in the form '<name>=<value>'
      if (!strchr(ln, '=')) continue;
      // Good line
      char *ev = new char[l+1];
      strcpy(ev, ln);
      putenv(ev);
   }

   // Close the file
   fclose(fenv);
}

//______________________________________________________________________________
static FILE *RedirectOutput(const char *logfile, const char *loc)
{
   // Redirect stdout to 'logfile'. This log file will be flushed to the
   // client or master after each command.
   // On success return a pointer to the open log file. Return 0 on failure.

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: enter: %s\n", loc, logfile);

   if (!logfile || strlen(logfile) <= 0) {
      fprintf(stderr,"%s: RedirectOutput: logfile path undefined\n", loc);
      return 0;
   }

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: reopen %s\n", loc, logfile);
   FILE *flog = freopen(logfile, "a", stdout);
   if (!flog) {
      fprintf(stderr,"%s: RedirectOutput: could not freopen stdout\n", loc);
      return 0;
   }

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: dup2 ...\n", loc);
   if ((dup2(fileno(stdout), fileno(stderr))) < 0) {
      fprintf(stderr,"%s: RedirectOutput: could not redirect stderr\n", loc);
      return 0;
   }

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: read open ...\n", loc);
   FILE *fLog = fopen(logfile, "r");
   if (!fLog) {
      fprintf(stderr,"%s: RedirectOutput: could not open logfile %s\n", loc, logfile);
      return 0;
   }

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: done!\n", loc);
   // We are done
   return fLog;
}

#ifdef R__AFS
//______________________________________________________________________________
static Int_t InitAFS(const char *fileafs, const char *loc)
{
   // Init AFS token using credentials at fileafs

   TString getter("GetTAFS");
   char *p = 0;
   TString afslib = "libAFSAuth";
   if ((p = gSystem->DynamicPathName(afslib, kTRUE))) {
      delete[] p;
      if (gSystem->Load(afslib) == -1) {
         if (loc)
            fprintf(stderr,"%s: can't load %s\n", loc, afslib.Data());
         return -1;
      }
   } else {
      if (loc)
         fprintf(stderr,"%s: can't locate %s\n", loc, afslib.Data());
      return -1;
   }

   // Locate constructor
   Func_t f = gSystem->DynFindSymbol(afslib, getter);
   if (f) {
      gAFS = (*((TAFS_t)f))(fileafs, 0, -1);
      if (!gAFS) {
         if (loc)
            fprintf(stderr,"%s: could not initialize a valid TAFS\n", loc);
         return -1;
      }
   } else {
      if (loc)
         fprintf(stderr,"%s: can't find %s\n", loc, getter.Data());
      return -1;
   }

   // Done
   return 0;
}
#endif

//______________________________________________________________________________
int main(int argc, char **argv)
{
   // PROOF server main program.

#ifdef R__DEBUG
   int debug = 1;
   while (debug)
      ;
#endif
   if (argc >= 6) {
      // Read and put system envs
      ReadPutEnvs(argv[5]);
   }

   int loglevel = (argc >= 5) ? strtol(argv[4], 0, 10) : -1;
   if (loglevel < 0 && getenv("ROOTPROOFLOGLEVEL"))
      loglevel = atoi(getenv("ROOTPROOFLOGLEVEL"));
   if (loglevel > 0)
      fprintf(stderr,"%s: starting %s\n", argv[1], argv[0]);

   // Redirect the output
   FILE *fLog = 0;
   char *loc = 0;
   char *logfile = (char *)getenv("ROOTPROOFLOGFILE");
   if (logfile && !getenv("ROOTPROOFDONOTREDIR")) {
      loc = (loglevel > 0) ? argv[1] : 0;
      if (loglevel > 0)
         fprintf(stderr,"%s: redirecting output to %s\n", argv[1], logfile);
      if (!(fLog = RedirectOutput(logfile, loc))) {
         fprintf(stderr,"%s: problems redirecting output to file %s\n", argv[1], logfile);
         exit(1);
      }
   }
   if (loglevel > 0)
      fprintf(stderr,"%s: output redirected to: %s\n",
             argv[1], (logfile ? logfile : "+++not redirected+++"));

#ifdef R__AFS
   // Init AFS, if required
   if (getenv("ROOTPROOFAFSCREDS")) {
      if (InitAFS(getenv("ROOTPROOFAFSCREDS"), loc) != 0) {
          fprintf(stderr,"%s: unable to initialize the AFS token\n", argv[1]);
      } else {
         if (loglevel > 0)
            fprintf(stderr,"%s: AFS token initialized\n", argv[1]);
      }
   }
#endif

   gROOT->SetBatch();
   TApplication *theApp = 0;

   // Enable autoloading
   gInterpreter->EnableAutoLoading();

   TString getter("GetTProofServ");
   TString prooflib = "libProof";
   if (argc > 2) {
      if (!strcmp(argv[2], "lite")) {
         // Lite version for local processing
         getter = "GetTProofServLite";
      } else if (!strcmp(argv[2], "xpd")) {
         // XPD: additionally load the appropriate library
         prooflib = "libProofx";
         getter = "GetTXProofServ";
      }
   }
   char *p = 0;
   if ((p = gSystem->DynamicPathName(prooflib, kTRUE))) {
      delete[] p;
      if (gSystem->Load(prooflib) == -1) {
         fprintf(stderr,"%s: can't load %s\n", argv[1], prooflib.Data());
         exit(1);
      }
   } else {
      fprintf(stderr,"%s: can't locate %s\n", argv[1], prooflib.Data());
      exit(1);
   }

   // Locate constructor
   Func_t f = gSystem->DynFindSymbol(prooflib, getter);
   if (f) {
      theApp = (TApplication *) (*((TProofServ_t)f))(&argc, argv, fLog);
   } else {
      fprintf(stderr,"%s: can't find %s\n", argv[1], getter.Data());
      exit(1);
   }

   // Ready to run
   if (loglevel > 0)
      fprintf(stderr,"%s: running the TProofServ application\n", argv[1]);

   theApp->Run();

#ifdef R__AFS
   // Cleanup
   if (gAFS)
      delete gAFS;
#endif

   // We can exit now
   gSystem->Exit(0);
}
<commit_msg>From Gerri: Enable the possibility to set hard and soft limits on the virtual memory used by the worker processes. This is done by calls to setrlimit with flag RLIMIT_AS. The two envs are called ROOTPROOFASSOFT and ROOTPROOFASHARD and the values are in MBs.<commit_after>// @(#)root/main:$Id$
// Author: Fons Rademakers   15/02/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// PMain                                                                //
//                                                                      //
// Main program used to create PROOF server application.                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <errno.h>

#ifdef WIN32
#include <io.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>

#include "RConfig.h"
#include "RConfigure.h"
#ifdef R__AFS
#include "TAFS.h"
#endif
#include "TApplication.h"
#include "TInterpreter.h"
#include "TROOT.h"
#include "TSystem.h"

// Macros to check memory ranges
#ifdef R__B64
#  define P_LONGOK(x) (1)
#else
#  define P_LONGOK(x) (x > LONG_MIN && x < LONG_MAX)
#endif
#define P_MBTOBYTES  (1024*1024)

static int gLogLevel = 0;

// Special type for the hook to the TXProofServ constructor, needed to avoid
// using the plugin manager
typedef TApplication *(*TProofServ_t)(Int_t *argc, char **argv, FILE *flog);

#ifdef R__AFS
// Special type for the hook to the TAFS constructor, needed to avoid
// using the plugin manager
typedef TAFS *(*TAFS_t)(const char *, const char *, Int_t);
// Instance of the AFS token class
static TAFS *gAFS = 0;
#endif

//______________________________________________________________________________
static void ReadPutEnvs(const char *envfile)
{
   // Read envs from file 'envfile' and add them to the env space

   // Check inputs
   if (!envfile || strlen(envfile) <= 0) return;

   // Open the file
   FILE *fenv = fopen(envfile, "r");
   if (!fenv) return;

   // Read lines
   char ln[4096];
   while (fgets(ln, sizeof(ln), fenv)) {
      int l = strlen(ln);
      // Strip '\n'
      if (l > 0 && ln[l-1] == '\n') { ln[l-1] = '\0'; l--; }
      // Skip comments or empty line
      if (l <= 0 || ln[0] == '#') continue;
      // Skip lines not in the form '<name>=<value>'
      if (!strchr(ln, '=')) continue;
      // Good line
      char *ev = new char[l+1];
      strcpy(ev, ln);
      putenv(ev);
   }

   // Close the file
   fclose(fenv);
}

//______________________________________________________________________________
static FILE *RedirectOutput(const char *logfile, const char *loc)
{
   // Redirect stdout to 'logfile'. This log file will be flushed to the
   // client or master after each command.
   // On success return a pointer to the open log file. Return 0 on failure.

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: enter: %s\n", loc, logfile);

   if (!logfile || strlen(logfile) <= 0) {
      fprintf(stderr,"%s: RedirectOutput: logfile path undefined\n", loc);
      return 0;
   }

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: reopen %s\n", loc, logfile);
   FILE *flog = freopen(logfile, "a", stdout);
   if (!flog) {
      fprintf(stderr,"%s: RedirectOutput: could not freopen stdout\n", loc);
      return 0;
   }

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: dup2 ...\n", loc);
   if ((dup2(fileno(stdout), fileno(stderr))) < 0) {
      fprintf(stderr,"%s: RedirectOutput: could not redirect stderr\n", loc);
      return 0;
   }

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: read open ...\n", loc);
   FILE *fLog = fopen(logfile, "r");
   if (!fLog) {
      fprintf(stderr,"%s: RedirectOutput: could not open logfile %s\n", loc, logfile);
      return 0;
   }

   if (loc)
      fprintf(stderr,"%s: RedirectOutput: done!\n", loc);
   // We are done
   return fLog;
}

//______________________________________________________________________________
static void SetMaxMemLimits(const char *prog)
{
   // Set limits on the address space (virtual memory) if required.

   const char *assoft = gSystem->Getenv("ROOTPROOFASSOFT");
   const char *ashard = gSystem->Getenv("ROOTPROOFASHARD");

   if (assoft || ashard) {
      struct rlimit aslim, aslimref;
      if (getrlimit(RLIMIT_AS, &aslimref) != 0) {
         fprintf(stderr,"%s: problems getting RLIMIT_AS values (errno: %d)\n", prog, errno);
         exit(1);
      }
      if (gLogLevel > 0)
         fprintf(stderr, "%s: memory limits currently set to %lld (soft) and %lld (hard) bytes\n",
                         prog, (Long64_t)aslimref.rlim_cur, (Long64_t)aslimref.rlim_max);
      aslim.rlim_cur = aslimref.rlim_cur;
      aslim.rlim_max = aslimref.rlim_max;
      if (assoft) {
         long rlim_cur = strtol(assoft, 0, 10);
         if (P_LONGOK(rlim_cur) && rlim_cur > 0)
            aslim.rlim_cur = (unsigned long) rlim_cur * P_MBTOBYTES;
      }
      if (ashard) {
         long rlim_max = strtol(ashard, 0, 10);
         if (P_LONGOK(rlim_max) && rlim_max > 0)
            aslim.rlim_max = (unsigned long) rlim_max * P_MBTOBYTES;
      }
      // Change the limits, if required
      if (aslim.rlim_cur != aslimref.rlim_cur || aslim.rlim_max != aslimref.rlim_max) {
         fprintf(stderr, "%s: setting memory limits to %lld (soft) and %lld (hard) bytes\n",
                         prog, (Long64_t)aslim.rlim_cur, (Long64_t)aslim.rlim_max);
         if (setrlimit(RLIMIT_AS, &aslim) != 0) {
            fprintf(stderr,"%s: problems setting RLIMIT_AS values (errno: %d)\n", prog, errno);
            exit(1);
         }
      }
   }
}

#ifdef R__AFS
//______________________________________________________________________________
static Int_t InitAFS(const char *fileafs, const char *loc)
{
   // Init AFS token using credentials at fileafs

   TString getter("GetTAFS");
   char *p = 0;
   TString afslib = "libAFSAuth";
   if ((p = gSystem->DynamicPathName(afslib, kTRUE))) {
      delete[] p;
      if (gSystem->Load(afslib) == -1) {
         if (loc)
            fprintf(stderr,"%s: can't load %s\n", loc, afslib.Data());
         return -1;
      }
   } else {
      if (loc)
         fprintf(stderr,"%s: can't locate %s\n", loc, afslib.Data());
      return -1;
   }

   // Locate constructor
   Func_t f = gSystem->DynFindSymbol(afslib, getter);
   if (f) {
      gAFS = (*((TAFS_t)f))(fileafs, 0, -1);
      if (!gAFS) {
         if (loc)
            fprintf(stderr,"%s: could not initialize a valid TAFS\n", loc);
         return -1;
      }
   } else {
      if (loc)
         fprintf(stderr,"%s: can't find %s\n", loc, getter.Data());
      return -1;
   }

   // Done
   return 0;
}
#endif

//______________________________________________________________________________
int main(int argc, char **argv)
{
   // PROOF server main program.

#ifdef R__DEBUG
   int debug = 1;
   while (debug)
      ;
#endif
   if (argc >= 6) {
      // Read and put system envs
      ReadPutEnvs(argv[5]);
   }

   gLogLevel = (argc >= 5) ? strtol(argv[4], 0, 10) : -1;
   if (gLogLevel < 0 && gSystem->Getenv("ROOTPROOFLOGLEVEL"))
      gLogLevel = atoi(gSystem->Getenv("ROOTPROOFLOGLEVEL"));
   if (gLogLevel > 0)
      fprintf(stderr,"%s: starting %s\n", argv[1], argv[0]);

   // Redirect the output
   FILE *fLog = 0;
   const char *loc = 0;
   const char *logfile = gSystem->Getenv("ROOTPROOFLOGFILE");
   if (logfile && !gSystem->Getenv("ROOTPROOFDONOTREDIR")) {
      loc = (gLogLevel > 0) ? argv[1] : 0;
      if (gLogLevel > 0)
         fprintf(stderr,"%s: redirecting output to %s\n", argv[1], logfile);
      if (!(fLog = RedirectOutput(logfile, loc))) {
         fprintf(stderr,"%s: problems redirecting output to file %s\n", argv[1], logfile);
         exit(1);
      }
   }
   if (gLogLevel > 0)
      fprintf(stderr,"%s: output redirected to: %s\n",
             argv[1], (logfile ? logfile : "+++not redirected+++"));

   SetMaxMemLimits(argv[1]);

#ifdef R__AFS
   // Init AFS, if required
   if (gSystem->Getenv("ROOTPROOFAFSCREDS")) {
      if (InitAFS(gSystem->Getenv("ROOTPROOFAFSCREDS"), loc) != 0) {
          fprintf(stderr,"%s: unable to initialize the AFS token\n", argv[1]);
      } else {
         if (gLogLevel > 0)
            fprintf(stderr,"%s: AFS token initialized\n", argv[1]);
      }
   }
#endif

   gROOT->SetBatch();
   TApplication *theApp = 0;

   // Enable autoloading
   gInterpreter->EnableAutoLoading();

   TString getter("GetTProofServ");
   TString prooflib = "libProof";
   if (argc > 2) {
      if (!strcmp(argv[2], "lite")) {
         // Lite version for local processing
         getter = "GetTProofServLite";
      } else if (!strcmp(argv[2], "xpd")) {
         // XPD: additionally load the appropriate library
         prooflib = "libProofx";
         getter = "GetTXProofServ";
      }
   }
   char *p = 0;
   if ((p = gSystem->DynamicPathName(prooflib, kTRUE))) {
      delete[] p;
      if (gSystem->Load(prooflib) == -1) {
         fprintf(stderr,"%s: can't load %s\n", argv[1], prooflib.Data());
         exit(1);
      }
   } else {
      fprintf(stderr,"%s: can't locate %s\n", argv[1], prooflib.Data());
      exit(1);
   }

   // Locate constructor
   Func_t f = gSystem->DynFindSymbol(prooflib, getter);
   if (f) {
      theApp = (TApplication *) (*((TProofServ_t)f))(&argc, argv, fLog);
   } else {
      fprintf(stderr,"%s: can't find %s\n", argv[1], getter.Data());
      exit(1);
   }

   // Ready to run
   if (gLogLevel > 0)
      fprintf(stderr,"%s: running the TProofServ application\n", argv[1]);

   theApp->Run();

#ifdef R__AFS
   // Cleanup
   if (gAFS)
      delete gAFS;
#endif

   // We can exit now
   gSystem->Exit(0);
}
<|endoftext|>