<commit_before>/*
Copyright (C) 2016 - Gbor "Razzie" Grzsny

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
*/

#pragma once

#include <array>
#include <cstdint>
#include <iosfwd>
#include <random>
#include <type_traits>

namespace raz
{
	/*
	 * RandomGenerator is based on the xorshift128+ algorithm
	 * https://en.wikipedia.org/wiki/Xorshift
	 */
	class RandomGenerator
	{
	public:
		typedef uint64_t result_type;
		static constexpr result_type default_seed = 1;

		RandomGenerator(result_type value = default_seed)
		{
			seed(value);
		}

		template<class Sseq>
		RandomGenerator(Sseq& seq)
		{
			seed(seq);
		}

		RandomGenerator(const RandomGenerator& other) :
			m_state(other.m_state)
		{
		}

		RandomGenerator& operator=(const RandomGenerator& other)
		{
			m_state = other.m_state;
			return *this;
		}

		void seed(result_type value = default_seed)
		{
			m_state[0] = value;
			m_state[1] = 0;
		}

		template<class Sseq>
		void seed(Sseq& seq)
		{
			seq.generate(m_state.begin(), m_state.end());
		}

		result_type operator()()
		{
			uint64_t x = m_state[0];
			uint64_t const y = m_state[1];
			m_state[0] = y;
			x ^= x << 23; // a
			m_state[1] = x ^ y ^ (x >> 17) ^ (y >> 26); // b, c
			return (m_state[1] + y);
		}

		void discard(unsigned long long z)
		{
			for (unsigned long long i = 0; i < z; ++i)
			{
				uint64_t x = m_state[0];
				uint64_t const y = m_state[1];
				m_state[0] = y;
				x ^= x << 23; // a
				m_state[1] = x ^ y ^ (x >> 17) ^ (y >> 26); // b, c
			}
		}

		bool operator==(const RandomGenerator& other) const
		{
			return (m_state == other.m_state);
		}

		bool operator!=(const RandomGenerator& other) const
		{
			return (m_state != other.m_state);
		}

		template<class Serializer>
		void operator()(Serializer& serializer)
		{
			serializer(m_state[0])(m_state[1]);
		}

#pragma push_macro("__raz")
#undef min
#undef max
		static constexpr result_type min()
		{
			return (0);
		}

		static constexpr result_type max()
		{
			return ((result_type)-1);
		}
#pragma pop_macro("__raz")

		template<class CharT, class Traits>
		friend std::basic_ostream<CharT, Traits>&
			operator<<(std::basic_ostream<CharT, Traits>& ost, const RandomGenerator& gen)
		{
			return (ost << gen.m_state[0] << " " << gen.m_state[1]);
		}

		template<class CharT, class Traits>
		friend std::basic_istream<CharT, Traits>&
			operator>>(std::basic_istream<CharT, Traits>& ist, RandomGenerator& gen)
		{
			return (ist >> gen.m_state[0] >> gen.m_state[1]);
		}

	private:
		std::array<uint64_t, 2> m_state;
	};

	template<class Generator>
	class RandomDistributor
	{
	public:
		RandomDistributor(Generator& generator) :
			m_generator(&generator)
		{
		}

		RandomDistributor(const RandomDistributor& other) :
			m_generator(other.m_generator)
		{
		}

		RandomDistributor& operator=(const RandomDistributor& other) = default;

		template<class IntType>
		std::enable_if_t<std::is_integral<IntType>::value, IntType>
			operator()(IntType min_value, IntType max_value)
		{
			std::uniform_int_distribution<IntType> dist(min_value, max_value);
			return dist(*m_generator);
		}

		template<class RealType>
		std::enable_if_t<std::is_floating_point<RealType>::value, RealType>
			operator()(RealType min_value, RealType max_value)
		{
			std::uniform_real_distribution<RealType> dist(min_value, max_value);
			return dist(*m_generator);
		}

	private:
		Generator* m_generator;
	};

	class Random : public RandomGenerator, public RandomDistributor<RandomGenerator>
	{
	public:
		Random(result_type value = default_seed) :
			RandomGenerator(value),
			RandomDistributor<RandomGenerator>(*this)
		{
		}

		template<class Sseq>
		Random(Sseq& seq) :
			RandomGenerator(seq),
			RandomDistributor<RandomGenerator>(*this)
		{
		}

		Random(const RandomGenerator& gen) :
			RandomGenerator(gen),
			RandomDistributor<RandomGenerator>(*this)
		{
		}

		Random& operator=(const RandomGenerator& gen)
		{
			RandomGenerator::operator=(gen);
			return *this;
		}
	};
}
<commit_msg>Fixed a constructor bug in Random<commit_after>/*
Copyright (C) 2016 - Gbor "Razzie" Grzsny

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
*/

#pragma once

#include <array>
#include <cstdint>
#include <iosfwd>
#include <random>
#include <type_traits>

namespace raz
{
	/*
	 * RandomGenerator is based on the xorshift128+ algorithm
	 * https://en.wikipedia.org/wiki/Xorshift
	 */
	class RandomGenerator
	{
	public:
		typedef uint64_t result_type;
		static constexpr result_type default_seed = 1;

		RandomGenerator(result_type value = default_seed)
		{
			seed(value);
		}

		template<class Sseq>
		RandomGenerator(Sseq& seq)
		{
			seed(seq);
		}

		RandomGenerator(const RandomGenerator& other) :
			m_state(other.m_state)
		{
		}

		RandomGenerator& operator=(const RandomGenerator& other)
		{
			m_state = other.m_state;
			return *this;
		}

		void seed(result_type value = default_seed)
		{
			m_state[0] = value;
			m_state[1] = 0;
		}

		template<class Sseq>
		void seed(Sseq& seq)
		{
			seq.generate(m_state.begin(), m_state.end());
		}

		result_type operator()()
		{
			uint64_t x = m_state[0];
			uint64_t const y = m_state[1];
			m_state[0] = y;
			x ^= x << 23; // a
			m_state[1] = x ^ y ^ (x >> 17) ^ (y >> 26); // b, c
			return (m_state[1] + y);
		}

		void discard(unsigned long long z)
		{
			for (unsigned long long i = 0; i < z; ++i)
			{
				uint64_t x = m_state[0];
				uint64_t const y = m_state[1];
				m_state[0] = y;
				x ^= x << 23; // a
				m_state[1] = x ^ y ^ (x >> 17) ^ (y >> 26); // b, c
			}
		}

		bool operator==(const RandomGenerator& other) const
		{
			return (m_state == other.m_state);
		}

		bool operator!=(const RandomGenerator& other) const
		{
			return (m_state != other.m_state);
		}

		template<class Serializer>
		void operator()(Serializer& serializer)
		{
			serializer(m_state[0])(m_state[1]);
		}

#pragma push_macro("__raz")
#undef min
#undef max
		static constexpr result_type min()
		{
			return (0);
		}

		static constexpr result_type max()
		{
			return ((result_type)-1);
		}
#pragma pop_macro("__raz")

		template<class CharT, class Traits>
		friend std::basic_ostream<CharT, Traits>&
			operator<<(std::basic_ostream<CharT, Traits>& ost, const RandomGenerator& gen)
		{
			return (ost << gen.m_state[0] << " " << gen.m_state[1]);
		}

		template<class CharT, class Traits>
		friend std::basic_istream<CharT, Traits>&
			operator>>(std::basic_istream<CharT, Traits>& ist, RandomGenerator& gen)
		{
			return (ist >> gen.m_state[0] >> gen.m_state[1]);
		}

	private:
		std::array<uint64_t, 2> m_state;
	};

	template<class Generator>
	class RandomDistributor
	{
	public:
		RandomDistributor(Generator& generator) :
			m_generator(&generator)
		{
		}

		RandomDistributor(const RandomDistributor& other) :
			m_generator(other.m_generator)
		{
		}

		RandomDistributor& operator=(const RandomDistributor& other)
		{
			m_generator = other.m_generator;
			return *this;
		}

		template<class IntType>
		std::enable_if_t<std::is_integral<IntType>::value, IntType>
			operator()(IntType min_value, IntType max_value)
		{
			std::uniform_int_distribution<IntType> dist(min_value, max_value);
			return dist(*m_generator);
		}

		template<class RealType>
		std::enable_if_t<std::is_floating_point<RealType>::value, RealType>
			operator()(RealType min_value, RealType max_value)
		{
			std::uniform_real_distribution<RealType> dist(min_value, max_value);
			return dist(*m_generator);
		}

	private:
		Generator* m_generator;
	};

	class Random : public RandomGenerator, public RandomDistributor<RandomGenerator>
	{
	public:
		Random(result_type value = default_seed) :
			RandomGenerator(value),
			RandomDistributor<RandomGenerator>(*static_cast<RandomGenerator*>(this))
		{
		}

		template<class Sseq>
		Random(Sseq& seq) :
			RandomGenerator(seq),
			RandomDistributor<RandomGenerator>(*static_cast<RandomGenerator*>(this))
		{
		}

		Random(const RandomGenerator& gen) :
			RandomGenerator(gen),
			RandomDistributor<RandomGenerator>(*static_cast<RandomGenerator*>(this))
		{
		}

		Random& operator=(const RandomGenerator& gen)
		{
			RandomGenerator::operator=(gen);
			return *this;
		}

		using RandomDistributor<RandomGenerator>::operator();
	};
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef _SV_LSTBOX_HXX
#define _SV_LSTBOX_HXX

#include <vcl/dllapi.h>
#include <vcl/ctrl.hxx>
#include <vcl/lstbox.h>

class Image;
class ImplListBox;
class ImplListBoxFloatingWindow;
class ImplBtn;
class ImplWin;

// --------------------------------------------------------------------
//  - ListBox -
// --------------------------------------------------------------------

class VCL_DLLPUBLIC ListBox : public Control
{
private:
    ImplListBox*                mpImplLB;
    ImplListBoxFloatingWindow*  mpFloatWin;
    ImplWin*                    mpImplWin;
    ImplBtn*                    mpBtn;
    sal_uInt16                  mnDDHeight;
    sal_uInt16                  mnSaveValue;
    sal_Int32 m_nMaxWidthChars;
    Link                        maSelectHdl;
    Link                        maDoubleClickHdl;
    sal_uInt16                  mnLineCount;

    /// bitfield
    bool            mbDDAutoSize : 1;
    bool            mbEdgeBlending : 1;

private:
    SAL_DLLPRIVATE void    ImplInitListBoxData();

    DECL_DLLPRIVATE_LINK(  ImplSelectHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplScrollHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplCancelHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplDoubleClickHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplClickBtnHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplPopupModeEndHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplSelectionChangedHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplUserDrawHdl, UserDrawEvent* );

protected:
    using Window::ImplInit;
    SAL_DLLPRIVATE void    ImplInit( Window* pParent, WinBits nStyle );
    SAL_DLLPRIVATE WinBits ImplInitStyle( WinBits nStyle );
    SAL_DLLPRIVATE void    ImplLoadRes( const ResId& rResId );
    sal_Bool                IsDropDownBox() const { return mpFloatWin ? sal_True : sal_False; }

protected:
    explicit            ListBox( WindowType nType );

    virtual void        FillLayoutData() const;

public:
    explicit            ListBox( Window* pParent, WinBits nStyle = WB_BORDER );
    explicit            ListBox( Window* pParent, const ResId& );
    virtual             ~ListBox();

