<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <iostream>
#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"

#if defined(_MSC_VER)
namespace std
{
	using ::isprint;
}
#define for if (false) {} else for
#endif

namespace
{
	template <class T>
	void call_destructor(T* o)
	{
		TORRENT_ASSERT(o);
		o->~T();
	}

	struct compare_string
	{
		compare_string(char const* s): m_str(s)  {}

		bool operator()(
			std::pair<std::string
			, libtorrent::entry> const& e) const
		{
			return m_str && e.first == m_str;
		}
		char const* m_str;
	};
}

namespace libtorrent
{
	namespace detail
	{
		TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val)
		{
			int sign = 0;
			if (val < 0)
			{
				sign = 1;
				val = -val;
			}
			buf[--size] = '\0';
			if (val == 0) buf[--size] = '0';
			for (; size > sign && val != 0;)
			{
				buf[--size] = '0' + char(val % 10);
				val /= 10;
			}
			if (sign) buf[--size] = '-';
			return buf + size;
		}
	}

	entry& entry::operator[](char const* key)
	{
		dictionary_type::iterator i = dict().find(key);
		if (i != dict().end()) return i->second;
		dictionary_type::iterator ret = dict().insert(
			dict().begin()
			, std::make_pair(std::string(key), entry()));
		return ret->second;
	}

	entry& entry::operator[](std::string const& key)
	{
		return (*this)[key.c_str()];
	}

	entry* entry::find_key(char const* key)
	{
		dictionary_type::iterator i = std::find_if(
			dict().begin()
			, dict().end()
			, compare_string(key));
		if (i == dict().end()) return 0;
		return &i->second;

	}

	entry const* entry::find_key(char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) return 0;
		return &i->second;
	}

#ifndef BOOST_NO_EXCEPTIONS
	const entry& entry::operator[](char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) throw type_error(
			(std::string("key not found: ") + key).c_str());
		return i->second;
	}

	const entry& entry::operator[](std::string const& key) const
	{
		return (*this)[key.c_str()];
	}