    virtual void        Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags );
    virtual void        Resize();
    virtual long        PreNotify( NotifyEvent& rNEvt );
    virtual void        StateChanged( StateChangedType nType );
    virtual void        DataChanged( const DataChangedEvent& rDCEvt );
    virtual void        UserDraw( const UserDrawEvent& rUDEvt );

    virtual void        Select();
    virtual void        DoubleClick();
    virtual void        GetFocus();
    virtual void        LoseFocus();
    virtual Window*     GetPreferredKeyInputWindow();

    virtual const Wallpaper& GetDisplayBackground() const;

    virtual void        setPosSizePixel( long nX, long nY,
                                         long nWidth, long nHeight, sal_uInt16 nFlags = WINDOW_POSSIZE_ALL );
    void                SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
                        { Control::SetPosSizePixel( rNewPos, rNewSize ); }
    void                SetDropDownSizePixel( const Size& rNewSize )
    { if( IsDropDownBox() ) setPosSizePixel( 0, 0, rNewSize.Width(), rNewSize.Height(), WINDOW_POSSIZE_SIZE | WINDOW_POSSIZE_DROPDOWN ); }

    Rectangle           GetDropDownPosSizePixel() const;

    void AdaptDropDownLineCountToMaximum();
    void                SetDropDownLineCount( sal_uInt16 nLines );
    sal_uInt16          GetDropDownLineCount() const;

    void                EnableAutoSize( bool bAuto );
    bool                IsAutoSizeEnabled() const { return mbDDAutoSize; }

    void                EnableDDAutoWidth( sal_Bool b );

    virtual sal_uInt16      InsertEntry( const OUString& rStr, sal_uInt16 nPos = LISTBOX_APPEND );
    virtual sal_uInt16      InsertEntry( const Image& rImage, sal_uInt16 nPos = LISTBOX_APPEND );
    virtual sal_uInt16      InsertEntry( const OUString& rStr, const Image& rImage, sal_uInt16 nPos = LISTBOX_APPEND );
    virtual void        RemoveEntry( const OUString& rStr );
    virtual void        RemoveEntry( sal_uInt16 nPos );

    virtual void        Clear();

    virtual sal_uInt16      GetEntryPos( const OUString& rStr ) const;
    virtual sal_uInt16      GetEntryPos( const void* pData ) const;
            Image       GetEntryImage( sal_uInt16 nPos ) const;
    virtual OUString    GetEntry( sal_uInt16 nPos ) const;
    virtual sal_uInt16      GetEntryCount() const;

    virtual void        SelectEntry( const OUString& rStr, sal_Bool bSelect = sal_True );
    virtual void        SelectEntryPos( sal_uInt16 nPos, sal_Bool bSelect = sal_True );

    virtual sal_uInt16  GetSelectEntryCount() const;
    virtual OUString    GetSelectEntry( sal_uInt16 nSelIndex = 0 ) const;
    virtual sal_uInt16  GetSelectEntryPos( sal_uInt16 nSelIndex = 0 ) const;

    virtual bool        IsEntrySelected(const OUString& rStr) const;
    virtual sal_Bool        IsEntryPosSelected( sal_uInt16 nPos ) const;
    virtual void        SetNoSelection();

    void                SetEntryData( sal_uInt16 nPos, void* pNewData );
    void*               GetEntryData( sal_uInt16 nPos ) const;

    /** this methods stores a combination of flags from the
        LISTBOX_ENTRY_FLAG_* defines at the given entry.
        See description of the possible LISTBOX_ENTRY_FLAG_* flags
        for details.
        Do not use these flags for user data as they are reserved
        to change the internal behaviour of the ListBox implementation
        for specific entries.
    */
    void            SetEntryFlags( sal_uInt16 nPos, long nFlags );

    /** this methods gets the current combination of flags from the
        LISTBOX_ENTRY_FLAG_* defines from the given entry.
        See description of the possible LISTBOX_ENTRY_FLAG_* flags
        for details.
    */
    long            GetEntryFlags( sal_uInt16 nPos ) const;

    void            SetTopEntry( sal_uInt16 nPos );
    sal_uInt16          GetTopEntry() const;

    void            SaveValue() { mnSaveValue = GetSelectEntryPos(); }
    sal_uInt16          GetSavedValue() const { return mnSaveValue; }

    void            SetSeparatorPos( sal_uInt16 n = LISTBOX_ENTRY_NOTFOUND );
    sal_uInt16          GetSeparatorPos() const;

    sal_Bool            IsTravelSelect() const;
    sal_Bool            IsInDropDown() const;
    void            ToggleDropDown();

    void            EnableMultiSelection( sal_Bool bMulti, sal_Bool bStackSelection );
    void            EnableMultiSelection( sal_Bool bMulti );
    sal_Bool            IsMultiSelectionEnabled() const;

    void            SetReadOnly( sal_Bool bReadOnly = sal_True );
    sal_Bool            IsReadOnly() const;

    Rectangle       GetBoundingRectangle( sal_uInt16 nItem ) const;

    void            SetUserItemSize( const Size& rSz );

    void            EnableUserDraw( sal_Bool bUserDraw );

    void            DrawEntry( const UserDrawEvent& rEvt, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos = sal_False );

    void            SetSelectHdl( const Link& rLink )       { maSelectHdl = rLink; }
    const Link&     GetSelectHdl() const                    { return maSelectHdl; }
    void            SetDoubleClickHdl( const Link& rLink )  { maDoubleClickHdl = rLink; }
    const Link&     GetDoubleClickHdl() const               { return maDoubleClickHdl; }

    Size            CalcSubEditSize() const;    //size of area inside lstbox, i.e. no scrollbar/dropdown
    Size            CalcMinimumSize() const;    //size of lstbox area, i.e. including scrollbar/dropdown
    virtual Size    GetOptimalSize() const;
    Size            CalcAdjustedSize( const Size& rPrefSize ) const;
    Size            CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const;
    void            GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const;

    sal_uInt16          GetDisplayLineCount() const;

    void            EnableMirroring();

    bool GetEdgeBlending() const { return mbEdgeBlending; }
    void SetEdgeBlending(bool bNew);

    /** checks whether a certain point lies within the bounds of
        a listbox item and returns the item as well as the character position
        the point is at.

If the point is inside an item the item pos is put into rPos and
        the item-relative character index is returned. If the point is not inside
        an item -1 is returned and rPos is unchanged.

        @param rPoint
        tells the point for which an item is requested.

        @param rPos
        gets the item at the specified point rPoint

        @returns
        the item-relative character index at point rPos or -1
        if no item is at that point.
     */
    using Control::GetIndexForPoint;
    long GetIndexForPoint( const Point& rPoint, sal_uInt16& rPos ) const;

    sal_Int32 getMaxWidthChars() const { return m_nMaxWidthChars; }
    void setMaxWidthChars(sal_Int32 nWidth);

    virtual bool set_property(const OString &rKey, const OString &rValue);
};

// ----------------
// - MultiListBox -
// ----------------

class VCL_DLLPUBLIC MultiListBox : public ListBox
{
public:
    using ListBox::SaveValue;
    using ListBox::GetSavedValue;
private:
    // Bei MultiListBox nicht erlaubt...
    void            SaveValue();
    sal_uInt16          GetSavedValue();

public:
    explicit        MultiListBox( Window* pParent, WinBits nStyle = 0 );
    explicit        MultiListBox( Window* pParent, const ResId& rResId );
};

#endif  // _SV_LSTBOX_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Convert vcl::ListBox::GetEntryPos from XubString to OUString<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef _SV_LSTBOX_HXX
#define _SV_LSTBOX_HXX

#include <vcl/dllapi.h>
#include <vcl/ctrl.hxx>
#include <vcl/lstbox.h>

class Image;
class ImplListBox;
class ImplListBoxFloatingWindow;
class ImplBtn;
class ImplWin;

// --------------------------------------------------------------------
//  - ListBox -
// --------------------------------------------------------------------

class VCL_DLLPUBLIC ListBox : public Control
{
private:
    ImplListBox*                mpImplLB;
    ImplListBoxFloatingWindow*  mpFloatWin;
    ImplWin*                    mpImplWin;
    ImplBtn*                    mpBtn;
    sal_uInt16                  mnDDHeight;
    sal_uInt16                  mnSaveValue;
    sal_Int32 m_nMaxWidthChars;
    Link                        maSelectHdl;
    Link                        maDoubleClickHdl;
    sal_uInt16                  mnLineCount;

    /// bitfield
    bool            mbDDAutoSize : 1;
    bool            mbEdgeBlending : 1;

private:
    SAL_DLLPRIVATE void    ImplInitListBoxData();

    DECL_DLLPRIVATE_LINK(  ImplSelectHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplScrollHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplCancelHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplDoubleClickHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplClickBtnHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplPopupModeEndHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplSelectionChangedHdl, void* );
    DECL_DLLPRIVATE_LINK(  ImplUserDrawHdl, UserDrawEvent* );

protected:
    using Window::ImplInit;
    SAL_DLLPRIVATE void    ImplInit( Window* pParent, WinBits nStyle );
    SAL_DLLPRIVATE WinBits ImplInitStyle( WinBits nStyle );
    SAL_DLLPRIVATE void    ImplLoadRes( const ResId& rResId );
    sal_Bool                IsDropDownBox() const { return mpFloatWin ? sal_True : sal_False; }

protected:
    explicit            ListBox( WindowType nType );

    virtual void        FillLayoutData() const;

public:
    explicit            ListBox( Window* pParent, WinBits nStyle = WB_BORDER );
    explicit            ListBox( Window* pParent, const ResId& );
    virtual             ~ListBox();