#endif

	entry::entry()
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	entry::entry(data_type t)
		: m_type(undefined_t)
	{
		construct(t);
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	entry::entry(const entry& e)
		: m_type(undefined_t)
	{
		copy(e);
#ifndef NDEBUG
		m_type_queried = e.m_type_queried;
#endif
	}

	entry::entry(dictionary_type const& v)
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	entry::entry(string_type const& v)
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
		new(data) string_type(v);
		m_type = string_t;
	}

	entry::entry(list_type const& v)
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
		new(data) list_type(v);
		m_type = list_t;
	}

	entry::entry(integer_type const& v)
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
		new(data) integer_type(v);
		m_type = int_t;
	}

	void entry::operator=(dictionary_type const& v)
	{
		destruct();
		new(data) dictionary_type(v);
		m_type = dictionary_t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::operator=(string_type const& v)
	{
		destruct();
		new(data) string_type(v);
		m_type = string_t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::operator=(list_type const& v)
	{
		destruct();
		new(data) list_type(v);
		m_type = list_t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::operator=(integer_type const& v)
	{
		destruct();
		new(data) integer_type(v);
		m_type = int_t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	bool entry::operator==(entry const& e) const
	{
		if (m_type != e.m_type) return false;

		switch(m_type)
		{
		case int_t:
			return integer() == e.integer();
		case string_t:
			return string() == e.string();
		case list_t:
			return list() == e.list();
		case dictionary_t:
			return dict() == e.dict();
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			return true;
		}
	}

	void entry::construct(data_type t)
	{
		switch(t)
		{
		case int_t:
			new(data) integer_type;
			break;
		case string_t:
			new(data) string_type;
			break;
		case list_t:
			new(data) list_type;
			break;
		case dictionary_t:
			new (data) dictionary_type;
			break;
		default:
			TORRENT_ASSERT(t == undefined_t);
		}
		m_type = t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::copy(entry const& e)
	{
		switch (e.type())
		{
		case int_t:
			new(data) integer_type(e.integer());
			break;
		case string_t:
			new(data) string_type(e.string());
			break;
		case list_t:
			new(data) list_type(e.list());
			break;
		case dictionary_t:
			new (data) dictionary_type(e.dict());
			break;
		default:
			TORRENT_ASSERT(e.type() == undefined_t);
		}
		m_type = e.type();
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::destruct()
	{
		switch(m_type)
		{
		case int_t:
			call_destructor(reinterpret_cast<integer_type*>(data));
			break;
		case string_t:
			call_destructor(reinterpret_cast<string_type*>(data));
			break;
		case list_t:
			call_destructor(reinterpret_cast<list_type*>(data));
			break;
		case dictionary_t:
			call_destructor(reinterpret_cast<dictionary_type*>(data));
			break;
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			break;
		}
		m_type = undefined_t;
#ifndef NDEBUG
		m_type_queried = false;
#endif
	}

	void entry::swap(entry& e)
	{
		// not implemented
		TORRENT_ASSERT(false);
	}

	void entry::print(std::ostream& os, int indent) const
	{
		TORRENT_ASSERT(indent >= 0);
		for (int i = 0; i < indent; ++i) os << " ";
		switch (m_type)
		{
		case int_t:
			os << integer() << "\n";
			break;
		case string_t:
			{
				bool binary_string = false;
				for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
				{
					if (!std::isprint(static_cast<unsigned char>(*i)))
					{
						binary_string = true;
						break;
					}
				}
				if (binary_string)
				{
					os.unsetf(std::ios_base::dec);
					os.setf(std::ios_base::hex);
					for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
						os << std::setfill('0') << std::setw(2)
							<< static_cast<unsigned int>((unsigned char)*i);
					os.unsetf(std::ios_base::hex);
					os.setf(std::ios_base::dec);
					os << "\n";
				}
				else
				{
					os << string() << "\n";
				}
			} break;
		case list_t:
			{
				os << "list\n";
				for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
				{
					i->print(os, indent+1);
				}
			} break;
		case dictionary_t:
			{
				os << "dictionary\n";
				for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
				{
					for (int j = 0; j < indent+1; ++j) os << " ";
					os << "[" << i->first << "]";
					if (i->second.type() != entry::string_t
						&& i->second.type() != entry::int_t)
						os << "\n";
					else os << " ";
					i->second.print(os, indent+2);
				}
			} break;
		default:
			os << "<uninitialized>\n";
		}
	}
}

<commit_msg>reverted last check in<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include <algorithm>
#include <iostream>
#include <iomanip>
#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"

#if defined(_MSC_VER)
namespace std
{
	using ::isprint;
}
#define for if (false) {} else for
#endif

namespace
{
	template <class T>
	void call_destructor(T* o)
	{
		TORRENT_ASSERT(o);
		o->~T();
	}

	struct compare_string
	{
		compare_string(char const* s): m_str(s)  {}

		bool operator()(
			std::pair<std::string
			, libtorrent::entry> const& e) const
		{
			return m_str && e.first == m_str;
		}
		char const* m_str;
	};
}

namespace libtorrent
{
	namespace detail
	{
		TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val)
		{
			int sign = 0;
			if (val < 0)
			{
				sign = 1;
				val = -val;
			}
			buf[--size] = '\0';
			if (val == 0) buf[--size] = '0';
			for (; size > sign && val != 0;)
			{
				buf[--size] = '0' + char(val % 10);
				val /= 10;
			}
			if (sign) buf[--size] = '-';
			return buf + size;
		}
	}

	entry& entry::operator[](char const* key)
	{
		dictionary_type::iterator i = dict().find(key);
		if (i != dict().end()) return i->second;
		dictionary_type::iterator ret = dict().insert(
			dict().begin()
			, std::make_pair(std::string(key), entry()));
		return ret->second;
	}

	entry& entry::operator[](std::string const& key)
	{
		return (*this)[key.c_str()];
	}

	entry* entry::find_key(char const* key)
	{
		dictionary_type::iterator i = std::find_if(
			dict().begin()
			, dict().end()
			, compare_string(key));
		if (i == dict().end()) return 0;
		return &i->second;

	}

	entry const* entry::find_key(char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) return 0;
		return &i->second;
	}

#ifndef BOOST_NO_EXCEPTIONS
	const entry& entry::operator[](char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) throw type_error(
			(std::string("key not found: ") + key).c_str());
		return i->second;
	}

	const entry& entry::operator[](std::string const& key) const
	{
		return (*this)[key.c_str()];
	}
#endif

	entry::entry()
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	entry::entry(data_type t)
		: m_type(undefined_t)
	{
		construct(t);
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	entry::entry(const entry& e)
		: m_type(undefined_t)
	{
		copy(e);
#ifndef NDEBUG
		m_type_queried = e.m_type_queried;
#endif
	}

	entry::entry(dictionary_type const& v)
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	entry::entry(string_type const& v)
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
		new(data) string_type(v);
		m_type = string_t;
	}

	entry::entry(list_type const& v)
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
		new(data) list_type(v);
		m_type = list_t;
	}

	entry::entry(integer_type const& v)
		: m_type(undefined_t)
	{
#ifndef NDEBUG
		m_type_queried = true;
#endif
		new(data) integer_type(v);
		m_type = int_t;
	}

	void entry::operator=(dictionary_type const& v)
	{
		destruct();
		new(data) dictionary_type(v);
		m_type = dictionary_t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::operator=(string_type const& v)
	{
		destruct();
		new(data) string_type(v);
		m_type = string_t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::operator=(list_type const& v)
	{
		destruct();
		new(data) list_type(v);
		m_type = list_t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::operator=(integer_type const& v)
	{
		destruct();
		new(data) integer_type(v);
		m_type = int_t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	bool entry::operator==(entry const& e) const
	{
		if (m_type != e.m_type) return false;

		switch(m_type)
		{
		case int_t:
			return integer() == e.integer();
		case string_t:
			return string() == e.string();
		case list_t:
			return list() == e.list();
		case dictionary_t:
			return dict() == e.dict();
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			return true;
		}
	}

	void entry::construct(data_type t)
	{
		switch(t)
		{
		case int_t:
			new(data) integer_type;
			break;
		case string_t:
			new(data) string_type;
			break;
		case list_t:
			new(data) list_type;
			break;
		case dictionary_t:
			new (data) dictionary_type;
			break;
		default:
			TORRENT_ASSERT(t == undefined_t);
		}
		m_type = t;
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::copy(entry const& e)
	{
		switch (e.type())
		{
		case int_t:
			new(data) integer_type(e.integer());
			break;
		case string_t:
			new(data) string_type(e.string());
			break;
		case list_t:
			new(data) list_type(e.list());
			break;
		case dictionary_t:
			new (data) dictionary_type(e.dict());
			break;
		default:
			TORRENT_ASSERT(e.type() == undefined_t);
		}
		m_type = e.type();
#ifndef NDEBUG
		m_type_queried = true;
#endif
	}

	void entry::destruct()
	{
		switch(m_type)
		{
		case int_t:
			call_destructor(reinterpret_cast<integer_type*>(data));
			break;
		case string_t:
			call_destructor(reinterpret_cast<string_type*>(data));
			break;
		case list_t:
			call_destructor(reinterpret_cast<list_type*>(data));
			break;
		case dictionary_t:
			call_destructor(reinterpret_cast<dictionary_type*>(data));
			break;
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			break;
		}
		m_type = undefined_t;
#ifndef NDEBUG
		m_type_queried = false;
#endif
	}

	void entry::swap(entry& e)
	{
		// not implemented
		TORRENT_ASSERT(false);
	}

	void entry::print(std::ostream& os, int indent) const
	{
		TORRENT_ASSERT(indent >= 0);
		for (int i = 0; i < indent; ++i) os << " ";
		switch (m_type)
		{
		case int_t:
			os << integer() << "\n";
			break;
		case string_t:
			{
				bool binary_string = false;
				for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
				{
					if (!std::isprint(static_cast<unsigned char>(*i)))
					{
						binary_string = true;
						break;
					}
				}
				if (binary_string)
				{
					os.unsetf(std::ios_base::dec);
					os.setf(std::ios_base::hex);
					for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
						os << std::setfill('0') << std::setw(2)
							<< static_cast<unsigned int>((unsigned char)*i);
					os.unsetf(std::ios_base::hex);
					os.setf(std::ios_base::dec);
					os << "\n";
				}
				else
				{
					os << string() << "\n";
				}
			} break;
		case list_t:
			{
				os << "list\n";
				for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
				{
					i->print(os, indent+1);
				}
			} break;
		case dictionary_t:
			{
				os << "dictionary\n";
				for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
				{
					for (int j = 0; j < indent+1; ++j) os << " ";
					os << "[" << i->first << "]";
					if (i->second.type() != entry::string_t
						&& i->second.type() != entry::int_t)
						os << "\n";
					else os << " ";
					i->second.print(os, indent+2);
				}
			} break;
		default:
			os << "<uninitialized>\n";
		}
	}
}

<|endoftext|>


<commit_before>#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
<commit_msg>delete stb_image_write.cpp<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: galmisc.hxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-26 07:23:09 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SVX_GALMISC_HXX_
#define _SVX_GALMISC_HXX_

#include <sot/storage.hxx>
#include <tools/urlobj.hxx>
#include <svtools/imap.hxx>
#include <svtools/hint.hxx>
#include <svtools/transfer.hxx>
#include "svdobj.hxx"
#include "galobj.hxx"

#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif
#ifndef _COM_SUN_STAR_AWT_XPROGRESSMONITOR_HPP
#include <com/sun/star/awt/XProgressMonitor.hpp>
#endif

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

// -----------
// - Defines -
// -----------

#define IV_IMAPINFO             (UINT32('S')*0x00000001+UINT32('D')*0x00000100+UINT32('U')*0x00010000+UINT32('D')*0x01000000)
#define ID_IMAPINFO             2

#define USERDATA_HDL()          (LINK(this,SgaUserDataFactory,MakeUserData))

#define GAL_RESID( nId )        ResId( nId, *GetGalleryResMgr() )
#define STREAMBUF_SIZE          16384L

#define SGA_IMPORT_NONE         0x0000
#define SGA_IMPORT_FILE         0x0001
#define SGA_IMPORT_INET         0x0002

#define GALLERY_PROGRESS_RANGE  10000

#define GALLERY_FG_COLOR        Application::GetSettings().GetStyleSettings().GetWindowTextColor()
#define GALLERY_BG_COLOR        Application::GetSettings().GetStyleSettings().GetWindowColor()
#define GALLERY_DLG_COLOR       Application::GetSettings().GetStyleSettings().GetDialogColor()

// -------------
// - Functions -
// -------------

class ResMgr;
class String;
class SvStream;
class Graphic;
class FmFormModel;
class ImageMap;
class Gallery;

SVX_DLLPUBLIC ResMgr*           GetGalleryResMgr();
USHORT          GalleryGraphicImport( const INetURLObject& rURL, Graphic& rGraphic, String& rFilterName, BOOL bShowProgress = FALSE );
BOOL            GallerySvDrawImport( SvStream& rIStm, FmFormModel& rModel );
BOOL            CreateIMapGraphic( const FmFormModel& rModel, Graphic& rGraphic, ImageMap& rImageMap );
SVX_DLLPUBLIC String            GetReducedString( const INetURLObject& rURL, ULONG nMaxLen );
String          GetSvDrawStreamNameFromURL( const INetURLObject& rSvDrawObjURL );

BOOL            FileExists( const INetURLObject& rURL );
BOOL            CreateDir(  const INetURLObject& rURL );
BOOL            CopyFile(  const INetURLObject& rSrcURL, const INetURLObject& rDstURL );
BOOL            KillFile( const INetURLObject& rURL );
BitmapEx        GalleryResGetBitmapEx( sal_uInt32 nId );

// ---------------
// - SgaIMapInfo -
// ---------------

class SgaIMapInfo : public SdrObjUserData, public SfxListener
{
    ImageMap                aImageMap;

public:
                            SgaIMapInfo() : SdrObjUserData( IV_IMAPINFO, ID_IMAPINFO, 0 ) {};

                            SgaIMapInfo( const ImageMap& rImageMap) :
                                SdrObjUserData( IV_IMAPINFO, ID_IMAPINFO, 0 ),
                                aImageMap( rImageMap ) {};

    virtual                 ~SgaIMapInfo() {};

    virtual SdrObjUserData* Clone( SdrObject* ) const
                            {
                                SgaIMapInfo* pInfo = new SgaIMapInfo;
                                pInfo->aImageMap = aImageMap;
                                return pInfo;
                            }

    const ImageMap&         GetImageMap() const { return aImageMap; }
};

// ----------------------
// - SgaUserDataFactory -
// ----------------------

class SgaUserDataFactory
{
public:
        SgaUserDataFactory() { SdrObjFactory::InsertMakeUserDataHdl( USERDATA_HDL() ); }
        ~SgaUserDataFactory() { SdrObjFactory::RemoveMakeUserDataHdl( USERDATA_HDL() ); }

        DECL_LINK( MakeUserData, SdrObjFactory* );
};

// -------------------
// - GalleryProgress -
// -------------------

class GraphicFilter;

class SVX_DLLPUBLIC GalleryProgress
{
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XProgressBar > mxProgressBar;
    GraphicFilter*                                                          mpFilter;

    public:

                                    GalleryProgress( GraphicFilter* pFilter = NULL );
                                    ~GalleryProgress();

    void                            Update( ULONG nVal, ULONG nMaxVal );
};

// -----------------------
// - GalleryTransferable -
// -----------------------

class Gallery;
class GalleryTheme;
class GraphicObject;

class GalleryTransferable : public TransferableHelper
{
friend class GalleryTheme;
using TransferableHelper::CopyToClipboard;

private:

    GalleryTheme*                   mpTheme;
    SgaObjKind                      meObjectKind;
    sal_uInt32                      mnObjectPos;
    SotStorageStreamRef             mxModelStream;
    GraphicObject*                  mpGraphicObject;
    ImageMap*                       mpImageMap;
    INetURLObject*                  mpURL;

protected:

                                    GalleryTransferable( GalleryTheme* pTheme, ULONG nObjectPos, bool bLazy );
                                    ~GalleryTransferable();

    void                            InitData( bool bLazy );

    // TransferableHelper
    virtual void                    AddSupportedFormats();
    virtual sal_Bool                GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor );
    virtual sal_Bool                WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const ::com::sun::star::datatransfer::DataFlavor& rFlavor );
    virtual void                    DragFinished( sal_Int8 nDropAction );
    virtual void                    ObjectReleased();

    void                            CopyToClipboard( Window* pWindow );
    void                            StartDrag( Window* pWindow, sal_Int8 nDragSourceActions,
                                               sal_Int32 nDragPointer = DND_POINTER_NONE,
                                               sal_Int32 nDragImage = DND_IMAGE_NONE );
};

// ---------------
// - GalleryHint -
// ---------------

#define GALLERY_HINT_NONE               0x00000000
#define GALLERY_HINT_CLOSE_THEME        0x00000001
#define GALLERY_HINT_THEME_REMOVED      0x00000002
#define GALLERY_HINT_THEME_RENAMED      0x00000004
#define GALLERY_HINT_THEME_CREATED      0x00000008
#define GALLERY_HINT_THEME_UPDATEVIEW   0x00000010
#define GALLERY_HINT_CLOSE_OBJECT       0x00000020
#define GALLERY_HINT_OBJECT_REMOVED     0x00000040

// -----------------------------------------------------------------------------

class GalleryHint : public SfxHint
{
private:

    ULONG           mnType;
    String          maThemeName;
    String          maStringData;
    ULONG           mnData1;
    ULONG           mnData2;

public:

                    GalleryHint( ULONG nType, const String& rThemeName, ULONG nData1 = 0UL, ULONG nData2 = 0UL ) :
                        mnType( nType ), maThemeName( rThemeName ), mnData1( nData1 ), mnData2( nData2 ) {}

                    GalleryHint( ULONG nType, const String& rThemeName, const String& rStringData, ULONG nData1 = 0UL, ULONG nData2 = 0UL ) :
                        mnType( nType ), maThemeName( rThemeName ), maStringData( rStringData ), mnData1( nData1 ), mnData2( nData2 ) {}

    ULONG           GetType() const { return mnType; }
    const String&   GetThemeName() const { return maThemeName; }
    const String&   GetStringData() const { return maStringData; }
    ULONG           GetData1() const { return mnData1; }
    ULONG           GetData2() const { return mnData2; }
};

    #endif
<commit_msg>INTEGRATION: CWS vgbugs07 (1.16.50); FILE MERGED 2007/06/04 13:26:06 vg 1.16.50.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: galmisc.hxx,v $
 *
 *  $Revision: 1.17 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 16:32:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SVX_GALMISC_HXX_
#define _SVX_GALMISC_HXX_

#include <sot/storage.hxx>
#include <tools/urlobj.hxx>
#include <svtools/imap.hxx>
#include <svtools/hint.hxx>
#include <svtools/transfer.hxx>
#include <svx/svdobj.hxx>
#include "galobj.hxx"

#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif
#ifndef _COM_SUN_STAR_AWT_XPROGRESSMONITOR_HPP
#include <com/sun/star/awt/XProgressMonitor.hpp>
#endif

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

// -----------
// - Defines -
// -----------

#define IV_IMAPINFO             (UINT32('S')*0x00000001+UINT32('D')*0x00000100+UINT32('U')*0x00010000+UINT32('D')*0x01000000)
#define ID_IMAPINFO             2

#define USERDATA_HDL()          (LINK(this,SgaUserDataFactory,MakeUserData))

#define GAL_RESID( nId )        ResId( nId, *GetGalleryResMgr() )
#define STREAMBUF_SIZE          16384L

#define SGA_IMPORT_NONE         0x0000
#define SGA_IMPORT_FILE         0x0001
#define SGA_IMPORT_INET         0x0002

#define GALLERY_PROGRESS_RANGE  10000

#define GALLERY_FG_COLOR        Application::GetSettings().GetStyleSettings().GetWindowTextColor()
#define GALLERY_BG_COLOR        Application::GetSettings().GetStyleSettings().GetWindowColor()
#define GALLERY_DLG_COLOR       Application::GetSettings().GetStyleSettings().GetDialogColor()

// -------------
// - Functions -
// -------------

class ResMgr;
class String;
class SvStream;
class Graphic;
class FmFormModel;
class ImageMap;
class Gallery;

SVX_DLLPUBLIC ResMgr*           GetGalleryResMgr();
USHORT          GalleryGraphicImport( const INetURLObject& rURL, Graphic& rGraphic, String& rFilterName, BOOL bShowProgress = FALSE );
BOOL            GallerySvDrawImport( SvStream& rIStm, FmFormModel& rModel );
BOOL            CreateIMapGraphic( const FmFormModel& rModel, Graphic& rGraphic, ImageMap& rImageMap );
SVX_DLLPUBLIC String            GetReducedString( const INetURLObject& rURL, ULONG nMaxLen );
String          GetSvDrawStreamNameFromURL( const INetURLObject& rSvDrawObjURL );

BOOL            FileExists( const INetURLObject& rURL );
BOOL            CreateDir(  const INetURLObject& rURL );
BOOL            CopyFile(  const INetURLObject& rSrcURL, const INetURLObject& rDstURL );
BOOL            KillFile( const INetURLObject& rURL );
BitmapEx        GalleryResGetBitmapEx( sal_uInt32 nId );

// ---------------
// - SgaIMapInfo -
// ---------------

class SgaIMapInfo : public SdrObjUserData, public SfxListener
{
    ImageMap                aImageMap;

public:
                            SgaIMapInfo() : SdrObjUserData( IV_IMAPINFO, ID_IMAPINFO, 0 ) {};

                            SgaIMapInfo( const ImageMap& rImageMap) :
                                SdrObjUserData( IV_IMAPINFO, ID_IMAPINFO, 0 ),
                                aImageMap( rImageMap ) {};

    virtual                 ~SgaIMapInfo() {};

    virtual SdrObjUserData* Clone( SdrObject* ) const
                            {
                                SgaIMapInfo* pInfo = new SgaIMapInfo;
                                pInfo->aImageMap = aImageMap;
                                return pInfo;
                            }

    const ImageMap&         GetImageMap() const { return aImageMap; }
};

// ----------------------
// - SgaUserDataFactory -
// ----------------------

class SgaUserDataFactory
{
public:
        SgaUserDataFactory() { SdrObjFactory::InsertMakeUserDataHdl( USERDATA_HDL() ); }
        ~SgaUserDataFactory() { SdrObjFactory::RemoveMakeUserDataHdl( USERDATA_HDL() ); }

        DECL_LINK( MakeUserData, SdrObjFactory* );
};

// -------------------
// - GalleryProgress -
// -------------------

class GraphicFilter;

class SVX_DLLPUBLIC GalleryProgress
{
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XProgressBar > mxProgressBar;
    GraphicFilter*                                                          mpFilter;

    public:

                                    GalleryProgress( GraphicFilter* pFilter = NULL );
                                    ~GalleryProgress();

    void                            Update( ULONG nVal, ULONG nMaxVal );
};

// -----------------------
// - GalleryTransferable -
// -----------------------

class Gallery;
class GalleryTheme;
class GraphicObject;

class GalleryTransferable : public TransferableHelper
{
friend class GalleryTheme;
using TransferableHelper::CopyToClipboard;

private:

    GalleryTheme*                   mpTheme;
    SgaObjKind                      meObjectKind;
    sal_uInt32                      mnObjectPos;
    SotStorageStreamRef             mxModelStream;
    GraphicObject*                  mpGraphicObject;
    ImageMap*                       mpImageMap;
    INetURLObject*                  mpURL;

protected:

                                    GalleryTransferable( GalleryTheme* pTheme, ULONG nObjectPos, bool bLazy );
                                    ~GalleryTransferable();

    void                            InitData( bool bLazy );

    // TransferableHelper
    virtual void                    AddSupportedFormats();
    virtual sal_Bool                GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor );
    virtual sal_Bool                WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const ::com::sun::star::datatransfer::DataFlavor& rFlavor );
    virtual void                    DragFinished( sal_Int8 nDropAction );
    virtual void                    ObjectReleased();

    void                            CopyToClipboard( Window* pWindow );
    void                            StartDrag( Window* pWindow, sal_Int8 nDragSourceActions,
                                               sal_Int32 nDragPointer = DND_POINTER_NONE,
                                               sal_Int32 nDragImage = DND_IMAGE_NONE );
};

// ---------------
// - GalleryHint -
// ---------------

#define GALLERY_HINT_NONE               0x00000000
#define GALLERY_HINT_CLOSE_THEME        0x00000001
#define GALLERY_HINT_THEME_REMOVED      0x00000002
#define GALLERY_HINT_THEME_RENAMED      0x00000004
#define GALLERY_HINT_THEME_CREATED      0x00000008
#define GALLERY_HINT_THEME_UPDATEVIEW   0x00000010
#define GALLERY_HINT_CLOSE_OBJECT       0x00000020
#define GALLERY_HINT_OBJECT_REMOVED     0x00000040

// -----------------------------------------------------------------------------

class GalleryHint : public SfxHint
{
private:

    ULONG           mnType;
    String          maThemeName;
    String          maStringData;
    ULONG           mnData1;
    ULONG           mnData2;

public:

                    GalleryHint( ULONG nType, const String& rThemeName, ULONG nData1 = 0UL, ULONG nData2 = 0UL ) :
                        mnType( nType ), maThemeName( rThemeName ), mnData1( nData1 ), mnData2( nData2 ) {}

                    GalleryHint( ULONG nType, const String& rThemeName, const String& rStringData, ULONG nData1 = 0UL, ULONG nData2 = 0UL ) :
                        mnType( nType ), maThemeName( rThemeName ), maStringData( rStringData ), mnData1( nData1 ), mnData2( nData2 ) {}

    ULONG           GetType() const { return mnType; }
    const String&   GetThemeName() const { return maThemeName; }
    const String&   GetStringData() const { return maStringData; }
    ULONG           GetData1() const { return mnData1; }
    ULONG           GetData2() const { return mnData2; }
};

    #endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: linkmgr.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 18:01:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _SVXLINKMGR_HXX
#define _SVXLINKMGR_HXX

#ifndef _LINKMGR_HXX
#include <sfx2/linkmgr.hxx>
#endif

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

class Graphic;
class Size;

// Damit der Link ueber den Status der zu ladenen Grafik informierten werden
// verschickt das FileObject ein SvData, mit der FormatId
// "RegisterStatusInfoId" und ein einem String als Datentraeger. Dieser
// enthaelt den folgenden enum.
enum LinkState
{
    STATE_LOAD_OK,
    STATE_LOAD_ERROR,
    STATE_LOAD_ABORT
};

class SVX_DLLPUBLIC SvxLinkManager : public ::sfx2::SvLinkManager
{
    SvxLinkManager( const SvxLinkManager& );
    SvxLinkManager& operator=( const SvxLinkManager& );

public:
    SvxLinkManager( SfxObjectShell * pCacheCont );

    // den Link mit einem PseudoObject verbinden und in die Liste eintragen
    BOOL InsertFileLink( sfx2::SvBaseLink&,
                        USHORT nFileType,
                        const String& rTxt,
                        const String* pFilterNm = 0,
                        const String* pRange = 0 );

            // falls am Link schon alles eingestellt ist !
    BOOL InsertFileLink( sfx2::SvBaseLink& );

        // erfrage die Strings fuer den Dialog
    virtual BOOL GetDisplayNames( const sfx2::SvBaseLink*,
                                    String* pType,
                                    String* pFile = 0,
                                    String* pLink = 0,
                                    String* pFilter = 0 ) const;

    virtual sfx2::SvLinkSourceRef CreateObj( sfx2::SvBaseLink * );

    // eine Uebertragung wird abgebrochen, also alle DownloadMedien canceln
    // (ist zur Zeit nur fuer die FileLinks interressant!)
    void CancelTransfers();

    static void SetTransferPriority( sfx2::SvBaseLink& rLink, USHORT nPrio );

    // um Status Informationen aus dem FileObject an den BaseLink zu
    // senden, gibt es eine eigene ClipBoardId. Das SvData-Object hat
    // dann die entsprechenden Informationen als String.
    // Wird zur Zeit fuer FileObject in Verbindung mit JavaScript benoetigt
    // - das braucht Informationen ueber Load/Abort/Error
    static ULONG  RegisterStatusInfoId();

    // if the mimetype says graphic/bitmap/gdimetafile then get the
    // graphic from the Any. Return says no errors
    static BOOL GetGraphicFromAny( const String& rMimeType,
                                const ::com::sun::star::uno::Any & rValue,
                                Graphic& rGrf );

};

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.6.1256); FILE MERGED 2008/04/01 15:49:17 thb 1.6.1256.3: #i85898# Stripping all external header guards 2008/04/01 12:46:22 thb 1.6.1256.2: #i85898# Stripping all external header guards 2008/03/31 14:17:56 rt 1.6.1256.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: linkmgr.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SVXLINKMGR_HXX
#define _SVXLINKMGR_HXX

#include <sfx2/linkmgr.hxx>
#include "svx/svxdllapi.h"

class Graphic;
class Size;

// Damit der Link ueber den Status der zu ladenen Grafik informierten werden
// verschickt das FileObject ein SvData, mit der FormatId
// "RegisterStatusInfoId" und ein einem String als Datentraeger. Dieser
// enthaelt den folgenden enum.
enum LinkState
{
    STATE_LOAD_OK,
    STATE_LOAD_ERROR,
    STATE_LOAD_ABORT
};

class SVX_DLLPUBLIC SvxLinkManager : public ::sfx2::SvLinkManager
{
    SvxLinkManager( const SvxLinkManager& );
    SvxLinkManager& operator=( const SvxLinkManager& );

public:
    SvxLinkManager( SfxObjectShell * pCacheCont );

    // den Link mit einem PseudoObject verbinden und in die Liste eintragen
    BOOL InsertFileLink( sfx2::SvBaseLink&,
                        USHORT nFileType,
                        const String& rTxt,
                        const String* pFilterNm = 0,
                        const String* pRange = 0 );

            // falls am Link schon alles eingestellt ist !
    BOOL InsertFileLink( sfx2::SvBaseLink& );

        // erfrage die Strings fuer den Dialog
    virtual BOOL GetDisplayNames( const sfx2::SvBaseLink*,
                                    String* pType,
                                    String* pFile = 0,
                                    String* pLink = 0,
                                    String* pFilter = 0 ) const;

    virtual sfx2::SvLinkSourceRef CreateObj( sfx2::SvBaseLink * );

    // eine Uebertragung wird abgebrochen, also alle DownloadMedien canceln
    // (ist zur Zeit nur fuer die FileLinks interressant!)
    void CancelTransfers();

    static void SetTransferPriority( sfx2::SvBaseLink& rLink, USHORT nPrio );

    // um Status Informationen aus dem FileObject an den BaseLink zu
    // senden, gibt es eine eigene ClipBoardId. Das SvData-Object hat
    // dann die entsprechenden Informationen als String.
    // Wird zur Zeit fuer FileObject in Verbindung mit JavaScript benoetigt
    // - das braucht Informationen ueber Load/Abort/Error
    static ULONG  RegisterStatusInfoId();

    // if the mimetype says graphic/bitmap/gdimetafile then get the
    // graphic from the Any. Return says no errors
    static BOOL GetGraphicFromAny( const String& rMimeType,
                                const ::com::sun::star::uno::Any & rValue,
                                Graphic& rGrf );

};

#endif

<|endoftext|>


<commit_before>/// \file ROOT/RAttrBase.hxx
/// \ingroup Gpad ROOT7
/// \author Sergey Linev <s.linev@gsi.de>
/// \date 2019-09-17
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

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

#ifndef ROOT7_RAttrBase
#define ROOT7_RAttrBase

#include <ROOT/RAttrMap.hxx>
#include <ROOT/RStyle.hxx>
#include <ROOT/RDrawable.hxx>

namespace ROOT {
namespace Experimental {

/** Base class for all attributes, used with RDrawable */
class RAttrBase {

   friend class RAttrMap;

   RDrawable *fDrawable{nullptr};      ///<! drawable used to store attributes
   std::unique_ptr<RAttrMap> fOwnAttr; ///<! own instance when deep copy is created
   std::string fPrefix;                ///<! name prefix for all attributes values
   const RAttrBase *fParent{nullptr};  ///<! parent attributes, prefix applied to it

protected:

   virtual const RAttrMap &GetDefaults() const;

   bool CopyValue(const std::string &name, const RAttrMap::Value_t &value, bool check_type = true);

   bool IsValueEqual(const std::string &name, const RAttrMap::Value_t *value, bool use_style = false) const;

   ///////////////////////////////////////////////////////////////////////////////

   void AssignDrawable(RDrawable *drawable, const std::string &prefix);

   void AssignParent(const RAttrBase *parent, const std::string &prefix);

   struct Rec_t {
      RAttrMap *attr{nullptr};
      std::string fullname;
      RDrawable *drawable{nullptr};
      operator bool() const { return !!attr; }
   };

   /// Find attributes container and full-qualified name for value
   const Rec_t AccessAttr(const std::string &name) const
   {
      const RAttrBase *prnt = this;
      std::string fullname = name;
      while (prnt) {
         fullname.insert(0, prnt->fPrefix);  // fullname = prnt->fPrefix + fullname
         if (prnt->fDrawable)
            return { &(prnt->fDrawable->fAttr), fullname, prnt->fDrawable };
         if (prnt->fOwnAttr)
            return { prnt->fOwnAttr.get(), fullname, nullptr };
         prnt = prnt->fParent;
      }
      return {nullptr, fullname, nullptr};
   }

   struct Val_t {
      const RAttrMap::Value_t *value{nullptr};
      std::shared_ptr<RStyle> style;
      operator bool() const { return !!value; }
   };

   const Val_t AccessValue(const std::string &name, bool use_style = true) const
   {
      if (auto access = AccessAttr(name)) {
         auto rec = access.attr->Find(access.fullname);
         if (rec) return { rec, nullptr };
         if (access.drawable && use_style)
            if (auto observe = access.drawable->fStyle.lock()) {
               if ((rec = observe->Eval(access.fullname, access.drawable)))
                  return { rec, observe };
            }
      }

      return { nullptr, nullptr };
   }

   Rec_t EnsureAttr(const std::string &name)
   {
      const RAttrBase *prnt = this;
      std::string fullname = name;
      while (prnt) {
         fullname.insert(0, prnt->fPrefix);  // fullname = prnt->fPrefix + fullname
         if (prnt->fDrawable)
            return { &(prnt->fDrawable->fAttr), fullname, prnt->fDrawable };
         if (!prnt->fParent && !prnt->fOwnAttr)
            const_cast<RAttrBase *>(prnt)->fOwnAttr = std::make_unique<RAttrMap>();
         if (prnt->fOwnAttr)
            return { prnt->fOwnAttr.get(), fullname, nullptr };
         prnt = prnt->fParent;
      }
      return {nullptr, fullname, nullptr};
   }

   /// Evaluate attribute value

   template <typename T,typename S = void>
   auto Eval(const std::string &name, bool use_dflts = true) const
   {
      if (auto v = AccessValue(name, true))
         return RAttrMap::Value_t::get_value<T,S>(v.value);

      const RAttrMap::Value_t *rec = nullptr;

      if (use_dflts)
         rec = GetDefaults().Find(name);

      return RAttrMap::Value_t::get_value<T,S>(rec);
   }

   double *GetDoublePtr(const std::string &name) const;

   void CopyTo(RAttrBase &tgt, bool use_style = true) const;

   bool IsSame(const RAttrBase &src, bool use_style = true) const;

   RAttrBase(RDrawable *drawable, const std::string &prefix = "") { AssignDrawable(drawable, prefix); }

   RAttrBase(const RAttrBase *parent, const std::string &prefix = "") { AssignParent(parent, prefix); }

   RAttrBase(const RAttrBase &src) { src.CopyTo(*this); }

   RAttrBase &operator=(const RAttrBase &src) { Clear(); src.CopyTo(*this); return *this; }

   void SetValue(const std::string &name, double value);
   void SetValue(const std::string &name, const int value);
   void SetValue(const std::string &name, const std::string &value);

   std::string GetPrefix() const { return fPrefix; }

   void ClearValue(const std::string &name);

   void Clear();

   template<typename T = void, std::enable_if_t<!std::is_pointer<T>{}>* = nullptr>
   bool HasValue(const std::string &name, bool check_defaults = false) const { return Eval<const RAttrMap::Value_t *,T>(name, check_defaults) != nullptr; }

   template<typename T, std::enable_if_t<!std::is_pointer<T>{}>* = nullptr>
   T GetValue(const std::string &name) const { return Eval<T>(name); }

public:
   RAttrBase() = default;

   virtual ~RAttrBase() = default;

   friend bool operator==(const RAttrBase& lhs, const RAttrBase& rhs){ return lhs.IsSame(rhs) && rhs.IsSame(lhs); }
   friend bool operator!=(const RAttrBase& lhs, const RAttrBase& rhs){ return !lhs.IsSame(rhs) || !rhs.IsSame(lhs); }
};

} // namespace Experimental
} // namespace ROOT

#define R__ATTR_CLASS(ClassName,dflt_prefix,dflt_values) \
protected: \
const RAttrMap &GetDefaults() const override \
{ \
   static auto dflts = RAttrMap().dflt_values; \
   return dflts; \
} \
public: \
   ClassName() = default; \
   ClassName(RDrawable *drawable, const std::string &prefix = dflt_prefix) { AssignDrawable(drawable, prefix); } \
   ClassName(const RAttrBase *parent, const std::string &prefix = dflt_prefix) { AssignParent(parent, prefix); } \
   ClassName(const ClassName &src) : ClassName() { src.CopyTo(*this); } \
   ClassName &operator=(const ClassName &src) { Clear(); src.CopyTo(*this); return *this; }

#endif
<commit_msg>[rdrawable] adjust signatures in RAttrBase<commit_after>/// \file ROOT/RAttrBase.hxx
/// \ingroup Gpad ROOT7
/// \author Sergey Linev <s.linev@gsi.de>
/// \date 2019-09-17
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

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

#ifndef ROOT7_RAttrBase
#define ROOT7_RAttrBase

#include <ROOT/RAttrMap.hxx>
#include <ROOT/RStyle.hxx>
#include <ROOT/RDrawable.hxx>

namespace ROOT {
namespace Experimental {

/** Base class for all attributes, used with RDrawable */
class RAttrBase {

   friend class RAttrMap;

   RDrawable *fDrawable{nullptr};      ///<! drawable used to store attributes
   std::unique_ptr<RAttrMap> fOwnAttr; ///<! own instance when deep copy is created
   std::string fPrefix;                ///<! name prefix for all attributes values
   const RAttrBase *fParent{nullptr};  ///<! parent attributes, prefix applied to it

protected:

   virtual const RAttrMap &GetDefaults() const;

   bool CopyValue(const std::string &name, const RAttrMap::Value_t &value, bool check_type = true);

   bool IsValueEqual(const std::string &name, const RAttrMap::Value_t *value, bool use_style = false) const;

   ///////////////////////////////////////////////////////////////////////////////

   void AssignDrawable(RDrawable *drawable, const std::string &prefix);

   void AssignParent(const RAttrBase *parent, const std::string &prefix);

   struct Rec_t {
      RAttrMap *attr{nullptr};
      std::string fullname;
      RDrawable *drawable{nullptr};
      operator bool() const { return !!attr; }
   };

   /// Find attributes container and full-qualified name for value
   const Rec_t AccessAttr(const std::string &name) const
   {
      const RAttrBase *prnt = this;
      std::string fullname = name;
      while (prnt) {
         fullname.insert(0, prnt->fPrefix); // fullname = prnt->fPrefix + fullname
         if (prnt->fDrawable)
            return {&(prnt->fDrawable->fAttr), fullname, prnt->fDrawable};
         if (prnt->fOwnAttr)
            return {prnt->fOwnAttr.get(), fullname, nullptr};
         prnt = prnt->fParent;
      }
      return {nullptr, fullname, nullptr};
   }

   struct Val_t {
      const RAttrMap::Value_t *value{nullptr};
      std::shared_ptr<RStyle> style;
      operator bool() const { return !!value; }
   };

   const Val_t AccessValue(const std::string &name, bool use_style = true) const
   {
      if (auto access = AccessAttr(name)) {
         if (auto rec = access.attr->Find(access.fullname))
            return {rec, nullptr};
         if (access.drawable && use_style)
            if (auto observe = access.drawable->fStyle.lock()) {
               if (auto rec = observe->Eval(access.fullname, access.drawable))
                  return {rec, observe};
            }
      }

      return {nullptr, nullptr};
   }

   Rec_t EnsureAttr(const std::string &name)
   {
      const RAttrBase *prnt = this;
      std::string fullname = name;
      while (prnt) {
         fullname.insert(0, prnt->fPrefix); // fullname = prnt->fPrefix + fullname
         if (prnt->fDrawable)
            return {&(prnt->fDrawable->fAttr), fullname, prnt->fDrawable};
         if (!prnt->fParent && !prnt->fOwnAttr)
            const_cast<RAttrBase *>(prnt)->fOwnAttr = std::make_unique<RAttrMap>();
         if (prnt->fOwnAttr)
            return {prnt->fOwnAttr.get(), fullname, nullptr};
         prnt = prnt->fParent;
      }
      return {nullptr, fullname, nullptr};
   }

   /// Evaluate attribute value

   template <typename RET_TYPE,typename MATCH_TYPE = void>
   auto Eval(const std::string &name, bool use_dflts = true) const
   {
      if (auto v = AccessValue(name, true))
         return RAttrMap::Value_t::get_value<RET_TYPE,MATCH_TYPE>(v.value);

      const RAttrMap::Value_t *rec = nullptr;

      if (use_dflts)
         rec = GetDefaults().Find(name);

      return RAttrMap::Value_t::get_value<RET_TYPE,MATCH_TYPE>(rec);
   }

   double *GetDoublePtr(const std::string &name) const;

   void CopyTo(RAttrBase &tgt, bool use_style = true) const;

   bool IsSame(const RAttrBase &src, bool use_style = true) const;

   RAttrBase(RDrawable *drawable, const std::string &prefix) { AssignDrawable(drawable, prefix); }

   RAttrBase(const RAttrBase *parent, const std::string &prefix) { AssignParent(parent, prefix); }

   RAttrBase(const RAttrBase &src) { src.CopyTo(*this); }

   RAttrBase &operator=(const RAttrBase &src)
   {
      Clear();
      src.CopyTo(*this);
      return *this;
   }

   void SetValue(const std::string &name, double value);
   void SetValue(const std::string &name, int value);
   void SetValue(const std::string &name, const std::string &value);

   const std::string &GetPrefix() const { return fPrefix; }

   void ClearValue(const std::string &name);

   void Clear();

   template <typename T = void>
   bool HasValue(const std::string &name, bool check_defaults = false) const
   {
      return Eval<const RAttrMap::Value_t *, T>(name, check_defaults) != nullptr;
   }

   template <typename T>
   T GetValue(const std::string &name) const
   {
      return Eval<T>(name);
   }

public:
   RAttrBase() = default;

   virtual ~RAttrBase() = default;

   friend bool operator==(const RAttrBase& lhs, const RAttrBase& rhs){ return lhs.IsSame(rhs) && rhs.IsSame(lhs); }
   friend bool operator!=(const RAttrBase& lhs, const RAttrBase& rhs){ return !lhs.IsSame(rhs) || !rhs.IsSame(lhs); }
};

} // namespace Experimental
} // namespace ROOT

#define R__ATTR_CLASS(ClassName,dflt_prefix,dflt_values) \
protected: \
const RAttrMap &GetDefaults() const override \
{ \
   static auto dflts = RAttrMap().dflt_values; \
   return dflts; \
} \
public: \
   ClassName() = default; \
   ClassName(RDrawable *drawable, const std::string &prefix = dflt_prefix) { AssignDrawable(drawable, prefix); } \
   ClassName(const RAttrBase *parent, const std::string &prefix = dflt_prefix) { AssignParent(parent, prefix); } \
   ClassName(const ClassName &src) : ClassName() { src.CopyTo(*this); } \
   ClassName &operator=(const ClassName &src) \
   { \
      Clear(); \
      src.CopyTo(*this); \
      return *this; \
   }

#endif
<|endoftext|>


<commit_before>// Copyright 2012 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <fstream>
#include <vector>
#include <set>
#include <string>
#include <cmath>
#include <exception>
#include <H5Cpp.h>
#include <dada_hdu.h>
#include <ascii_header.h>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef READ_DATA_HPP
#define READ_DATA_HPP

namespace AstroData {

// Exception: the PSRDada ring buffer does not work
class RingBufferError : public std::exception {
public:
  RingBufferError();
  ~RingBufferError() throw ();

  const char * what() const throw ();
};

// Zapped channels (excluded from computation)
void readZappedChannels(Observation & observation, const std::string & inputFileName, std::vector< uint8_t > & zappedChannels);
// Integration steps
void readIntegrationSteps(const Observation & observation, const std::string  & inputFileName, std::set< unsigned int > & integrationSteps);
// SIGPROC data
template< typename T > void readSIGPROC(const Observation & observation, const unsigned int padding, const uint8_t inputBits, const unsigned int bytesToSkip, const std::string & inputFilename, std::vector< std::vector< T > * > & data, const unsigned int firstSecond = 0);
// LOFAR data
template< typename T > void readLOFAR(std::string headerFilename, std::string rawFilename, Observation & observation, const unsigned int padding, std::vector< std::vector< T > * > & data, unsigned int nrBatches = 0, unsigned int firstSecond = 0);
// PSRDADA buffer
template< typename T > void readPSRDadaHeader(Observation & observation, dada_hdu_t & ringBuffer) throw(RingBufferError);
template< typename T > inline void readPSRDada(Observation & observation, const unsigned int padding, dada_hdu_t & ringBuffer, std::vector< T > * data) throw(RingBufferError);

// Implementations

template< typename T > void readSIGPROC(const Observation & observation, const unsigned int padding, const uint8_t inputBits, const unsigned int bytesToSkip, const std::string & inputFilename, std::vector< std::vector< T > * > & data, const unsigned int firstSecond = 0) {
	std::ifstream inputFile;
	const unsigned int BUFFER_DIM = sizeof(T);
	char * buffer = new char [BUFFER_DIM];

	inputFile.open(inputFilename.c_str(), std::ios::binary);
	inputFile.sync_with_stdio(false);
	inputFile.seekg(bytesToSkip, std::ios::beg);
	for ( unsigned int batch = 0; batch < observation.getNrBatches(); batch++ ) {
    if ( inputBits >= 8 ) {
      data.at(batch) = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T)));
      for ( unsigned int sample = 0; sample < observation.getNrSamplesPerBatch(); sample++ ) {
        for ( unsigned int channel = observation.getNrChannels(); channel > 0; channel-- ) {
          inputFile.read(buffer, BUFFER_DIM);
          data.at(batch)->at((static_cast< uint64_t >(channel - 1) * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T))) + sample) = *(reinterpret_cast< T * >(buffer));
        }
      }
    } else {
      uint64_t bytesToRead = static_cast< uint64_t >(observation.getNrSamplesPerBatch() * (observation.getNrChannels() / (8.0 / inputBits)));

      data.at(batch) = new std::vector< T >(observation.getNrChannels() * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T)));
      for ( uint64_t byte = 0; byte < bytesToRead; byte++ ) {
        unsigned int channel = (observation.getNrChannels() - 1) - ((byte * (8 / inputBits)) % observation.getNrChannels());
        unsigned int sample = (byte * (8 / inputBits)) / observation.getNrChannels();
        unsigned int sampleByte = sample / (8 / inputBits);
        uint8_t sampleFirstBit = (sample % (8 / inputBits)) * inputBits;

        inputFile.read(buffer, BUFFER_DIM);
        for ( unsigned int item = 0; item < 8 / inputBits; item++ ) {
          uint8_t channelFirstBit = item * inputBits;
          uint8_t sampleBuffer = 0;

          if ( item > channel ) {
            // All channels read, the remaining elements are from the next sample
            unsigned int channelOffset = 0;
            channel = (observation.getNrChannels() - 1);
            sample += 1;
            sampleByte = sample / (8 / inputBits);
            sampleFirstBit = (sample % (8 / inputBits)) * inputBits;

            while ( item < (8 / inputBits) ) {
              channelFirstBit = item * inputBits;
              sampleBuffer = data.at(batch)->at((static_cast< uint64_t >(channel - channelOffset) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T))) + sampleByte);
              for ( uint8_t bit = 0; bit < inputBits; bit++ ) {
                isa::utils::setBit(sampleBuffer, isa::utils::getBit(*buffer, channelFirstBit + bit), sampleFirstBit + bit);
              }
              data.at(batch)->at((static_cast< uint64_t >(channel - channelOffset) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T))) + sampleByte) = sampleBuffer;
              item++;
              channelOffset++;
            }

            break;
          }
          sampleBuffer = data.at(batch)->at((static_cast< uint64_t >(channel - item) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T))) + sampleByte);
          for ( uint8_t bit = 0; bit < inputBits; bit++ ) {
            isa::utils::setBit(sampleBuffer, isa::utils::getBit(*buffer, channelFirstBit + bit), sampleFirstBit + bit);
          }
          data.at(batch)->at((static_cast< uint64_t >(channel - item) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T))) + sampleByte) = sampleBuffer;
        }
      }
    }
	}
	inputFile.close();

	delete [] buffer;
}