    virtual void        Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags );
    virtual void        Resize();
    virtual long        PreNotify( NotifyEvent& rNEvt );
    virtual void        StateChanged( StateChangedType nType );
    virtual void        DataChanged( const DataChangedEvent& rDCEvt );
    virtual void        UserDraw( const UserDrawEvent& rUDEvt );

    virtual void        Select();
    virtual void        DoubleClick();
    virtual void        GetFocus();
    virtual void        LoseFocus();
    virtual Window*     GetPreferredKeyInputWindow();

    virtual const Wallpaper& GetDisplayBackground() const;

    virtual void        setPosSizePixel( long nX, long nY,
                                         long nWidth, long nHeight, sal_uInt16 nFlags = WINDOW_POSSIZE_ALL );
    void                SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
                        { Control::SetPosSizePixel( rNewPos, rNewSize ); }
    void                SetDropDownSizePixel( const Size& rNewSize )
    { if( IsDropDownBox() ) setPosSizePixel( 0, 0, rNewSize.Width(), rNewSize.Height(), WINDOW_POSSIZE_SIZE | WINDOW_POSSIZE_DROPDOWN ); }

    Rectangle           GetDropDownPosSizePixel() const;

    void AdaptDropDownLineCountToMaximum();
    void                SetDropDownLineCount( sal_uInt16 nLines );
    sal_uInt16          GetDropDownLineCount() const;

    void                EnableAutoSize( bool bAuto );
    bool                IsAutoSizeEnabled() const { return mbDDAutoSize; }

    void                EnableDDAutoWidth( sal_Bool b );

    virtual sal_uInt16      InsertEntry( const OUString& rStr, sal_uInt16 nPos = LISTBOX_APPEND );
    virtual sal_uInt16      InsertEntry( const Image& rImage, sal_uInt16 nPos = LISTBOX_APPEND );
    virtual sal_uInt16      InsertEntry( const OUString& rStr, const Image& rImage, sal_uInt16 nPos = LISTBOX_APPEND );
    virtual void        RemoveEntry( const OUString& rStr );
    virtual void        RemoveEntry( sal_uInt16 nPos );

    virtual void        Clear();

    virtual sal_uInt16      GetEntryPos( const OUString& rStr ) const;
    virtual sal_uInt16      GetEntryPos( const void* pData ) const;
            Image       GetEntryImage( sal_uInt16 nPos ) const;
    virtual OUString    GetEntry( sal_uInt16 nPos ) const;
    virtual sal_uInt16      GetEntryCount() const;

    virtual void        SelectEntry( const OUString& rStr, sal_Bool bSelect = sal_True );
    virtual void        SelectEntryPos( sal_uInt16 nPos, sal_Bool bSelect = sal_True );

    virtual sal_uInt16  GetSelectEntryCount() const;
    virtual OUString    GetSelectEntry( sal_uInt16 nSelIndex = 0 ) const;
    virtual sal_uInt16  GetSelectEntryPos( sal_uInt16 nSelIndex = 0 ) const;

    virtual bool        IsEntrySelected(const OUString& rStr) const;
    virtual sal_Bool    IsEntryPosSelected( sal_uInt16 nPos ) const;
    virtual void        SetNoSelection();

    void                SetEntryData( sal_uInt16 nPos, void* pNewData );
    void*               GetEntryData( sal_uInt16 nPos ) const;

    /** this methods stores a combination of flags from the
        LISTBOX_ENTRY_FLAG_* defines at the given entry.
        See description of the possible LISTBOX_ENTRY_FLAG_* flags
        for details.
        Do not use these flags for user data as they are reserved
        to change the internal behaviour of the ListBox implementation
        for specific entries.
    */
    void            SetEntryFlags( sal_uInt16 nPos, long nFlags );

    /** this methods gets the current combination of flags from the
        LISTBOX_ENTRY_FLAG_* defines from the given entry.
        See description of the possible LISTBOX_ENTRY_FLAG_* flags
        for details.
    */
    long            GetEntryFlags( sal_uInt16 nPos ) const;

    void            SetTopEntry( sal_uInt16 nPos );
    sal_uInt16          GetTopEntry() const;

    void            SaveValue() { mnSaveValue = GetSelectEntryPos(); }
    sal_uInt16          GetSavedValue() const { return mnSaveValue; }

    void            SetSeparatorPos( sal_uInt16 n = LISTBOX_ENTRY_NOTFOUND );
    sal_uInt16          GetSeparatorPos() const;

    sal_Bool            IsTravelSelect() const;
    sal_Bool            IsInDropDown() const;
    void            ToggleDropDown();

    void            EnableMultiSelection( sal_Bool bMulti, sal_Bool bStackSelection );
    void            EnableMultiSelection( sal_Bool bMulti );
    sal_Bool            IsMultiSelectionEnabled() const;

    void            SetReadOnly( sal_Bool bReadOnly = sal_True );
    sal_Bool            IsReadOnly() const;

    Rectangle       GetBoundingRectangle( sal_uInt16 nItem ) const;

    void            SetUserItemSize( const Size& rSz );

    void            EnableUserDraw( sal_Bool bUserDraw );

    void            DrawEntry( const UserDrawEvent& rEvt, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos = sal_False );

    void            SetSelectHdl( const Link& rLink )       { maSelectHdl = rLink; }
    const Link&     GetSelectHdl() const                    { return maSelectHdl; }
    void            SetDoubleClickHdl( const Link& rLink )  { maDoubleClickHdl = rLink; }
    const Link&     GetDoubleClickHdl() const               { return maDoubleClickHdl; }

    Size            CalcSubEditSize() const;    //size of area inside lstbox, i.e. no scrollbar/dropdown
    Size            CalcMinimumSize() const;    //size of lstbox area, i.e. including scrollbar/dropdown
    virtual Size    GetOptimalSize() const;
    Size            CalcAdjustedSize( const Size& rPrefSize ) const;
    Size            CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const;
    void            GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const;

    sal_uInt16          GetDisplayLineCount() const;

    void            EnableMirroring();

    bool GetEdgeBlending() const { return mbEdgeBlending; }
    void SetEdgeBlending(bool bNew);

    /** checks whether a certain point lies within the bounds of
        a listbox item and returns the item as well as the character position
        the point is at.

If the point is inside an item the item pos is put into rPos and
        the item-relative character index is returned. If the point is not inside
        an item -1 is returned and rPos is unchanged.

        @param rPoint
        tells the point for which an item is requested.

        @param rPos
        gets the item at the specified point rPoint

        @returns
        the item-relative character index at point rPos or -1
        if no item is at that point.
     */
    using Control::GetIndexForPoint;
    long GetIndexForPoint( const Point& rPoint, sal_uInt16& rPos ) const;

    sal_Int32 getMaxWidthChars() const { return m_nMaxWidthChars; }
    void setMaxWidthChars(sal_Int32 nWidth);

    virtual bool set_property(const OString &rKey, const OString &rValue);
};

// ----------------
// - MultiListBox -
// ----------------

class VCL_DLLPUBLIC MultiListBox : public ListBox
{
public:
    using ListBox::SaveValue;
    using ListBox::GetSavedValue;
private:
    // Bei MultiListBox nicht erlaubt...
    void            SaveValue();
    sal_uInt16          GetSavedValue();

public:
    explicit        MultiListBox( Window* pParent, WinBits nStyle = 0 );
    explicit        MultiListBox( Window* pParent, const ResId& rResId );

};

#endif  // _SV_LSTBOX_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "rapid_pbd/action_executor.h"

#include <string>

#include "actionlib/client/simple_action_client.h"
#include "actionlib/server/simple_action_server.h"
#include "control_msgs/FollowJointTrajectoryAction.h"
#include "control_msgs/GripperCommandAction.h"
#include "rapid_pbd_msgs/SegmentSurfacesAction.h"
#include "ros/ros.h"
#include "visualization_msgs/MarkerArray.h"

#include "rapid_pbd/action_names.h"
#include "rapid_pbd/action_utils.h"
#include "rapid_pbd/errors.h"
#include "rapid_pbd/motion_planning.h"
#include "rapid_pbd/visualizer.h"
#include "rapid_pbd/world.h"

using actionlib::SimpleActionClient;
using actionlib::SimpleClientGoalState;
using control_msgs::FollowJointTrajectoryAction;
using rapid_pbd_msgs::Action;

namespace msgs = rapid_pbd_msgs;

namespace rapid {
namespace pbd {
ActionExecutor::ActionExecutor(const Action& action,
                               ActionClients* action_clients,
                               MotionPlanning* motion_planning, World* world,
                               const RobotConfig& robot_config,
                               const RuntimeVisualizer& runtime_viz)
    : action_(action),
      clients_(action_clients),
      motion_planning_(motion_planning),
      world_(world),
      robot_config_(robot_config),
      runtime_viz_(runtime_viz) {}

bool ActionExecutor::IsValid(const Action& action) {
  if (action.type == Action::ACTUATE_GRIPPER) {
    if (action.actuator_group == Action::GRIPPER ||
        action.actuator_group == Action::LEFT_GRIPPER ||
        action.actuator_group == Action::RIGHT_GRIPPER) {
    } else {
      PublishInvalidGroupError(action);
      return false;
    }
  } else if (action.type == Action::MOVE_TO_JOINT_GOAL) {
    if (action.actuator_group == Action::ARM ||
        action.actuator_group == Action::LEFT_ARM ||
        action.actuator_group == Action::RIGHT_ARM ||
        action.actuator_group == Action::HEAD) {
    } else {
      PublishInvalidGroupError(action);
      return false;
    }
    if (!HasJointValues(action)) {
      return false;
    }
  } else if (action.type == Action::MOVE_TO_CARTESIAN_GOAL) {
    if (action.actuator_group == Action::ARM ||
        action.actuator_group == Action::LEFT_ARM ||
        action.actuator_group == Action::RIGHT_ARM ||
        action.actuator_group == Action::HEAD) {
    } else {
      PublishInvalidGroupError(action);
      return false;
    }
  } else if (action.type == Action::DETECT_TABLETOP_OBJECTS) {
  } else if (action.type == Action::FIND_CUSTOM_LANDMARK) {
  } else {
    ROS_ERROR("Invalid action type: \"%s\"", action.type.c_str());
    return false;
  }
  return true;
}

std::string ActionExecutor::Start() {
  if (action_.type == Action::ACTUATE_GRIPPER) {
    ActuateGripper();
  } else if (action_.type == Action::MOVE_TO_JOINT_GOAL) {
    std::vector<std::string> joint_names;
    std::vector<double> joint_positions;
    GetJointPositions(action_, &joint_names, &joint_positions);
    return motion_planning_->AddJointGoal(joint_names, joint_positions);
  } else if (action_.type == Action::MOVE_TO_CARTESIAN_GOAL) {
    std::vector<std::string> joint_names;
    std::vector<double> joint_positions;
    if (HasJointValues(action_)) {
      GetJointPositions(action_, &joint_names, &joint_positions);
    }
    return motion_planning_->AddPoseGoal(action_.actuator_group, action_.pose,
                                         action_.landmark, joint_names,
                                         joint_positions);
  } else if (action_.type == Action::DETECT_TABLETOP_OBJECTS) {
    DetectTabletopObjects();
  }
  return "";
}

bool ActionExecutor::IsDone(std::string* error) const {
  if (action_.type == Action::ACTUATE_GRIPPER) {
    if (action_.actuator_group == Action::GRIPPER) {
      return clients_->gripper_client.getState().isDone();
    } else if (action_.actuator_group == Action::LEFT_GRIPPER) {
      return clients_->l_gripper_client.getState().isDone();
    } else if (action_.actuator_group == Action::RIGHT_GRIPPER) {
      return clients_->r_gripper_client.getState().isDone();
    }
  } else if (action_.type == Action::DETECT_TABLETOP_OBJECTS) {
    bool done = clients_->surface_segmentation_client.getState().isDone();
    if (done) {
      msgs::SegmentSurfacesResultConstPtr result =
          clients_->surface_segmentation_client.getResult();
      if (result) {
        if (result->landmarks.size() == 0) {
          *error = errors::kNoLandmarksDetected;
        }
        world_->surface_box_landmarks = result->landmarks;
        runtime_viz_.PublishSurfaceBoxes(result->landmarks);
      } else {
        ROS_ERROR("Surface segmentation result pointer was null!");
        *error = "Surface segmentation result pointer was null!";
        return false;
      }
    }
    return done;
  }
  return true;
}

void ActionExecutor::Cancel() {
  if (action_.type == Action::ACTUATE_GRIPPER) {
    if (action_.actuator_group == Action::GRIPPER) {
      clients_->gripper_client.cancelAllGoals();
    } else if (action_.actuator_group == Action::LEFT_GRIPPER) {
      clients_->l_gripper_client.cancelAllGoals();
    } else if (action_.actuator_group == Action::RIGHT_GRIPPER) {
      clients_->r_gripper_client.cancelAllGoals();
    }
  } else if (action_.type == Action::DETECT_TABLETOP_OBJECTS) {
    clients_->surface_segmentation_client.cancelAllGoals();
  }
}

void ActionExecutor::ActuateGripper() {
  control_msgs::GripperCommandGoal gripper_goal;
  gripper_goal.command = action_.gripper_command;

  SimpleActionClient<control_msgs::GripperCommandAction>* client;
  if (action_.actuator_group == Action::GRIPPER) {
    client = &clients_->gripper_client;
  } else if (action_.actuator_group == Action::LEFT_GRIPPER) {
    client = &clients_->l_gripper_client;
  } else if (action_.actuator_group == Action::RIGHT_GRIPPER) {
    client = &clients_->r_gripper_client;
  } else {
    return;
  }
  client->sendGoal(gripper_goal);
}

void ActionExecutor::DetectTabletopObjects() {
  rapid_pbd_msgs::SegmentSurfacesGoal goal;
  goal.save_cloud = false;
  clients_->surface_segmentation_client.sendGoal(goal);
}

void ActionExecutor::PublishInvalidGroupError(const Action& action) {
  ROS_ERROR("Invalid actuator_group \"%s\" for action type \"%s\".",
            action.actuator_group.c_str(), action.type.c_str());
}
}  // namespace pbd
}  // namespace rapid
<commit_msg>Fixed head motions not execution.<commit_after>#include "rapid_pbd/action_executor.h"