template< typename T > void readLOFAR(std::string headerFilename, std::string rawFilename, Observation & observation, const unsigned int padding, std::vector< std::vector< T > * > & data, unsigned int nrBatches, unsigned int firstSecond) {
  unsigned int nrSubbands, nrChannels;
  float minFreq, channelBandwidth;
	// Read the HDF5 file with the metadata
	H5::H5File headerFile = H5::H5File(headerFilename, H5F_ACC_RDONLY);
	H5::FloatType typeDouble = H5::FloatType(H5::PredType::NATIVE_DOUBLE);
	double valueDouble = 0.0;
	H5::IntType typeUInt = H5::IntType(H5::PredType::NATIVE_UINT);
	unsigned int valueUInt = 0;

	H5::Group currentNode = headerFile.openGroup("/");
	currentNode.openAttribute("OBSERVATION_FREQUENCY_MIN").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
  minFreq = valueDouble;
	currentNode = currentNode.openGroup(currentNode.getObjnameByIdx(0));
	currentNode.openAttribute("TOTAL_INTEGRATION_TIME").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
	double totalIntegrationTime = valueDouble;
	currentNode.openAttribute("NOF_BEAMS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	observation.setNrBeams(valueUInt);
	currentNode = currentNode.openGroup(currentNode.getObjnameByIdx(0));
	currentNode.openAttribute("NOF_SAMPLES").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	unsigned int totalSamples = valueUInt;
	currentNode.openAttribute("NOF_STATIONS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	observation.setNrStations(valueUInt);
	currentNode.openAttribute("CHANNELS_PER_SUBBAND").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	nrChannels = valueUInt;
	currentNode.openAttribute("CHANNEL_WIDTH").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
  channelBandwidth = valueDouble / 1000000;
	H5::DataSet currentData = currentNode.openDataSet("STOKES_0");
	currentData.openAttribute("NOF_SUBBANDS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	nrSubbands = valueUInt;
	headerFile.close();

	observation.setNrSamplesPerBatch(static_cast< unsigned int >(totalSamples / totalIntegrationTime));
	if ( nrBatches == 0 ) {
		observation.setNrBatches(static_cast< unsigned int >(totalIntegrationTime));
	} else {
		if ( static_cast< unsigned int >(totalIntegrationTime) >= (firstSecond + nrBatches) ) {
			observation.setNrBatches(nrBatches);
		} else {
			observation.setNrBatches(static_cast< unsigned int >(totalIntegrationTime) - firstSecond);
		}
	}
  observation.setFrequencyRange(1, nrSubbands * nrChannels, minFreq, channelBandwidth);

	// Read the raw file with the actual data
	std::ifstream rawFile;
	rawFile.open(rawFilename.c_str(), std::ios::binary);
	rawFile.sync_with_stdio(false);
	if ( firstSecond > 0 ) {
		rawFile.seekg(firstSecond * observation.getNrSamplesPerBatch() * nrSubbands * nrChannels, std::ios::beg);
	}
	data.resize(observation.getNrBatches());

	char * word = new char [4];
	for ( unsigned int batch = 0; batch < observation.getNrBatches(); batch++ ) {
		data.at(batch) = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T)));
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerBatch(); sample++ ) {
			for ( unsigned int subband = 0; subband < nrSubbands; subband++ ) {
				for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
          unsigned int globalChannel = (subband * nrChannels) + channel;

					rawFile.read(word, 4);
          isa::utils::bigEndianToLittleEndian(word);
          data.at(batch)->at((globalChannel * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T))) + sample) = *(reinterpret_cast< T * >(word));
				}
			}
		}
	}
	rawFile.close();
	delete [] word;
}