#include <string>

#include "actionlib/client/simple_action_client.h"
#include "actionlib/server/simple_action_server.h"
#include "control_msgs/FollowJointTrajectoryAction.h"
#include "control_msgs/GripperCommandAction.h"
#include "rapid_pbd_msgs/SegmentSurfacesAction.h"
#include "ros/ros.h"
#include "visualization_msgs/MarkerArray.h"

#include "rapid_pbd/action_names.h"
#include "rapid_pbd/action_utils.h"
#include "rapid_pbd/errors.h"
#include "rapid_pbd/motion_planning.h"
#include "rapid_pbd/visualizer.h"
#include "rapid_pbd/world.h"

using actionlib::SimpleActionClient;
using actionlib::SimpleClientGoalState;
using control_msgs::FollowJointTrajectoryAction;
using rapid_pbd_msgs::Action;

namespace msgs = rapid_pbd_msgs;

namespace rapid {
namespace pbd {
ActionExecutor::ActionExecutor(const Action& action,
                               ActionClients* action_clients,
                               MotionPlanning* motion_planning, World* world,
                               const RobotConfig& robot_config,
                               const RuntimeVisualizer& runtime_viz)
    : action_(action),
      clients_(action_clients),
      motion_planning_(motion_planning),
      world_(world),
      robot_config_(robot_config),
      runtime_viz_(runtime_viz) {}

bool ActionExecutor::IsValid(const Action& action) {
  if (action.type == Action::ACTUATE_GRIPPER) {
    if (action.actuator_group == Action::GRIPPER ||
        action.actuator_group == Action::LEFT_GRIPPER ||
        action.actuator_group == Action::RIGHT_GRIPPER) {
    } else {
      PublishInvalidGroupError(action);
      return false;
    }
  } else if (action.type == Action::MOVE_TO_JOINT_GOAL) {
    if (action.actuator_group == Action::ARM ||
        action.actuator_group == Action::LEFT_ARM ||
        action.actuator_group == Action::RIGHT_ARM ||
        action.actuator_group == Action::HEAD) {
    } else {
      PublishInvalidGroupError(action);
      return false;
    }
    if (!HasJointValues(action)) {
      return false;
    }
  } else if (action.type == Action::MOVE_TO_CARTESIAN_GOAL) {
    if (action.actuator_group == Action::ARM ||
        action.actuator_group == Action::LEFT_ARM ||
        action.actuator_group == Action::RIGHT_ARM ||
        action.actuator_group == Action::HEAD) {
    } else {
      PublishInvalidGroupError(action);
      return false;
    }
  } else if (action.type == Action::DETECT_TABLETOP_OBJECTS) {
  } else if (action.type == Action::FIND_CUSTOM_LANDMARK) {
  } else {
    ROS_ERROR("Invalid action type: \"%s\"", action.type.c_str());
    return false;
  }
  return true;
}

std::string ActionExecutor::Start() {
  if (action_.type == Action::ACTUATE_GRIPPER) {
    ActuateGripper();
  } else if (action_.type == Action::MOVE_TO_JOINT_GOAL) {
    std::vector<std::string> joint_names;
    std::vector<double> joint_positions;
    GetJointPositions(action_, &joint_names, &joint_positions);
    if (action_.actuator_group == msgs::Action::ARM || action_.actuator_group == msgs::Action::LEFT_ARM || action_.actuator_group == msgs::Action::RIGHT_ARM) {
      return motion_planning_->AddJointGoal(joint_names, joint_positions);
    } else if (action_.actuator_group == Action::HEAD) {
      control_msgs::FollowJointTrajectoryGoal joint_goal;
      joint_goal.trajectory = action_.joint_trajectory;
      joint_goal.trajectory.header.stamp = ros::Time::now();
			SimpleActionClient<FollowJointTrajectoryAction>* client;
  		  client = &clients_->head_client;
  		client->sendGoal(joint_goal);
    } else {
      return "Invalid actuator group";
    }
  } else if (action_.type == Action::MOVE_TO_CARTESIAN_GOAL) {
    std::vector<std::string> joint_names;
    std::vector<double> joint_positions;
    if (HasJointValues(action_)) {
      GetJointPositions(action_, &joint_names, &joint_positions);
    }
    return motion_planning_->AddPoseGoal(action_.actuator_group, action_.pose,
                                         action_.landmark, joint_names,
                                         joint_positions);
  } else if (action_.type == Action::DETECT_TABLETOP_OBJECTS) {
    DetectTabletopObjects();
  }
  return "";
}

bool ActionExecutor::IsDone(std::string* error) const {
  if (action_.type == Action::ACTUATE_GRIPPER) {
    if (action_.actuator_group == Action::GRIPPER) {
      return clients_->gripper_client.getState().isDone();
    } else if (action_.actuator_group == Action::LEFT_GRIPPER) {
      return clients_->l_gripper_client.getState().isDone();
    } else if (action_.actuator_group == Action::RIGHT_GRIPPER) {
      return clients_->r_gripper_client.getState().isDone();
    }
  } else if (action_.type == Action::MOVE_TO_JOINT_GOAL) {
    if (action_.actuator_group == Action::HEAD) {
      return clients_->head_client.getState().isDone();
    } else {
      // Arm motions are controlled by motion planning in the step executor.
      return true;
    }
  } else if (action_.type == Action::DETECT_TABLETOP_OBJECTS) {
    bool done = clients_->surface_segmentation_client.getState().isDone();
    if (done) {
      msgs::SegmentSurfacesResultConstPtr result =
          clients_->surface_segmentation_client.getResult();
      if (result) {
        if (result->landmarks.size() == 0) {
          *error = errors::kNoLandmarksDetected;
        }
        world_->surface_box_landmarks = result->landmarks;
        runtime_viz_.PublishSurfaceBoxes(result->landmarks);
      } else {
        ROS_ERROR("Surface segmentation result pointer was null!");
        *error = "Surface segmentation result pointer was null!";
        return false;
      }
    }
    return done;
  }
  return true;
}

void ActionExecutor::Cancel() {
  if (action_.type == Action::ACTUATE_GRIPPER) {
    if (action_.actuator_group == Action::GRIPPER) {
      clients_->gripper_client.cancelAllGoals();
    } else if (action_.actuator_group == Action::LEFT_GRIPPER) {
      clients_->l_gripper_client.cancelAllGoals();
    } else if (action_.actuator_group == Action::RIGHT_GRIPPER) {
      clients_->r_gripper_client.cancelAllGoals();
    }
  } else if (action_.type == Action::MOVE_TO_JOINT_GOAL) {
    if (action_.actuator_group == Action::HEAD) {
      clients_->head_client.cancelAllGoals();
    } else {
      // Arm motions are cancelled by motion planning in the step executor.
    }
  } else if (action_.type == Action::DETECT_TABLETOP_OBJECTS) {
    clients_->surface_segmentation_client.cancelAllGoals();
  }
}

void ActionExecutor::ActuateGripper() {
  control_msgs::GripperCommandGoal gripper_goal;
  gripper_goal.command = action_.gripper_command;

  SimpleActionClient<control_msgs::GripperCommandAction>* client;
  if (action_.actuator_group == Action::GRIPPER) {
    client = &clients_->gripper_client;
  } else if (action_.actuator_group == Action::LEFT_GRIPPER) {
    client = &clients_->l_gripper_client;
  } else if (action_.actuator_group == Action::RIGHT_GRIPPER) {
    client = &clients_->r_gripper_client;
  } else {
    return;
  }
  client->sendGoal(gripper_goal);
}

void ActionExecutor::DetectTabletopObjects() {
  rapid_pbd_msgs::SegmentSurfacesGoal goal;
  goal.save_cloud = false;
  clients_->surface_segmentation_client.sendGoal(goal);
}

void ActionExecutor::PublishInvalidGroupError(const Action& action) {
  ROS_ERROR("Invalid actuator_group \"%s\" for action type \"%s\".",
            action.actuator_group.c_str(), action.type.c_str());
}
}  // namespace pbd
}  // namespace rapid
<|endoftext|>


<commit_before>#include"all_defines.hpp"
#include"objects.hpp"
#include"heaps.hpp"
#include"types.hpp"

#include<map>
#include<stack>
#include<cstdlib>
#include<stdint.h>

/*-----------------------------------------------------------------------------
Semispaces
-----------------------------------------------------------------------------*/

Semispace::Semispace(size_t nsz) {
	nsz = Object::round_up_to_alignment(nsz);
	max = nsz;
	// add alignment in case mem is misaligned
	mem = std::malloc(nsz + Object::alignment);
	if(!mem) throw std::bad_alloc();

	allocpt = mem;
	// check alignment
	intptr_t tmp = reinterpret_cast<intptr_t>(allocpt);
	if(tmp & Object::tag_mask) {
		char* callocpt = (char*)allocpt;
		callocpt += Object::alignment - (tmp & Object::tag_mask);
		allocpt = callocpt;
	}
	allocstart = allocpt;

	char* cmem = (char*)mem;
	char* clifoallocpt = cmem + nsz;
	// adjust for alignment
	tmp = reinterpret_cast<intptr_t>(clifoallocpt);
	clifoallocpt -= (tmp & Object::tag_mask);

	lifoallocpt = clifoallocpt;
	lifoallocstart = lifoallocpt;
}

Semispace::~Semispace() {
	Generic* gp;
	size_t step;
	char* mvpt;
	char* endpt;

	/*TODO: consider refactoring*/
	/*----Delete normally-allocated memory----*/
	mvpt = (char*) allocstart;
	endpt = (char*) allocpt;

	while(mvpt < endpt) {
		gp = (Generic*)(void*) mvpt;
		step = gp->real_size();
		gp->~Generic();
		mvpt += step;
	}

	/*----Delete lifo-allocated memory----*/
	mvpt = (char*) lifoallocpt;
	endpt = (char*) lifoallocstart;

	while(mvpt < endpt) {
		gp = (Generic*)(void*) mvpt;
		step = gp->real_size();
		gp->~Generic();
		mvpt += step;
	}

	std::free(mem);
}