template< typename T > void readPSRDadaHeader(Observation & observation, dada_hdu_t & ringBuffer) throw(RingBufferError) {
  // Staging variables for the header elements
  unsigned int uintValue = 0;
  float floatValue[2] = {0.0f, 0.0f};
  // Header string
  uint64_t headerBytes = 0;
  char * header = 0;

  header = ipcbuf_get_next_read(ringBuffer.header_block, &headerBytes);

  if ( (header == 0) || (headerBytes == 0 ) ) {
    throw RingBufferError();
  }

  ascii_header_get(header, "SAMPLES_PER_SECOND", "%d", &uintValue);
  observation.setNrSamplesPerBatch(uintValue);
  ascii_header_get(header, "CHANNELS", "%d", &uintValue);
  ascii_header_get(header, "MIN_FREQUENCY", "%f", &floatValue[0]);
  ascii_header_get(header, "CHANNEL_BANDWIDTH", "%f", &floatValue[1]);
  observation.setFrequencyRange(1, uintValue, floatValue[0], floatValue[1]);
  ipcbuf_mark_cleared(ringBuffer.header_block);

  delete header;
}

template< typename T > inline void readPSRDada(Observation & observation, const unsigned int padding, dada_hdu_t & ringBuffer, std::vector< T > * data) throw(RingBufferError) {
  if ( (ipcio_read(ringBuffer.data_block, reinterpret_cast< char * >(data->data()), observation.getNrChannels() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T)) * sizeof(T))) < 0 ) {
    throw RingBufferError();
  }
}

} // AstroData