/*
sz must be computed using the exact same
computation used in real_size() of the
object to be allocated.  This includes
alignment.
*/
void* Semispace::alloc(size_t sz) {
	prev_alloc = sz;
	void* tmp = allocpt;
	char* callocpt = (char*) allocpt;
	callocpt += sz;
	allocpt = callocpt;
	return tmp;
}

/*should be used only for most recent allocation
(i.e. should be used for freeing memory when the
constructor throws.)
*/
void Semispace::dealloc(void* pt) {
	#ifdef DEBUG
		char* callocpt = (char*) allocpt;
		callocpt -= prev_alloc;
		if(callocpt != pt) throw_DeallocError(pt);
	#endif
	allocpt = pt;
}

void* Semispace::lifo_alloc(size_t sz) {
	prev_alloc = sz;
	char* clifoallocpt = (char*) lifoallocpt;
	clifoallocpt -= sz;
	lifoallocpt = clifoallocpt;
	return lifoallocpt;
}

void Semispace::lifo_dealloc(Generic* pt) {
	/*if we can't deallocate, just ignore*/
	if(((void*) pt) != lifoallocpt) return;
	size_t sz = pt->real_size();
	pt->~Generic();
	char* clifoallocpt = (char*)(void*) pt;
	clifoallocpt += sz;
	lifoallocpt = clifoallocpt;
}

/*This function should be used only when the
constructor for the object fails.  It does
*not* properly destroy the object.
*/
void Semispace::lifo_dealloc_abort(void* pt) {
	#ifdef DEBUG
		if(pt != lifoallocpt) throw_DeallocError(pt);
	#endif
	char* clifoallocpt = (char*) lifoallocpt;
	clifoallocpt += prev_alloc;
	lifoallocpt = clifoallocpt;
}

void Semispace::traverse_objects(HeapTraverser* ht) const {
	char* mvpt = (char*) allocstart;
	char* endpt = (char*) allocpt;

	while(mvpt < endpt) {
		Generic* tmp = (Generic*)(void*) mvpt;
		size_t sz = tmp->real_size();
		ht->traverse(tmp);
		mvpt += sz;
	}

	mvpt = (char*) lifoallocpt;
	endpt = (char*) lifoallocstart;

	while(mvpt < endpt) {
		gp = (Generic*)(void*) mvpt;
		step = gp->real_size();
		gp->~Generic();
		mvpt += step;
	}
}

/*Used by SemispaceCloningTraverser below*/
class MovingTraverser : public GenericTraverser {
private:
	ptrdiff_t diff;
public:
	void traverse(Object::ref& o) {
		if(is_a<Generic*>(o)) {
			Generic* gp = as_a<Generic*>(o);
			char* cgp = (char*)(void*) gp;
			cgp -= diff;
			gp = (Generic*)(void*) cgp;
			o = Object::to_ref(gp);
		}
	}
	explicit MovingTraverser(ptrdiff_t ndiff) : diff(ndiff) { }
};

class SemispaceCloningTraverser : public HeapTraverser {
private:
	Semispace* sp;
	MovingTraverser mt;
public:
	void traverse(Generic* gp) {
		Generic* np = gp->clone(sp);
		np->traverse_references(&mt);
	}
	SemispaceCloningTraverser(Semispace* nsp, ptrdiff_t ndiff)
		: sp(nsp), mt(ndiff) { }
};

/*Preconditions:
	this should be self-contained (i.e. objects in it
	  should not contain references to objects outside
	  of this semispace)
	this should have no lifo-allocated objects
*/
void Semispace::clone(boost::scoped_ptr<Semispace>& ns, Generic*& g) const {
	ns.reset(new Semispace(max));
	char* myallocstart = (char*) allocstart;
	char* hisallocstart = (char*) ns->allocstart;

	SemispaceCloningTraverser sct(&*ns, myallocstart - hisallocstart);

	traverse_objects(&sct);

	char* cg = (char*)(void*) g;
	cg -= (myallocstart - hisallocstart);
	g = (Generic*)(void*) cg;
}

/*-----------------------------------------------------------------------------
ValueHolder
-----------------------------------------------------------------------------*/

void ValueHolder::traverse_objects(HeapTraverser* ht) const {
	for(ValueHolder const* pt = this; pt; pt = &*pt->next) {
		if(pt->sp) pt->sp->traverse_objects(ht);
	}
}

/*clones only itself, not the chain*/
void ValueHolder::clone(ValueHolderRef& np) const {
	np.p = new ValueHolder();
	if(sp) {
		boost::scoped_ptr<Semispace> nsp;
		Generic* gp = as_a<Generic*>(val);
		sp->clone(nsp, gp);
		np->sp.swap(nsp);
		np->val = Object::to_ref(gp);
	} else {
		np->val = val;
	}
}

class ObjectMeasurer : public GenericTraverser {
public:
	size_t N;
	std::map<Generic*,Generic*>* mp;
	std::stack<Generic*> todo;

	explicit ObjectMeasurer(std::map<Generic*,Generic*>* nmp)
		: N(0), mp(nmp) { }

	void traverse(Object::ref& o) {
		if(is_a<Generic*>(o)) {
			Generic* gp = as_a<Generic*>(o);
			if(mp->find(gp) == mp->end()) {
				(*mp)[gp] = gp;
				todo.push(gp);
			}
		}
	}
	void operate(Generic* gp) {
		(*mp)[gp] = gp;
		todo.push(gp);
		do {
			N += gp->real_size();
			gp = todo.top(); todo.pop();
			gp->traverse_references(this);
		} while(!todo.empty());
	}
};

class ReferenceReplacer : public GenericTraverser {
private:
	std::map<Generic*, Generic*>* mp;
public:
	explicit ReferenceReplacer(std::map<Generic*, Generic*>* nmp)
		: mp(nmp) { }
	void traverse(Object::ref& o) {
		if(is_a<Generic*>(o)) {
			std::map<Generic*, Generic*>::iterator it;
			it = mp->find(as_a<Generic*>(o));
			if(it != mp->end()) {
				o = Object::to_ref(it->second);
			}
		}
	}
};

void ValueHolder::copy_object(ValueHolderRef& np, Object::ref o) {
	typedef std::map<Generic*, Generic*> TM;
	if(is_a<Generic*>(o)) {
		TM obs;
		size_t total = 0;
		/*first, measure the memory*/
		{ObjectMeasurer om(&obs);
			om.operate(as_a<Generic*>(o));
			total = om.N;
		}
		/*now create the Semispace*/
		boost::scoped_ptr<Semispace> sp(new Semispace(total));

		/*copy*/
		for(TM::iterator it = obs.begin(); it != obs.end(); ++it) {
			it->second = it->second->clone(&*sp);
		}

		/*translate*/
		{ObjectsTraverser<ReferenceReplacer> ot(&obs);
			sp->traverse_objects(&ot);
		}
		Generic* old_o = as_a<Generic*>(o);
		Generic* new_o = obs[old_o];
		o = Object::to_ref(new_o);

		/*create holder*/
		np.p = new ValueHolder;
		np.p->val = o;
		np.p->sp.swap(sp);
	} else {
		np.p = new ValueHolder;
		np.p->val = o;
	}
}

/*-----------------------------------------------------------------------------
Heaps
-----------------------------------------------------------------------------*/

void Heap::traverse_objects(HeapTraverser* ht) const {
	main->traverse_objects(ht);
	if(!other_spaces.empty()) {
		other_spaces->traverse_objects(ht);
	}
}

/*copy and modify GC class*/
class GCTraverser : public GenericTraverser {
	Semispace* nsp;
public:
	explicit GCTraverser(Semispace* nnsp) : nsp(nnsp) { }
	void traverse(Object::ref& r) {
		if(is_a<Generic*>(r)) {
			Generic* gp = as_a<Generic*>(r);
			BrokenHeart* bp = dynamic_cast<BrokenHeart*>(gp);
			if(bp) { //broken heart
				r = Object::to_ref(bp->to);
			} else { //unbroken
				Generic* ngp = gp->clone(nsp);
				gp->break_heart(ngp);
				r = Object::to_ref(ngp);
			}
		} else return;
	}
};

void Heap::cheney_collection(Semispace* nsp) {
	GCTraverser gc(nsp);
	/*step 1: initial traverse*/
	scan_root_object(&gc);
	/*step 2: non-root traverse*/
	/*notice that we traverse the new semispace
	this is a two-pointer Cheney collector, with mvpt
	being one pointer and nsp->allocpt the other one
	*/
	char* mvpt = (char*) nsp->allocstart;
	while(mvpt < ((char*) nsp->allocpt)) {
		Generic* gp = (Generic*)(void*) mvpt;
		size_t obsz = gp->real_size();
		gp->traverse_references(&gc);
		mvpt += obsz;
	}
}

#ifdef DEBUG
	#include<iostream>
#endif

void Heap::GC(size_t insurance) {

	#ifdef DEBUG
		std::cout << "GC!" << std::endl;
	#endif

	/*Determine the sizes of all semispaces*/
	size_t total = main->used() + insurance;
	total +=
	(other_spaces.empty()) ?	0 :
	/*otherwise*/			other_spaces->used_total() ;

	if(tight) total *= 2;

	/*get a new Semispace*/
	boost::scoped_ptr<Semispace> nsp(new Semispace(total));

	/*traverse*/
	cheney_collection(&*nsp);

	/*replace*/
	main.swap(nsp);
	nsp.reset();
	other_spaces.reset();

	/*determine if resizing is appropriate*/
	if(main->used() + insurance <= total / 4) {
		/*semispace a bit large... make it smaller*/
		nsp.reset(new Semispace(total / 2));
		cheney_collection(&*nsp);
		main.swap(nsp);
		nsp.reset();
	} else if(main->used() + insurance >= (total / 4) * 3) {
		tight = 1;
	}
}

<commit_msg>src/heaps.cpp: Fixed Semispace::traverse_objects()<commit_after>#include"all_defines.hpp"
#include"objects.hpp"
#include"heaps.hpp"
#include"types.hpp"

#include<map>
#include<stack>
#include<cstdlib>
#include<stdint.h>

/*-----------------------------------------------------------------------------
Semispaces
-----------------------------------------------------------------------------*/

Semispace::Semispace(size_t nsz) {
	nsz = Object::round_up_to_alignment(nsz);
	max = nsz;
	// add alignment in case mem is misaligned
	mem = std::malloc(nsz + Object::alignment);
	if(!mem) throw std::bad_alloc();

	allocpt = mem;
	// check alignment
	intptr_t tmp = reinterpret_cast<intptr_t>(allocpt);
	if(tmp & Object::tag_mask) {
		char* callocpt = (char*)allocpt;
		callocpt += Object::alignment - (tmp & Object::tag_mask);
		allocpt = callocpt;
	}
	allocstart = allocpt;

	char* cmem = (char*)mem;
	char* clifoallocpt = cmem + nsz;
	// adjust for alignment
	tmp = reinterpret_cast<intptr_t>(clifoallocpt);
	clifoallocpt -= (tmp & Object::tag_mask);

	lifoallocpt = clifoallocpt;
	lifoallocstart = lifoallocpt;
}

Semispace::~Semispace() {
	Generic* gp;
	size_t step;
	char* mvpt;
	char* endpt;

	/*TODO: consider refactoring*/
	/*----Delete normally-allocated memory----*/
	mvpt = (char*) allocstart;
	endpt = (char*) allocpt;

	while(mvpt < endpt) {
		gp = (Generic*)(void*) mvpt;
		step = gp->real_size();
		gp->~Generic();
		mvpt += step;
	}

	/*----Delete lifo-allocated memory----*/
	mvpt = (char*) lifoallocpt;
	endpt = (char*) lifoallocstart;

	while(mvpt < endpt) {
		gp = (Generic*)(void*) mvpt;
		step = gp->real_size();
		gp->~Generic();
		mvpt += step;
	}

	std::free(mem);
}

/*
sz must be computed using the exact same
computation used in real_size() of the
object to be allocated.  This includes
alignment.
*/
void* Semispace::alloc(size_t sz) {
	prev_alloc = sz;
	void* tmp = allocpt;
	char* callocpt = (char*) allocpt;
	callocpt += sz;
	allocpt = callocpt;
	return tmp;
}

/*should be used only for most recent allocation
(i.e. should be used for freeing memory when the
constructor throws.)
*/
void Semispace::dealloc(void* pt) {
	#ifdef DEBUG
		char* callocpt = (char*) allocpt;
		callocpt -= prev_alloc;
		if(callocpt != pt) throw_DeallocError(pt);
	#endif
	allocpt = pt;
}

void* Semispace::lifo_alloc(size_t sz) {
	prev_alloc = sz;
	char* clifoallocpt = (char*) lifoallocpt;
	clifoallocpt -= sz;
	lifoallocpt = clifoallocpt;
	return lifoallocpt;
}

void Semispace::lifo_dealloc(Generic* pt) {
	/*if we can't deallocate, just ignore*/
	if(((void*) pt) != lifoallocpt) return;
	size_t sz = pt->real_size();
	pt->~Generic();
	char* clifoallocpt = (char*)(void*) pt;
	clifoallocpt += sz;
	lifoallocpt = clifoallocpt;
}

/*This function should be used only when the
constructor for the object fails.  It does
*not* properly destroy the object.
*/
void Semispace::lifo_dealloc_abort(void* pt) {
	#ifdef DEBUG
		if(pt != lifoallocpt) throw_DeallocError(pt);
	#endif
	char* clifoallocpt = (char*) lifoallocpt;
	clifoallocpt += prev_alloc;
	lifoallocpt = clifoallocpt;
}

void Semispace::traverse_objects(HeapTraverser* ht) const {
	char* mvpt = (char*) allocstart;
	char* endpt = (char*) allocpt;

	while(mvpt < endpt) {
		Generic* tmp = (Generic*)(void*) mvpt;
		size_t sz = tmp->real_size();
		ht->traverse(tmp);
		mvpt += sz;
	}

	mvpt = (char*) lifoallocpt;
	endpt = (char*) lifoallocstart;

	while(mvpt < endpt) {
		Generic* tmp = (Generic*)(void*) mvpt;
		size_t sz = tmp->real_size();
		ht->traverse(tmp);
		mvpt += sz;
	}
}

/*Used by SemispaceCloningTraverser below*/
class MovingTraverser : public GenericTraverser {
private:
	ptrdiff_t diff;
public:
	void traverse(Object::ref& o) {
		if(is_a<Generic*>(o)) {
			Generic* gp = as_a<Generic*>(o);
			char* cgp = (char*)(void*) gp;
			cgp -= diff;
			gp = (Generic*)(void*) cgp;
			o = Object::to_ref(gp);
		}
	}
	explicit MovingTraverser(ptrdiff_t ndiff) : diff(ndiff) { }
};

class SemispaceCloningTraverser : public HeapTraverser {
private:
	Semispace* sp;
	MovingTraverser mt;
public:
	void traverse(Generic* gp) {
		Generic* np = gp->clone(sp);
		np->traverse_references(&mt);
	}
	SemispaceCloningTraverser(Semispace* nsp, ptrdiff_t ndiff)
		: sp(nsp), mt(ndiff) { }
};

/*Preconditions:
	this should be self-contained (i.e. objects in it
	  should not contain references to objects outside
	  of this semispace)
	this should have no lifo-allocated objects
*/
void Semispace::clone(boost::scoped_ptr<Semispace>& ns, Generic*& g) const {
	ns.reset(new Semispace(max));
	char* myallocstart = (char*) allocstart;
	char* hisallocstart = (char*) ns->allocstart;

	SemispaceCloningTraverser sct(&*ns, myallocstart - hisallocstart);

	traverse_objects(&sct);

	char* cg = (char*)(void*) g;
	cg -= (myallocstart - hisallocstart);
	g = (Generic*)(void*) cg;
}

/*-----------------------------------------------------------------------------
ValueHolder
-----------------------------------------------------------------------------*/

void ValueHolder::traverse_objects(HeapTraverser* ht) const {
	for(ValueHolder const* pt = this; pt; pt = &*pt->next) {
		if(pt->sp) pt->sp->traverse_objects(ht);
	}
}

/*clones only itself, not the chain*/
void ValueHolder::clone(ValueHolderRef& np) const {
	np.p = new ValueHolder();
	if(sp) {
		boost::scoped_ptr<Semispace> nsp;
		Generic* gp = as_a<Generic*>(val);
		sp->clone(nsp, gp);
		np->sp.swap(nsp);
		np->val = Object::to_ref(gp);
	} else {
		np->val = val;
	}
}

class ObjectMeasurer : public GenericTraverser {
public:
	size_t N;
	std::map<Generic*,Generic*>* mp;
	std::stack<Generic*> todo;

	explicit ObjectMeasurer(std::map<Generic*,Generic*>* nmp)
		: N(0), mp(nmp) { }

	void traverse(Object::ref& o) {
		if(is_a<Generic*>(o)) {
			Generic* gp = as_a<Generic*>(o);
			if(mp->find(gp) == mp->end()) {
				(*mp)[gp] = gp;
				todo.push(gp);
			}
		}
	}
	void operate(Generic* gp) {
		(*mp)[gp] = gp;
		todo.push(gp);
		do {
			N += gp->real_size();
			gp = todo.top(); todo.pop();
			gp->traverse_references(this);
		} while(!todo.empty());
	}
};

class ReferenceReplacer : public GenericTraverser {
private:
	std::map<Generic*, Generic*>* mp;
public:
	explicit ReferenceReplacer(std::map<Generic*, Generic*>* nmp)
		: mp(nmp) { }
	void traverse(Object::ref& o) {
		if(is_a<Generic*>(o)) {
			std::map<Generic*, Generic*>::iterator it;
			it = mp->find(as_a<Generic*>(o));
			if(it != mp->end()) {
				o = Object::to_ref(it->second);
			}
		}
	}
};

void ValueHolder::copy_object(ValueHolderRef& np, Object::ref o) {
	typedef std::map<Generic*, Generic*> TM;
	if(is_a<Generic*>(o)) {
		TM obs;
		size_t total = 0;
		/*first, measure the memory*/
		{ObjectMeasurer om(&obs);
			om.operate(as_a<Generic*>(o));
			total = om.N;
		}
		/*now create the Semispace*/
		boost::scoped_ptr<Semispace> sp(new Semispace(total));

		/*copy*/
		for(TM::iterator it = obs.begin(); it != obs.end(); ++it) {
			it->second = it->second->clone(&*sp);
		}

		/*translate*/
		{ObjectsTraverser<ReferenceReplacer> ot(&obs);
			sp->traverse_objects(&ot);
		}
		Generic* old_o = as_a<Generic*>(o);
		Generic* new_o = obs[old_o];
		o = Object::to_ref(new_o);

		/*create holder*/
		np.p = new ValueHolder;
		np.p->val = o;
		np.p->sp.swap(sp);
	} else {
		np.p = new ValueHolder;
		np.p->val = o;
	}
}

/*-----------------------------------------------------------------------------
Heaps
-----------------------------------------------------------------------------*/

void Heap::traverse_objects(HeapTraverser* ht) const {
	main->traverse_objects(ht);
	if(!other_spaces.empty()) {
		other_spaces->traverse_objects(ht);
	}
}

/*copy and modify GC class*/
class GCTraverser : public GenericTraverser {
	Semispace* nsp;
public:
	explicit GCTraverser(Semispace* nnsp) : nsp(nnsp) { }
	void traverse(Object::ref& r) {
		if(is_a<Generic*>(r)) {
			Generic* gp = as_a<Generic*>(r);
			BrokenHeart* bp = dynamic_cast<BrokenHeart*>(gp);
			if(bp) { //broken heart
				r = Object::to_ref(bp->to);
			} else { //unbroken
				Generic* ngp = gp->clone(nsp);
				gp->break_heart(ngp);
				r = Object::to_ref(ngp);
			}
		} else return;
	}
};

void Heap::cheney_collection(Semispace* nsp) {
	GCTraverser gc(nsp);
	/*step 1: initial traverse*/
	scan_root_object(&gc);
	/*step 2: non-root traverse*/
	/*notice that we traverse the new semispace
	this is a two-pointer Cheney collector, with mvpt
	being one pointer and nsp->allocpt the other one
	*/
	char* mvpt = (char*) nsp->allocstart;
	while(mvpt < ((char*) nsp->allocpt)) {
		Generic* gp = (Generic*)(void*) mvpt;
		size_t obsz = gp->real_size();
		gp->traverse_references(&gc);
		mvpt += obsz;
	}
}

#ifdef DEBUG
	#include<iostream>
#endif

void Heap::GC(size_t insurance) {

	#ifdef DEBUG
		std::cout << "GC!" << std::endl;
	#endif

	/*Determine the sizes of all semispaces*/
	size_t total = main->used() + insurance;
	total +=
	(other_spaces.empty()) ?	0 :
	/*otherwise*/			other_spaces->used_total() ;

	if(tight) total *= 2;

	/*get a new Semispace*/
	boost::scoped_ptr<Semispace> nsp(new Semispace(total));

	/*traverse*/
	cheney_collection(&*nsp);

	/*replace*/
	main.swap(nsp);
	nsp.reset();
	other_spaces.reset();

	/*determine if resizing is appropriate*/
	if(main->used() + insurance <= total / 4) {
		/*semispace a bit large... make it smaller*/
		nsp.reset(new Semispace(total / 2));
		cheney_collection(&*nsp);
		main.swap(nsp);
		nsp.reset();
	} else if(main->used() + insurance >= (total / 4) * 3) {
		tight = 1;
	}
}

<|endoftext|>


<commit_before>#include <string>
#include <set>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <iterator>
#include <ext/stdio_filebuf.h>
#include "stream.h"

using namespace std;

struct compare_t {
    bool operator()(const char* p, const char* q) const {
        return strcmp(p,q) < 0;
    }
};

template <class T, class C, class F>
void run(const set<T,C>& ss1, const set<T,C>& ss2, F algorithm) {
    algorithm(
        ss1.begin(), ss1.end(),
        ss2.begin(), ss2.end(),
        ostream_iterator<T>(cout, "\n"));
}