#endif // READ_DATA_HPP

<commit_msg>There was still a missing reference to the word "second". Removed.<commit_after>// Copyright 2012 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <fstream>
#include <vector>
#include <set>
#include <string>
#include <cmath>
#include <exception>
#include <H5Cpp.h>
#include <dada_hdu.h>
#include <ascii_header.h>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef READ_DATA_HPP
#define READ_DATA_HPP

namespace AstroData {

// Exception: the PSRDada ring buffer does not work
class RingBufferError : public std::exception {
public:
  RingBufferError();
  ~RingBufferError() throw ();

  const char * what() const throw ();
};

// Zapped channels (excluded from computation)
void readZappedChannels(Observation & observation, const std::string & inputFileName, std::vector< uint8_t > & zappedChannels);
// Integration steps
void readIntegrationSteps(const Observation & observation, const std::string  & inputFileName, std::set< unsigned int > & integrationSteps);
// SIGPROC data
template< typename T > void readSIGPROC(const Observation & observation, const unsigned int padding, const uint8_t inputBits, const unsigned int bytesToSkip, const std::string & inputFilename, std::vector< std::vector< T > * > & data, const unsigned int firstBatch = 0);
// LOFAR data
template< typename T > void readLOFAR(std::string headerFilename, std::string rawFilename, Observation & observation, const unsigned int padding, std::vector< std::vector< T > * > & data, unsigned int nrBatches = 0, unsigned int firstBatch = 0);
// PSRDADA buffer
template< typename T > void readPSRDadaHeader(Observation & observation, dada_hdu_t & ringBuffer) throw(RingBufferError);
template< typename T > inline void readPSRDada(Observation & observation, const unsigned int padding, dada_hdu_t & ringBuffer, std::vector< T > * data) throw(RingBufferError);

// Implementations

template< typename T > void readSIGPROC(const Observation & observation, const unsigned int padding, const uint8_t inputBits, const unsigned int bytesToSkip, const std::string & inputFilename, std::vector< std::vector< T > * > & data, const unsigned int firstBatch = 0) {
	std::ifstream inputFile;
	const unsigned int BUFFER_DIM = sizeof(T);
	char * buffer = new char [BUFFER_DIM];

	inputFile.open(inputFilename.c_str(), std::ios::binary);
	inputFile.sync_with_stdio(false);
	inputFile.seekg(bytesToSkip, std::ios::beg);
	for ( unsigned int batch = 0; batch < observation.getNrBatches(); batch++ ) {
    if ( inputBits >= 8 ) {
      data.at(batch) = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T)));
      for ( unsigned int sample = 0; sample < observation.getNrSamplesPerBatch(); sample++ ) {
        for ( unsigned int channel = observation.getNrChannels(); channel > 0; channel-- ) {
          inputFile.read(buffer, BUFFER_DIM);
          data.at(batch)->at((static_cast< uint64_t >(channel - 1) * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T))) + sample) = *(reinterpret_cast< T * >(buffer));
        }
      }
    } else {
      uint64_t bytesToRead = static_cast< uint64_t >(observation.getNrSamplesPerBatch() * (observation.getNrChannels() / (8.0 / inputBits)));

      data.at(batch) = new std::vector< T >(observation.getNrChannels() * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T)));
      for ( uint64_t byte = 0; byte < bytesToRead; byte++ ) {
        unsigned int channel = (observation.getNrChannels() - 1) - ((byte * (8 / inputBits)) % observation.getNrChannels());
        unsigned int sample = (byte * (8 / inputBits)) / observation.getNrChannels();
        unsigned int sampleByte = sample / (8 / inputBits);
        uint8_t sampleFirstBit = (sample % (8 / inputBits)) * inputBits;

        inputFile.read(buffer, BUFFER_DIM);
        for ( unsigned int item = 0; item < 8 / inputBits; item++ ) {
          uint8_t channelFirstBit = item * inputBits;
          uint8_t sampleBuffer = 0;

          if ( item > channel ) {
            // All channels read, the remaining elements are from the next sample
            unsigned int channelOffset = 0;
            channel = (observation.getNrChannels() - 1);
            sample += 1;
            sampleByte = sample / (8 / inputBits);
            sampleFirstBit = (sample % (8 / inputBits)) * inputBits;

            while ( item < (8 / inputBits) ) {
              channelFirstBit = item * inputBits;
              sampleBuffer = data.at(batch)->at((static_cast< uint64_t >(channel - channelOffset) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T))) + sampleByte);
              for ( uint8_t bit = 0; bit < inputBits; bit++ ) {
                isa::utils::setBit(sampleBuffer, isa::utils::getBit(*buffer, channelFirstBit + bit), sampleFirstBit + bit);
              }
              data.at(batch)->at((static_cast< uint64_t >(channel - channelOffset) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T))) + sampleByte) = sampleBuffer;
              item++;
              channelOffset++;
            }

            break;
          }
          sampleBuffer = data.at(batch)->at((static_cast< uint64_t >(channel - item) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T))) + sampleByte);
          for ( uint8_t bit = 0; bit < inputBits; bit++ ) {
            isa::utils::setBit(sampleBuffer, isa::utils::getBit(*buffer, channelFirstBit + bit), sampleFirstBit + bit);
          }
          data.at(batch)->at((static_cast< uint64_t >(channel - item) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(T))) + sampleByte) = sampleBuffer;
        }
      }
    }
	}
	inputFile.close();

	delete [] buffer;
}

template< typename T > void readLOFAR(std::string headerFilename, std::string rawFilename, Observation & observation, const unsigned int padding, std::vector< std::vector< T > * > & data, unsigned int nrBatches, unsigned int firstBatch) {
  unsigned int nrSubbands, nrChannels;
  float minFreq, channelBandwidth;
	// Read the HDF5 file with the metadata
	H5::H5File headerFile = H5::H5File(headerFilename, H5F_ACC_RDONLY);
	H5::FloatType typeDouble = H5::FloatType(H5::PredType::NATIVE_DOUBLE);
	double valueDouble = 0.0;
	H5::IntType typeUInt = H5::IntType(H5::PredType::NATIVE_UINT);
	unsigned int valueUInt = 0;

	H5::Group currentNode = headerFile.openGroup("/");
	currentNode.openAttribute("OBSERVATION_FREQUENCY_MIN").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
  minFreq = valueDouble;
	currentNode = currentNode.openGroup(currentNode.getObjnameByIdx(0));
	currentNode.openAttribute("TOTAL_INTEGRATION_TIME").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
	double totalIntegrationTime = valueDouble;
	currentNode.openAttribute("NOF_BEAMS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	observation.setNrBeams(valueUInt);
	currentNode = currentNode.openGroup(currentNode.getObjnameByIdx(0));
	currentNode.openAttribute("NOF_SAMPLES").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	unsigned int totalSamples = valueUInt;
	currentNode.openAttribute("NOF_STATIONS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	observation.setNrStations(valueUInt);
	currentNode.openAttribute("CHANNELS_PER_SUBBAND").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	nrChannels = valueUInt;
	currentNode.openAttribute("CHANNEL_WIDTH").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
  channelBandwidth = valueDouble / 1000000;
	H5::DataSet currentData = currentNode.openDataSet("STOKES_0");
	currentData.openAttribute("NOF_SUBBANDS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	nrSubbands = valueUInt;
	headerFile.close();

	observation.setNrSamplesPerBatch(static_cast< unsigned int >(totalSamples / totalIntegrationTime));
	if ( nrBatches == 0 ) {
		observation.setNrBatches(static_cast< unsigned int >(totalIntegrationTime));
	} else {
		if ( static_cast< unsigned int >(totalIntegrationTime) >= (firstBatch + nrBatches) ) {
			observation.setNrBatches(nrBatches);
		} else {
			observation.setNrBatches(static_cast< unsigned int >(totalIntegrationTime) - firstBatch);
		}
	}
  observation.setFrequencyRange(1, nrSubbands * nrChannels, minFreq, channelBandwidth);

	// Read the raw file with the actual data
	std::ifstream rawFile;
	rawFile.open(rawFilename.c_str(), std::ios::binary);
	rawFile.sync_with_stdio(false);
	if ( firstBatch > 0 ) {
		rawFile.seekg(firstBatch * observation.getNrSamplesPerBatch() * nrSubbands * nrChannels, std::ios::beg);
	}
	data.resize(observation.getNrBatches());

	char * word = new char [4];
	for ( unsigned int batch = 0; batch < observation.getNrBatches(); batch++ ) {
		data.at(batch) = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T)));
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerBatch(); sample++ ) {
			for ( unsigned int subband = 0; subband < nrSubbands; subband++ ) {
				for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
          unsigned int globalChannel = (subband * nrChannels) + channel;

					rawFile.read(word, 4);
          isa::utils::bigEndianToLittleEndian(word);
          data.at(batch)->at((globalChannel * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T))) + sample) = *(reinterpret_cast< T * >(word));
				}
			}
		}
	}
	rawFile.close();
	delete [] word;
}