const char* operations[] = {
    "union",
    "difference",
    "intersection",
    "symmetric_difference"
};

void help() {
    cout << "setops provides set operations for text files" << endl;
    cout << "Usage: setops [operation] <[file1] 3<[file2]" << endl;
    cout << "Available operations:" << endl;
    for (int i=0; i<4; ++i)
        cout << "  " << operations[i] << endl;
    cout << "You can use short prefix to specify operation like 'u' for 'union'." << endl;
}

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

    if (argc != 2) {
        help();
        return 1;
    }

    typedef set<const char*, compare_t> rows_t;

    rows_t ss1;
    stream_t in1(cin);
    while (const char* p = in1.next())
        if (!ss1.insert(p).second)
            in1.undo(p);

    rows_t ss2;
    __gnu_cxx::stdio_filebuf<char> filebuf(3, ios::in);
    istream cin3(&filebuf);
    stream_t in2(cin3);
    while (const char* p = in2.next())
        if (!ss2.insert(p).second)
            in2.undo(p);

    typedef rows_t::const_iterator I;
    typedef ostream_iterator<const char*> O;

    for (int i=0; i<4; ++i) {
        if (strstr(operations[i], argv[1]) == operations[i]) {
            switch (i) {
                case 0: run(ss1, ss2, set_union<I,I,O>); return 0;
                case 1: run(ss1, ss2, set_difference<I,I,O>); return 0;
                case 2: run(ss1, ss2, set_intersection<I,I,O>); return 0;
                case 3: run(ss1, ss2, set_symmetric_difference<I,I,O>); return 0;
            }
        }
    }
    cerr << "Unknown operation." << endl;
    return 2;
}
<commit_msg>setops: missing Compare specialization fixed<commit_after>#include <string>
#include <set>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <iterator>
#include <ext/stdio_filebuf.h>
#include "stream.h"

using namespace std;

struct compare_t {
    bool operator()(const char* p, const char* q) const {
        return strcmp(p,q) < 0;
    }
};

template <class T, class C, class F>
void run(const set<T,C>& ss1, const set<T,C>& ss2, F algorithm) {
    algorithm(
        ss1.begin(), ss1.end(),
        ss2.begin(), ss2.end(),
        ostream_iterator<T>(cout, "\n"),
        compare_t());
}

const char* operations[] = {
    "union",
    "difference",
    "intersection",
    "symmetric_difference"
};

void help() {
    cout << "setops provides set operations for text files" << endl;
    cout << "Usage: setops [operation] <[file1] 3<[file2]" << endl;
    cout << "Available operations:" << endl;
    for (int i=0; i<4; ++i)
        cout << "  " << operations[i] << endl;
    cout << "You can use short prefix to specify operation like 'u' for 'union'." << endl;
}

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

    if (argc != 2) {
        help();
        return 1;
    }

    typedef set<const char*, compare_t> rows_t;

    rows_t ss1;
    stream_t in1(cin);
    while (const char* p = in1.next())
        if (!ss1.insert(p).second)
            in1.undo(p);

    rows_t ss2;
    __gnu_cxx::stdio_filebuf<char> filebuf(3, ios::in);
    istream cin3(&filebuf);
    stream_t in2(cin3);
    while (const char* p = in2.next())
        if (!ss2.insert(p).second)
            in2.undo(p);

    typedef rows_t::const_iterator I;
    typedef ostream_iterator<const char*> O;

    typedef compare_t C;
    for (int i=0; i<4; ++i) {
        if (strstr(operations[i], argv[1]) == operations[i]) {
            switch (i) {
                case 0: run(ss1, ss2, set_union<I,I,O,C>); return 0;
                case 1: run(ss1, ss2, set_difference<I,I,O,C>); return 0;
                case 2: run(ss1, ss2, set_intersection<I,I,O,C>); return 0;
                case 3: run(ss1, ss2, set_symmetric_difference<I,I,O,C>); return 0;
            }
        }
    }
    cerr << "Unknown operation." << endl;
    return 2;
}
<|endoftext|>


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

// Tests for the Command Buffer Helper.

#include "base/at_exit.h"
#include "base/callback.h"
#include "base/message_loop.h"
#include "base/scoped_nsautorelease_pool.h"
#include "gpu/command_buffer/client/cmd_buffer_helper.h"
#include "gpu/command_buffer/service/mocks.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/gpu_processor.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace gpu {

using testing::Return;
using testing::Mock;
using testing::Truly;
using testing::Sequence;
using testing::DoAll;
using testing::Invoke;
using testing::_;

const int32 kNumCommandEntries = 10;
const int32 kCommandBufferSizeBytes =
    kNumCommandEntries * sizeof(CommandBufferEntry);

// Test fixture for CommandBufferHelper test - Creates a CommandBufferHelper,
// using a CommandBufferEngine with a mock AsyncAPIInterface for its interface
// (calling it directly, not through the RPC mechanism).
class CommandBufferHelperTest : public testing::Test {
 protected:
  virtual void SetUp() {
    api_mock_.reset(new AsyncAPIMock);
    // ignore noops in the mock - we don't want to inspect the internals of the
    // helper.
    EXPECT_CALL(*api_mock_, DoCommand(0, _, _))
        .WillRepeatedly(Return(error::kNoError));

    command_buffer_.reset(new CommandBufferService);
    command_buffer_->Initialize(kNumCommandEntries);
    Buffer ring_buffer = command_buffer_->GetRingBuffer();

    parser_ = new CommandParser(ring_buffer.ptr,
                                ring_buffer.size,
                                0,
                                ring_buffer.size,
                                0,
                                api_mock_.get());

    scoped_refptr<GPUProcessor> gpu_processor(new GPUProcessor(
        command_buffer_.get(), NULL, parser_, 1));
    command_buffer_->SetPutOffsetChangeCallback(NewCallback(
        gpu_processor.get(), &GPUProcessor::ProcessCommands));

    api_mock_->set_engine(gpu_processor.get());

    helper_.reset(new CommandBufferHelper(command_buffer_.get()));
    helper_->Initialize();
  }

  virtual void TearDown() {
    // If the GPUProcessor posts any tasks, this forces them to run.
    MessageLoop::current()->RunAllPending();
    helper_.release();
  }

  // Adds a command to the buffer through the helper, while adding it as an
  // expected call on the API mock.
  void AddCommandWithExpect(error::Error _return,
                            unsigned int command,
                            int arg_count,
                            CommandBufferEntry *args) {
    CommandHeader header;
    header.size = arg_count + 1;
    header.command = command;
    CommandBufferEntry* cmds = helper_->GetSpace(arg_count + 1);
    CommandBufferOffset put = 0;
    cmds[put++].value_header = header;
    for (int ii = 0; ii < arg_count; ++ii) {
      cmds[put++] = args[ii];
    }

    EXPECT_CALL(*api_mock_, DoCommand(command, arg_count,
        Truly(AsyncAPIMock::IsArgs(arg_count, args))))
        .InSequence(sequence_)
        .WillOnce(Return(_return));
  }

  // Checks that the buffer from put to put+size is free in the parser.
  void CheckFreeSpace(CommandBufferOffset put, unsigned int size) {
    CommandBufferOffset parser_put = parser_->put();
    CommandBufferOffset parser_get = parser_->get();
    CommandBufferOffset limit = put + size;
    if (parser_get > parser_put) {
      // "busy" buffer wraps, so "free" buffer is between put (inclusive) and
      // get (exclusive).
      EXPECT_LE(parser_put, put);
      EXPECT_GT(parser_get, limit);
    } else {
      // "busy" buffer does not wrap, so the "free" buffer is the top side (from
      // put to the limit) and the bottom side (from 0 to get).
      if (put >= parser_put) {
        // we're on the top side, check we are below the limit.
        EXPECT_GE(kNumCommandEntries, limit);
      } else {
        // we're on the bottom side, check we are below get.
        EXPECT_GT(parser_get, limit);
      }
    }
  }

  int32 GetGetOffset() {
    return command_buffer_->GetState().get_offset;
  }

  int32 GetPutOffset() {
    return command_buffer_->GetState().put_offset;
  }

  error::Error GetError() {
    return command_buffer_->GetState().error;
  }

  CommandBufferOffset get_helper_put() { return helper_->put_; }

  base::ScopedNSAutoreleasePool autorelease_pool_;
  base::AtExitManager at_exit_manager_;
  MessageLoop message_loop_;
  scoped_ptr<AsyncAPIMock> api_mock_;
  scoped_ptr<CommandBufferService> command_buffer_;
  CommandParser* parser_;
  scoped_ptr<CommandBufferHelper> helper_;
  Sequence sequence_;
};

// Checks that commands in the buffer are properly executed, and that the
// status/error stay valid.
TEST_F(CommandBufferHelperTest, TestCommandProcessing) {
  // Check initial state of the engine - it should have been configured by the
  // helper.
  EXPECT_TRUE(parser_ != NULL);
  EXPECT_EQ(error::kNoError, GetError());
  EXPECT_EQ(0, GetGetOffset());

  // Add 3 commands through the helper
  AddCommandWithExpect(error::kNoError, 1, 0, NULL);

  CommandBufferEntry args1[2];
  args1[0].value_uint32 = 3;
  args1[1].value_float = 4.f;
  AddCommandWithExpect(error::kNoError, 2, 2, args1);

  CommandBufferEntry args2[2];
  args2[0].value_uint32 = 5;
  args2[1].value_float = 6.f;
  AddCommandWithExpect(error::kNoError, 3, 2, args2);

  helper_->Flush();
  // Check that the engine has work to do now.
  EXPECT_FALSE(parser_->IsEmpty());

  // Wait until it's done.
  helper_->Finish();
  // Check that the engine has no more work to do.
  EXPECT_TRUE(parser_->IsEmpty());

  // Check that the commands did happen.
  Mock::VerifyAndClearExpectations(api_mock_.get());

  // Check the error status.
  EXPECT_EQ(error::kNoError, GetError());
}

// Checks that commands in the buffer are properly executed when wrapping the
// buffer, and that the status/error stay valid.
TEST_F(CommandBufferHelperTest, TestCommandWrapping) {
  // Add 5 commands of size 3 through the helper to make sure we do wrap.
  CommandBufferEntry args1[2];
  args1[0].value_uint32 = 3;
  args1[1].value_float = 4.f;

  for (unsigned int i = 0; i < 5; ++i) {
    AddCommandWithExpect(error::kNoError, i + 1, 2, args1);
  }

  helper_->Finish();
  // Check that the commands did happen.
  Mock::VerifyAndClearExpectations(api_mock_.get());

  // Check the error status.
  EXPECT_EQ(error::kNoError, GetError());
}

// Checks that asking for available entries work, and that the parser
// effectively won't use that space.
TEST_F(CommandBufferHelperTest, TestAvailableEntries) {
  CommandBufferEntry args[2];
  args[0].value_uint32 = 3;
  args[1].value_float = 4.f;

  // Add 2 commands through the helper - 8 entries
  AddCommandWithExpect(error::kNoError, 1, 0, NULL);
  AddCommandWithExpect(error::kNoError, 2, 0, NULL);
  AddCommandWithExpect(error::kNoError, 3, 2, args);
  AddCommandWithExpect(error::kNoError, 4, 2, args);

  // Ask for 5 entries.
  helper_->WaitForAvailableEntries(5);

  CommandBufferOffset put = get_helper_put();
  CheckFreeSpace(put, 5);

  // Add more commands.
  AddCommandWithExpect(error::kNoError, 5, 2, args);

  // Wait until everything is done done.
  helper_->Finish();

  // Check that the commands did happen.
  Mock::VerifyAndClearExpectations(api_mock_.get());

  // Check the error status.
  EXPECT_EQ(error::kNoError, GetError());
}