template< typename T > void readPSRDadaHeader(Observation & observation, dada_hdu_t & ringBuffer) throw(RingBufferError) {
  // Staging variables for the header elements
  unsigned int uintValue = 0;
  float floatValue[2] = {0.0f, 0.0f};
  // Header string
  uint64_t headerBytes = 0;
  char * header = 0;

  header = ipcbuf_get_next_read(ringBuffer.header_block, &headerBytes);

  if ( (header == 0) || (headerBytes == 0 ) ) {
    throw RingBufferError();
  }

  ascii_header_get(header, "SAMPLES_PER_SECOND", "%d", &uintValue);
  observation.setNrSamplesPerBatch(uintValue);
  ascii_header_get(header, "CHANNELS", "%d", &uintValue);
  ascii_header_get(header, "MIN_FREQUENCY", "%f", &floatValue[0]);
  ascii_header_get(header, "CHANNEL_BANDWIDTH", "%f", &floatValue[1]);
  observation.setFrequencyRange(1, uintValue, floatValue[0], floatValue[1]);
  ipcbuf_mark_cleared(ringBuffer.header_block);

  delete header;
}

template< typename T > inline void readPSRDada(Observation & observation, const unsigned int padding, dada_hdu_t & ringBuffer, std::vector< T > * data) throw(RingBufferError) {
  if ( (ipcio_read(ringBuffer.data_block, reinterpret_cast< char * >(data->data()), observation.getNrChannels() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(T)) * sizeof(T))) < 0 ) {
    throw RingBufferError();
  }
}

} // AstroData

#endif // READ_DATA_HPP

<|endoftext|>


<commit_before>/* pocl/include/vccompat.h - Compatibility header to provide some functions
   iwhich are not found from VC++.

   Copyright (c) 2014 Mikael Lepistö <elhigu@gmail.com>

   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.
*/

#define __restrict__ __restrict
<commit_msg>Added Visual Studion implementations for libltdl functions.<commit_after>/* pocl/include/vccompat.h - Compatibility header to provide some functions
   which are not found from VC++.

   All functions should be static inline so that they can be included in many places
   without having problem of symbol collision.

   Copyright (c) 2014 Mikael Lepistö <elhigu@gmail.com>

   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.
*/

#define __restrict__ __restrict

/**
 * ltdl compatibility functions
 */
#include <Windows.h>
typedef HMODULE lt_dlhandle;

static inline lt_dlhandle lt_dlopen(const char* filename) {
  return (lt_dlhandle)LoadLibrary(filename);
}

static inline int lt_dlerror(void) {
   return GetLastError();
}

static inline void *lt_dlsym(lt_dlhandle handle, const char *symbol) {
  return GetProcAddress(handle, symbol);
}

/**
 * Memory allocation functions
 */
static int posix_memalign(void **p, size_t align, size_t size) {
   void *buf = _aligned_malloc(size, align);
   if (buf == NULL) return errno;
   *p = buf;
   return 0;
}

<|endoftext|>


<commit_before>#ifndef INTERSECTION_SSE_HPP_
#define INTERSECTION_SSE_HPP_

#include <cstring>

#include <immintrin.h>

#include "naive.hpp"

// taken from: https://highlyscalable.wordpress.com/2012/06/05/fast-intersection-sorted-lists-sse/
size_t intersect_vector_sse(const uint32_t *list1, size_t size1, const uint32_t *list2, size_t size2, uint32_t *result){
	size_t count = 0;
	size_t i_a = 0, i_b = 0;

	// trim lengths to be a multiple of 4
	size_t st_a = (size1 / 4) * 4;
	size_t st_b = (size2 / 4) * 4;

	while(i_a < st_a && i_b < st_b) {
		// load segments of four 32-bit elements
		__m128i v_a = _mm_load_si128((__m128i*)&list1[i_a]);
		__m128i v_b = _mm_load_si128((__m128i*)&list2[i_b]);

		// move pointers
// 		int32_t a_max = _mm_extract_epi32(v_a, 3);
		int32_t a_max = list1[i_a+3];
// 		int32_t b_max = _mm_extract_epi32(v_b, 3);
		int32_t b_max = list2[i_b+3];
		i_a += (a_max <= b_max) * 4;
		i_b += (a_max >= b_max) * 4;

		// not usable here but mentioned in paper: _mm_slli_si128
		// compute mask of common elements
		constexpr int32_t cyclic_shift = _MM_SHUFFLE(0,3,2,1); //rotating right
		constexpr int32_t cyclic_shift2= _MM_SHUFFLE(2,1,0,3); //rotating left
		constexpr int32_t cyclic_shift3= _MM_SHUFFLE(1,0,3,2); //between
		__m128i cmp_mask1 = _mm_cmpeq_epi32(v_a, v_b);         // pairwise comparison
		__m128i rot1 = _mm_shuffle_epi32(v_b, cyclic_shift);   // shuffling
		__m128i cmp_mask2 = _mm_cmpeq_epi32(v_a, rot1);        // again...
		__m128i rot2 = _mm_shuffle_epi32(v_b, cyclic_shift3);
		__m128i cmp_mask3 = _mm_cmpeq_epi32(v_a, rot2);        // and again...
		__m128i rot3 = _mm_shuffle_epi32(v_b, cyclic_shift2);
		__m128i cmp_mask4 = _mm_cmpeq_epi32(v_a, rot3);        // and again.
		__m128i cmp_mask = _mm_or_si128(
				_mm_or_si128(cmp_mask1, cmp_mask2),
				_mm_or_si128(cmp_mask3, cmp_mask4)
		); // OR-ing of comparison masks
		// convert the 128-bit mask to the 4-bit mask
		int32_t mask = _mm_movemask_ps((__m128)cmp_mask);

		// copy out common elements
		__m128i p = _mm_shuffle_epi8(v_a, shuffle_mask[mask]);
		_mm_storeu_si128((__m128i*)&result[count], p);
		count += _mm_popcnt_u32(mask); // a number of elements is a weight of the mask
	}

	// intersect the tail using scalar intersection
	count += intersect_scalar(list1+i_a, size1-i_a, list2+i_b, size2-i_b, result+count);

	return count;
}

size_t intersect_vector_sse_count(const uint32_t *list1, size_t size1, const uint32_t *list2, size_t size2){
	size_t count = 0;
	size_t i_a = 0, i_b = 0;

	// trim lengths to be a multiple of 4
	size_t st_a = (size1 / 4) * 4;
	size_t st_b = (size2 / 4) * 4;

	while(i_a < st_a && i_b < st_b) {
		// load segments of four 32-bit elements
		__m128i v_a = _mm_load_si128((__m128i*)&list1[i_a]);
		__m128i v_b = _mm_load_si128((__m128i*)&list2[i_b]);

		// move pointers
// 		int32_t a_max = _mm_extract_epi32(v_a, 3);
		int32_t a_max = list1[i_a+3];
// 		int32_t b_max = _mm_extract_epi32(v_b, 3);
		int32_t b_max = list2[i_b+3];
		i_a += (a_max <= b_max) * 4;
		i_b += (a_max >= b_max) * 4;

		// not usable here but mentioned in paper: _mm_slli_si128
		// compute mask of common elements
		constexpr int32_t cyclic_shift = _MM_SHUFFLE(0,3,2,1); //rotating right
		constexpr int32_t cyclic_shift2= _MM_SHUFFLE(2,1,0,3); //rotating left
		constexpr int32_t cyclic_shift3= _MM_SHUFFLE(1,0,3,2); //between
		__m128i cmp_mask1 = _mm_cmpeq_epi32(v_a, v_b);         // pairwise comparison
		__m128i rot1 = _mm_shuffle_epi32(v_b, cyclic_shift);   // shuffling
		__m128i cmp_mask2 = _mm_cmpeq_epi32(v_a, rot1);        // again...
		__m128i rot2 = _mm_shuffle_epi32(v_b, cyclic_shift3);
		__m128i cmp_mask3 = _mm_cmpeq_epi32(v_a, rot2);        // and again...
		__m128i rot3 = _mm_shuffle_epi32(v_b, cyclic_shift2);
		__m128i cmp_mask4 = _mm_cmpeq_epi32(v_a, rot3);        // and again.
		__m128i cmp_mask = _mm_or_si128(
				_mm_or_si128(cmp_mask1, cmp_mask2),
				_mm_or_si128(cmp_mask3, cmp_mask4)
		); // OR-ing of comparison masks
		// convert the 128-bit mask to the 4-bit mask
		int32_t mask = _mm_movemask_ps((__m128)cmp_mask);

		count += _mm_popcnt_u32(mask); // a number of elements is a weight of the mask
	}

	// intersect the tail using scalar intersection
	count += intersect_scalar_count(list1+i_a, size1-i_a, list2+i_b, size2-i_b);

	return count;
}

#ifndef DISABLE_ASM
size_t intersect_vector_sse_asm(const uint32_t *list1, size_t size1, const uint32_t *list2, size_t size2, uint32_t *result){
	size_t count = 0;
	size_t i_a = 0, i_b = 0;

	// trim lengths to be a multiple of 4
	size_t st_a = (size1 / 4) * 4;
	size_t st_b = (size2 / 4) * 4;

	while(i_a < st_a && i_b < st_b) {
		asm(".intel_syntax noprefix;"

			"vmovdqa xmm0, [%q3 + %q[i_a]*4];" //__m128i v_a = _mm_load_si128((__m128i*)&list1[i_a]);
			"vmovdqa xmm1, [%q4 + %q[i_b]*4];" //__m128i v_b = _mm_load_si128((__m128i*)&list2[i_b]);

			"mov r8d, [%q[list1] + %q[i_a]*4 + 12];" //int32_t a_max = list1[i_a+3];
			"mov r9d, [%q[list2] + %q[i_b]*4 + 12];" //int32_t b_max = list2[i_b+3];
			//i_a += (a_max <= b_max) * 4;
			//i_b += (a_max >= b_max) * 4;
			"xor rax, rax;"
			"xor rbx, rbx;"
			"cmp r8d, r9d;"
			"setbe al;"
			"setae bl;"
			"lea %q[i_a], [%q[i_a] + rax*4];"
			"lea %q[i_b], [%q[i_b] + rbx*4];"

// 			"vpcmpeqd xmm2, xmm0, xmm1;"
// 			"vpshufd xmm1, xmm1, 0x39;"
// 			"vpcmpeqd xmm3, xmm0, xmm1;"
// 			"vpshufd xmm1, xmm1, 0x39;"
// 			"vpcmpeqd xmm4, xmm0, xmm1;"
// 			"vpshufd xmm1, xmm1, 0x39;"
// 			"vpcmpeqd xmm5, xmm0, xmm1;"
			"vpshufd xmm6, xmm1, 0x39;"
			"vpshufd xmm7, xmm1, 0x4e;"
			"vpshufd xmm8, xmm1, 0x93;"
			"vpcmpeqd xmm2, xmm0, xmm1;"
			"vpcmpeqd xmm3, xmm0, xmm6;"
			"vpcmpeqd xmm4, xmm0, xmm7;"
			"vpcmpeqd xmm5, xmm0, xmm8;"

			"vpor xmm2, xmm2, xmm3;"
			"vpor xmm4, xmm4, xmm5;"
			"vpor xmm2, xmm2, xmm4;"

			"vmovmskps r8d, xmm2;"
			// save in result
			// 16 multiplier not possible in index expression
			// -> do it outside
			"movslq r9, r8d;"
			"shl r9, 4;"
			"vpshufb xmm0, xmm0, [%q[shuffle_mask] + r9];"
			"vmovups [%q[result] + %q[count]*4], xmm0;"

			"popcnt r8d, r8d;"
// 			"movl r8, r8d;" // zero extend
			"add %q[count], r8;"

			".att_syntax;"
			: [i_a]"=r"(i_a), [i_b]"=r"(i_b), [count]"=r"(count)
			: [list1]"r"(list1), [list2]"r"(list2), [result]"r"(result), [shuffle_mask]"r"(shuffle_mask),
				"0"(i_a), "1"(i_b), "2"(count)
			: "%rax", "%rbx", "%r8", "%r9",
				"%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5",
				"%xmm6", "%xmm7", "xmm8",
				"memory", "cc"
		);
	}
	// intersect the tail using scalar intersection
	count += intersect_scalar(list1+i_a, size1-i_a, list2+i_b, size2-i_b, result+count);

	return count;
}
#endif

#endif
<commit_msg>resuse registers as much as possible in assembly SSE intersection<commit_after>#ifndef INTERSECTION_SSE_HPP_
#define INTERSECTION_SSE_HPP_

#include <cstring>

#include <immintrin.h>

#include "naive.hpp"

// taken from: https://highlyscalable.wordpress.com/2012/06/05/fast-intersection-sorted-lists-sse/
size_t intersect_vector_sse(const uint32_t *list1, size_t size1, const uint32_t *list2, size_t size2, uint32_t *result){
	size_t count = 0;
	size_t i_a = 0, i_b = 0;

	// trim lengths to be a multiple of 4
	size_t st_a = (size1 / 4) * 4;
	size_t st_b = (size2 / 4) * 4;

	while(i_a < st_a && i_b < st_b) {
		// load segments of four 32-bit elements
		__m128i v_a = _mm_load_si128((__m128i*)&list1[i_a]);
		__m128i v_b = _mm_load_si128((__m128i*)&list2[i_b]);

		// move pointers
// 		int32_t a_max = _mm_extract_epi32(v_a, 3);
		int32_t a_max = list1[i_a+3];
// 		int32_t b_max = _mm_extract_epi32(v_b, 3);
		int32_t b_max = list2[i_b+3];
		i_a += (a_max <= b_max) * 4;
		i_b += (a_max >= b_max) * 4;

		// not usable here but mentioned in paper: _mm_slli_si128
		// compute mask of common elements
		constexpr int32_t cyclic_shift = _MM_SHUFFLE(0,3,2,1); //rotating right
		constexpr int32_t cyclic_shift2= _MM_SHUFFLE(2,1,0,3); //rotating left
		constexpr int32_t cyclic_shift3= _MM_SHUFFLE(1,0,3,2); //between
		__m128i cmp_mask1 = _mm_cmpeq_epi32(v_a, v_b);         // pairwise comparison
		__m128i rot1 = _mm_shuffle_epi32(v_b, cyclic_shift);   // shuffling
		__m128i cmp_mask2 = _mm_cmpeq_epi32(v_a, rot1);        // again...
		__m128i rot2 = _mm_shuffle_epi32(v_b, cyclic_shift3);
		__m128i cmp_mask3 = _mm_cmpeq_epi32(v_a, rot2);        // and again...
		__m128i rot3 = _mm_shuffle_epi32(v_b, cyclic_shift2);
		__m128i cmp_mask4 = _mm_cmpeq_epi32(v_a, rot3);        // and again.
		__m128i cmp_mask = _mm_or_si128(
				_mm_or_si128(cmp_mask1, cmp_mask2),
				_mm_or_si128(cmp_mask3, cmp_mask4)
		); // OR-ing of comparison masks
		// convert the 128-bit mask to the 4-bit mask
		int32_t mask = _mm_movemask_ps((__m128)cmp_mask);

		// copy out common elements
		__m128i p = _mm_shuffle_epi8(v_a, shuffle_mask[mask]);
		_mm_storeu_si128((__m128i*)&result[count], p);
		count += _mm_popcnt_u32(mask); // a number of elements is a weight of the mask
	}

	// intersect the tail using scalar intersection
	count += intersect_scalar(list1+i_a, size1-i_a, list2+i_b, size2-i_b, result+count);

	return count;
}

size_t intersect_vector_sse_count(const uint32_t *list1, size_t size1, const uint32_t *list2, size_t size2){
	size_t count = 0;
	size_t i_a = 0, i_b = 0;

	// trim lengths to be a multiple of 4
	size_t st_a = (size1 / 4) * 4;
	size_t st_b = (size2 / 4) * 4;

	while(i_a < st_a && i_b < st_b) {
		// load segments of four 32-bit elements
		__m128i v_a = _mm_load_si128((__m128i*)&list1[i_a]);
		__m128i v_b = _mm_load_si128((__m128i*)&list2[i_b]);

		// move pointers
// 		int32_t a_max = _mm_extract_epi32(v_a, 3);
		int32_t a_max = list1[i_a+3];
// 		int32_t b_max = _mm_extract_epi32(v_b, 3);
		int32_t b_max = list2[i_b+3];
		i_a += (a_max <= b_max) * 4;
		i_b += (a_max >= b_max) * 4;

		// not usable here but mentioned in paper: _mm_slli_si128
		// compute mask of common elements
		constexpr int32_t cyclic_shift = _MM_SHUFFLE(0,3,2,1); //rotating right
		constexpr int32_t cyclic_shift2= _MM_SHUFFLE(2,1,0,3); //rotating left
		constexpr int32_t cyclic_shift3= _MM_SHUFFLE(1,0,3,2); //between
		__m128i cmp_mask1 = _mm_cmpeq_epi32(v_a, v_b);         // pairwise comparison
		__m128i rot1 = _mm_shuffle_epi32(v_b, cyclic_shift);   // shuffling
		__m128i cmp_mask2 = _mm_cmpeq_epi32(v_a, rot1);        // again...
		__m128i rot2 = _mm_shuffle_epi32(v_b, cyclic_shift3);
		__m128i cmp_mask3 = _mm_cmpeq_epi32(v_a, rot2);        // and again...
		__m128i rot3 = _mm_shuffle_epi32(v_b, cyclic_shift2);
		__m128i cmp_mask4 = _mm_cmpeq_epi32(v_a, rot3);        // and again.
		__m128i cmp_mask = _mm_or_si128(
				_mm_or_si128(cmp_mask1, cmp_mask2),
				_mm_or_si128(cmp_mask3, cmp_mask4)
		); // OR-ing of comparison masks
		// convert the 128-bit mask to the 4-bit mask
		int32_t mask = _mm_movemask_ps((__m128)cmp_mask);

		count += _mm_popcnt_u32(mask); // a number of elements is a weight of the mask
	}

	// intersect the tail using scalar intersection
	count += intersect_scalar_count(list1+i_a, size1-i_a, list2+i_b, size2-i_b);

	return count;
}

#ifndef DISABLE_ASM
size_t intersect_vector_sse_asm(const uint32_t *list1, size_t size1, const uint32_t *list2, size_t size2, uint32_t *result){
	size_t count = 0;
	size_t i_a = 0, i_b = 0;

	// trim lengths to be a multiple of 4
	size_t st_a = (size1 / 4) * 4;
	size_t st_b = (size2 / 4) * 4;

	while(i_a < st_a && i_b < st_b) {
		asm(".intel_syntax noprefix;"
			//FIXME: uses 128-bit instructions of AVX not SSE
			"vmovdqa xmm0, [%q3 + %q[i_a]*4];" //__m128i v_a = _mm_load_si128((__m128i*)&list1[i_a]);
			"vmovdqa xmm1, [%q4 + %q[i_b]*4];" //__m128i v_b = _mm_load_si128((__m128i*)&list2[i_b]);

			"mov r8d, [%q[list1] + %q[i_a]*4 + 12];" //int32_t a_max = list1[i_a+3];
			"mov r9d, [%q[list2] + %q[i_b]*4 + 12];" //int32_t b_max = list2[i_b+3];
			//i_a += (a_max <= b_max) * 4;
			//i_b += (a_max >= b_max) * 4;
			"xor rax, rax;"
			"xor rbx, rbx;"
			"cmp r8d, r9d;"
			"setbe al;"
			"setae bl;"
			"lea %q[i_a], [%q[i_a] + rax*4];"
			"lea %q[i_b], [%q[i_b] + rbx*4];"

			"vpshufd xmm2, xmm1, 0x39;"
			"vpshufd xmm3, xmm1, 0x4e;"
			"vpshufd xmm4, xmm1, 0x93;"
			"vpcmpeqd xmm1, xmm0, xmm1;"
			"vpcmpeqd xmm2, xmm0, xmm2;"
			"vpcmpeqd xmm3, xmm0, xmm3;"
			"vpcmpeqd xmm4, xmm0, xmm4;"

			"vpor xmm2, xmm1, xmm2;"
			"vpor xmm4, xmm3, xmm4;"
			"vpor xmm2, xmm2, xmm4;"

			"vmovmskps r8d, xmm2;"
			// save in result
			// 16 multiplier not possible in index expression
			// -> do it outside
			"movslq r9, r8d;"
			"shl r9, 4;"
			"vpshufb xmm0, xmm0, [%q[shuffle_mask] + r9];"
			"vmovups [%q[result] + %q[count]*4], xmm0;"

			"popcnt r8d, r8d;"
			"add %q[count], r8;"

			".att_syntax;"
			: [i_a]"=r"(i_a), [i_b]"=r"(i_b), [count]"=r"(count)
			: [list1]"r"(list1), [list2]"r"(list2), [result]"r"(result), [shuffle_mask]"r"(shuffle_mask),
				"0"(i_a), "1"(i_b), "2"(count)
			: "%rax", "%rbx", "%r8", "%r9",
				"%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4",
				"memory", "cc"
		);
	}
	// intersect the tail using scalar intersection
	count += intersect_scalar(list1+i_a, size1-i_a, list2+i_b, size2-i_b, result+count);

	return count;
}
#endif

#endif
<|endoftext|>