// Checks that the InsertToken/WaitForToken work.
TEST_F(CommandBufferHelperTest, TestToken) {
  CommandBufferEntry args[2];
  args[0].value_uint32 = 3;
  args[1].value_float = 4.f;

  // Add a first command.
  AddCommandWithExpect(error::kNoError, 3, 2, args);
  // keep track of the buffer position.
  CommandBufferOffset command1_put = get_helper_put();
  int32 token = helper_->InsertToken();

  EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
      .WillOnce(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken),
                      Return(error::kNoError)));
  // Add another command.
  AddCommandWithExpect(error::kNoError, 4, 2, args);
  helper_->WaitForToken(token);
  // check that the get pointer is beyond the first command.
  EXPECT_LE(command1_put, GetGetOffset());
  helper_->Finish();

  // Check that the commands did happen.
  Mock::VerifyAndClearExpectations(api_mock_.get());

  // Check the error status.
  EXPECT_EQ(error::kNoError, GetError());
}

}  // namespace gpu
<commit_msg>Add command buffer test for case where command inserted exactly matches the space left in the command buffer.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Tests for the Command Buffer Helper.

#include "base/at_exit.h"
#include "base/callback.h"
#include "base/message_loop.h"
#include "base/scoped_nsautorelease_pool.h"
#include "gpu/command_buffer/client/cmd_buffer_helper.h"
#include "gpu/command_buffer/service/mocks.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/gpu_processor.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace gpu {

using testing::Return;
using testing::Mock;
using testing::Truly;
using testing::Sequence;
using testing::DoAll;
using testing::Invoke;
using testing::_;

const int32 kNumCommandEntries = 10;
const int32 kCommandBufferSizeBytes =
    kNumCommandEntries * sizeof(CommandBufferEntry);

// Test fixture for CommandBufferHelper test - Creates a CommandBufferHelper,
// using a CommandBufferEngine with a mock AsyncAPIInterface for its interface
// (calling it directly, not through the RPC mechanism).
class CommandBufferHelperTest : public testing::Test {
 protected:
  virtual void SetUp() {
    api_mock_.reset(new AsyncAPIMock);
    // ignore noops in the mock - we don't want to inspect the internals of the
    // helper.
    EXPECT_CALL(*api_mock_, DoCommand(0, _, _))
        .WillRepeatedly(Return(error::kNoError));

    command_buffer_.reset(new CommandBufferService);
    command_buffer_->Initialize(kNumCommandEntries);
    Buffer ring_buffer = command_buffer_->GetRingBuffer();

    parser_ = new CommandParser(ring_buffer.ptr,
                                ring_buffer.size,
                                0,
                                ring_buffer.size,
                                0,
                                api_mock_.get());

    scoped_refptr<GPUProcessor> gpu_processor(new GPUProcessor(
        command_buffer_.get(), NULL, parser_, 1));
    command_buffer_->SetPutOffsetChangeCallback(NewCallback(
        gpu_processor.get(), &GPUProcessor::ProcessCommands));

    api_mock_->set_engine(gpu_processor.get());

    helper_.reset(new CommandBufferHelper(command_buffer_.get()));
    helper_->Initialize();
  }

  virtual void TearDown() {
    // If the GPUProcessor posts any tasks, this forces them to run.
    MessageLoop::current()->RunAllPending();
    helper_.release();
  }

  // Adds a command to the buffer through the helper, while adding it as an
  // expected call on the API mock.
  void AddCommandWithExpect(error::Error _return,
                            unsigned int command,
                            int arg_count,
                            CommandBufferEntry *args) {
    CommandHeader header;
    header.size = arg_count + 1;
    header.command = command;
    CommandBufferEntry* cmds = helper_->GetSpace(arg_count + 1);
    CommandBufferOffset put = 0;
    cmds[put++].value_header = header;
    for (int ii = 0; ii < arg_count; ++ii) {
      cmds[put++] = args[ii];
    }

    EXPECT_CALL(*api_mock_, DoCommand(command, arg_count,
        Truly(AsyncAPIMock::IsArgs(arg_count, args))))
        .InSequence(sequence_)
        .WillOnce(Return(_return));
  }

  // Checks that the buffer from put to put+size is free in the parser.
  void CheckFreeSpace(CommandBufferOffset put, unsigned int size) {
    CommandBufferOffset parser_put = parser_->put();
    CommandBufferOffset parser_get = parser_->get();
    CommandBufferOffset limit = put + size;
    if (parser_get > parser_put) {
      // "busy" buffer wraps, so "free" buffer is between put (inclusive) and
      // get (exclusive).
      EXPECT_LE(parser_put, put);
      EXPECT_GT(parser_get, limit);
    } else {
      // "busy" buffer does not wrap, so the "free" buffer is the top side (from
      // put to the limit) and the bottom side (from 0 to get).
      if (put >= parser_put) {
        // we're on the top side, check we are below the limit.
        EXPECT_GE(kNumCommandEntries, limit);
      } else {
        // we're on the bottom side, check we are below get.
        EXPECT_GT(parser_get, limit);
      }
    }
  }

  int32 GetGetOffset() {
    return command_buffer_->GetState().get_offset;
  }

  int32 GetPutOffset() {
    return command_buffer_->GetState().put_offset;
  }

  error::Error GetError() {
    return command_buffer_->GetState().error;
  }

  CommandBufferOffset get_helper_put() { return helper_->put_; }

  base::ScopedNSAutoreleasePool autorelease_pool_;
  base::AtExitManager at_exit_manager_;
  MessageLoop message_loop_;
  scoped_ptr<AsyncAPIMock> api_mock_;
  scoped_ptr<CommandBufferService> command_buffer_;
  CommandParser* parser_;
  scoped_ptr<CommandBufferHelper> helper_;
  Sequence sequence_;
};

// Checks that commands in the buffer are properly executed, and that the
// status/error stay valid.
TEST_F(CommandBufferHelperTest, TestCommandProcessing) {
  // Check initial state of the engine - it should have been configured by the
  // helper.
  EXPECT_TRUE(parser_ != NULL);
  EXPECT_EQ(error::kNoError, GetError());
  EXPECT_EQ(0, GetGetOffset());

  // Add 3 commands through the helper
  AddCommandWithExpect(error::kNoError, 1, 0, NULL);

  CommandBufferEntry args1[2];
  args1[0].value_uint32 = 3;
  args1[1].value_float = 4.f;
  AddCommandWithExpect(error::kNoError, 2, 2, args1);

  CommandBufferEntry args2[2];
  args2[0].value_uint32 = 5;
  args2[1].value_float = 6.f;
  AddCommandWithExpect(error::kNoError, 3, 2, args2);

  helper_->Flush();
  // Check that the engine has work to do now.
  EXPECT_FALSE(parser_->IsEmpty());

  // Wait until it's done.
  helper_->Finish();
  // Check that the engine has no more work to do.
  EXPECT_TRUE(parser_->IsEmpty());

  // Check that the commands did happen.
  Mock::VerifyAndClearExpectations(api_mock_.get());

  // Check the error status.
  EXPECT_EQ(error::kNoError, GetError());
}

// Checks that commands in the buffer are properly executed when wrapping the
// buffer, and that the status/error stay valid.
TEST_F(CommandBufferHelperTest, TestCommandWrapping) {
  // Add 5 commands of size 3 through the helper to make sure we do wrap.
  CommandBufferEntry args1[2];
  args1[0].value_uint32 = 5;
  args1[1].value_float = 4.f;

  for (unsigned int i = 0; i < 5; ++i) {
    AddCommandWithExpect(error::kNoError, i + 1, 2, args1);
  }

  helper_->Finish();
  // Check that the commands did happen.
  Mock::VerifyAndClearExpectations(api_mock_.get());

  // Check the error status.
  EXPECT_EQ(error::kNoError, GetError());
}

// Checks the case where the command inserted exactly matches the space left in
// the command buffer.
TEST_F(CommandBufferHelperTest, TestCommandWrappingExactMultiple) {
  const int32 kCommandSize = 5;
  const int32 kNumArgs = kCommandSize - 1;
  COMPILE_ASSERT(kNumCommandEntries % kCommandSize == 0,
                 Not_multiple_of_num_command_entries);
  CommandBufferEntry args1[kNumArgs];
  for (size_t ii = 0; ii < kNumArgs; ++ii) {
    args1[0].value_uint32 = ii + 1;
  }

  for (unsigned int i = 0; i < 5; ++i) {
    AddCommandWithExpect(error::kNoError, i + 1, kNumArgs, args1);
  }

  helper_->Finish();
  // Check that the commands did happen.
  Mock::VerifyAndClearExpectations(api_mock_.get());

  // Check the error status.
  EXPECT_EQ(error::kNoError, GetError());
}

// Checks that asking for available entries work, and that the parser
// effectively won't use that space.
TEST_F(CommandBufferHelperTest, TestAvailableEntries) {
  CommandBufferEntry args[2];
  args[0].value_uint32 = 3;
  args[1].value_float = 4.f;

  // Add 2 commands through the helper - 8 entries
  AddCommandWithExpect(error::kNoError, 1, 0, NULL);
  AddCommandWithExpect(error::kNoError, 2, 0, NULL);
  AddCommandWithExpect(error::kNoError, 3, 2, args);
  AddCommandWithExpect(error::kNoError, 4, 2, args);

  // Ask for 5 entries.
  helper_->WaitForAvailableEntries(5);

  CommandBufferOffset put = get_helper_put();
  CheckFreeSpace(put, 5);

  // Add more commands.
  AddCommandWithExpect(error::kNoError, 5, 2, args);

  // Wait until everything is done done.
  helper_->Finish();

  // Check that the commands did happen.
  Mock::VerifyAndClearExpectations(api_mock_.get());

  // Check the error status.
  EXPECT_EQ(error::kNoError, GetError());
}

// Checks that the InsertToken/WaitForToken work.
TEST_F(CommandBufferHelperTest, TestToken) {
  CommandBufferEntry args[2];
  args[0].value_uint32 = 3;
  args[1].value_float = 4.f;

  // Add a first command.
  AddCommandWithExpect(error::kNoError, 3, 2, args);
  // keep track of the buffer position.
  CommandBufferOffset command1_put = get_helper_put();
  int32 token = helper_->InsertToken();

  EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
      .WillOnce(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken),
                      Return(error::kNoError)));
  // Add another command.
  AddCommandWithExpect(error::kNoError, 4, 2, args);
  helper_->WaitForToken(token);
  // check that the get pointer is beyond the first command.
  EXPECT_LE(command1_put, GetGetOffset());
  helper_->Finish();

  // Check that the commands did happen.
  Mock::VerifyAndClearExpectations(api_mock_.get());

  // Check the error status.
  EXPECT_EQ(error::kNoError, GetError());
}

}  // namespace gpu
<|endoftext|>