<commit_before>/*
    Copyright 2012 Ulrik Mikaelsson <ulrik.mikaelsson@gmail.com>

    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 "linkedassetstore.hpp"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
#include <boost/make_shared.hpp>
#include <string>
#include <time.h>

using namespace std;

namespace asio = boost::asio;
namespace fs = boost::filesystem;

using namespace bithorded;

const fs::path META_DIR = ".bh_meta/assets";
const fs::path TIGER_DIR = ".bh_meta/tiger";

const int THREADPOOL_CONCURRENCY = 4;

LinkedAssetStore::LinkedAssetStore(boost::asio::io_service& ioSvc, const boost::filesystem3::path& baseDir) :
	_threadPool(THREADPOOL_CONCURRENCY),
	_ioSvc(ioSvc),
	_baseDir(baseDir),
	_assetsFolder(baseDir/META_DIR),
	_tigerFolder(baseDir/TIGER_DIR)
{
	if (!fs::exists(_baseDir))
		throw ios_base::failure("LinkedAssetStore: baseDir does not exist");
	if (!fs::exists(_assetsFolder))
		fs::create_directories(_assetsFolder);
	if (!fs::exists(_tigerFolder))
		fs::create_directories(_tigerFolder);
	srand(time(NULL));
}

struct HashTask : public Task {
	Asset::Ptr asset;
	asio::io_service& io_svc;
	asio::io_service::work _work;
	LinkedAssetStore::ResultHandler handler;

	HashTask(Asset::Ptr asset, asio::io_service& io_svc, LinkedAssetStore::ResultHandler handler )
		: asset(asset), io_svc(io_svc), _work(io_svc), handler(handler)
	{}

	void operator()() {
		asset->notifyValidRange(0, asset->size());

		io_svc.post(boost::bind(handler, asset));
		delete this;
	}
};

bool path_is_in(const fs::path& path, const fs::path& folder) {
	string path_(fs::absolute(path).string());
	string folder_(fs::absolute(folder).string()+'/');
	return boost::starts_with(path_, folder_);
}

string random_string(size_t len) {
	static const char alphanum[] =
		"0123456789"
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
		"abcdefghijklmnopqrstuvwxyz";

	string s(len, ' ');
	for (size_t i = 0; i < len; ++i) {
		s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
	}

	return s;
}

bool LinkedAssetStore::addAsset(const boost::filesystem3::path& file, LinkedAssetStore::ResultHandler handler)
{
	if (!path_is_in(file, _baseDir)) {
		return false;
	} else {
		fs::path assetFolder;
		do {
			assetFolder = _assetsFolder / random_string(20);
		} while (fs::exists(assetFolder));

		fs::create_directory(assetFolder);
		fs::create_symlink(file, assetFolder/"data");

		Asset::Ptr asset = boost::make_shared<Asset>(assetFolder);
		HashTask* task = new HashTask(asset, _ioSvc, boost::bind(&LinkedAssetStore::_addAsset, this, _1, handler));
		_threadPool.post(*task);
		return true;
	}
}

void LinkedAssetStore::_addAsset(Asset::Ptr& asset, LinkedAssetStore::ResultHandler upstream)
{
	BitHordeIds ids;
	if (asset.get() && asset->getIds(ids)) {
		for (auto iter=ids.begin(); iter != ids.end(); iter++) {
			if (iter->type() == bithorde::HashType::TREE_TIGER) {
				fs::path link = _tigerFolder / base32encode(iter->id());
				if (fs::exists(fs::symlink_status(link)))
					fs::remove(link);

				// TODO: make links relative instead, so storage can be moved around a little.
				fs::create_symlink(fs::absolute(asset->folder()), link);
			}
		}
	}
	upstream(asset);
}

Asset::Ptr LinkedAssetStore::findAsset(const BitHordeIds& ids)
{
	for (auto iter=ids.begin(); iter != ids.end(); iter++) {
		if (iter->type() == bithorde::HashType::TREE_TIGER) {
			fs::path link = _tigerFolder / base32encode(iter->id());
			boost::system::error_code e;
			auto asset = fs::read_symlink(link, e);
			if (!e && fs::is_directory(asset)) {
				return boost::make_shared<Asset>(asset);
			}
		}
	}
	return Asset::Ptr();
}

<commit_msg>[bithorded/store/LinkedAssetStore]Validate asset-status (including checking mtime) before returning it.<commit_after>/*
    Copyright 2012 Ulrik Mikaelsson <ulrik.mikaelsson@gmail.com>

    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 "linkedassetstore.hpp"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
#include <boost/make_shared.hpp>
#include <string>
#include <time.h>
#include <utime.h>

using namespace std;

namespace asio = boost::asio;
namespace fs = boost::filesystem;

using namespace bithorded;

const fs::path META_DIR = ".bh_meta/assets";
const fs::path TIGER_DIR = ".bh_meta/tiger";

const int THREADPOOL_CONCURRENCY = 4;

LinkedAssetStore::LinkedAssetStore(boost::asio::io_service& ioSvc, const boost::filesystem3::path& baseDir) :
	_threadPool(THREADPOOL_CONCURRENCY),
	_ioSvc(ioSvc),
	_baseDir(baseDir),
	_assetsFolder(baseDir/META_DIR),
	_tigerFolder(baseDir/TIGER_DIR)
{
	if (!fs::exists(_baseDir))
		throw ios_base::failure("LinkedAssetStore: baseDir does not exist");
	if (!fs::exists(_assetsFolder))
		fs::create_directories(_assetsFolder);
	if (!fs::exists(_tigerFolder))
		fs::create_directories(_tigerFolder);
	srand(time(NULL));
}

struct HashTask : public Task {
	Asset::Ptr asset;
	asio::io_service& io_svc;
	asio::io_service::work _work;
	LinkedAssetStore::ResultHandler handler;

	HashTask(Asset::Ptr asset, asio::io_service& io_svc, LinkedAssetStore::ResultHandler handler )
		: asset(asset), io_svc(io_svc), _work(io_svc), handler(handler)
	{}

	void operator()() {
		asset->notifyValidRange(0, asset->size());

		io_svc.post(boost::bind(handler, asset));
		delete this;
	}
};

bool path_is_in(const fs::path& path, const fs::path& folder) {
	string path_(fs::absolute(path).string());
	string folder_(fs::absolute(folder).string()+'/');
	return boost::starts_with(path_, folder_);
}

string random_string(size_t len) {
	static const char alphanum[] =
		"0123456789"
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
		"abcdefghijklmnopqrstuvwxyz";

	string s(len, ' ');
	for (size_t i = 0; i < len; ++i) {
		s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
	}

	return s;
}

bool LinkedAssetStore::addAsset(const boost::filesystem3::path& file, LinkedAssetStore::ResultHandler handler)
{
	if (!path_is_in(file, _baseDir)) {
		return false;
	} else {
		fs::path assetFolder;
		do {
			assetFolder = _assetsFolder / random_string(20);
		} while (fs::exists(assetFolder));

		fs::create_directory(assetFolder);
		fs::create_symlink(file, assetFolder/"data");

		Asset::Ptr asset = boost::make_shared<Asset>(assetFolder);
		HashTask* task = new HashTask(asset, _ioSvc, boost::bind(&LinkedAssetStore::_addAsset, this, _1, handler));
		_threadPool.post(*task);
		return true;
	}
}

void LinkedAssetStore::_addAsset(Asset::Ptr& asset, LinkedAssetStore::ResultHandler upstream)
{
	BitHordeIds ids;
	if (asset.get() && asset->getIds(ids)) {
		const char *data_path = (asset->folder()/"data").c_str();
		lutimes(data_path, NULL);
		cerr << data_path << endl;

		for (auto iter=ids.begin(); iter != ids.end(); iter++) {
			if (iter->type() == bithorde::HashType::TREE_TIGER) {
				fs::path link = _tigerFolder / base32encode(iter->id());
				if (fs::exists(fs::symlink_status(link)))
					fs::remove(link);

				// TODO: make links relative instead, so storage can be moved around a little.
				fs::create_symlink(fs::absolute(asset->folder()), link);
			}
		}
	}
	upstream(asset);
}

void purgeLink(const fs::path& path) {
	fs::remove(path);
}

void purgeLinkAndAsset(const fs::path& path) {
	boost::system::error_code e;
	auto asset = fs::read_symlink(path, e);
	purgeLink(path);
	if (!e && fs::is_directory(asset))
		fs::remove_all(asset);
}

enum LinkStatus{
	OK,
	BROKEN,
	OUTDATED,
};

LinkStatus validateDataSymlink(const fs::path& path) {
	struct stat linkStat, dataStat;

	const char* c_path = path.c_str();
	if (lstat(c_path, &linkStat) ||
	    !S_ISLNK(linkStat.st_mode) ||
	    stat(c_path, &dataStat) ||
	    !S_ISREG(dataStat.st_mode))
		return BROKEN;
	if (linkStat.st_mtime >= dataStat.st_mtime)
		return OK;
	else
		return OUTDATED;
}

void noop(Asset::Ptr) {}

Asset::Ptr LinkedAssetStore::findAsset(const BitHordeIds& ids)
{
	for (auto iter=ids.begin(); iter != ids.end(); iter++) {
		if (iter->type() == bithorde::HashType::TREE_TIGER) {
			fs::path hashLink = _tigerFolder / base32encode(iter->id());
			boost::system::error_code e;
			auto assetFolder = fs::read_symlink(hashLink, e);
			Asset::Ptr asset;
			if (e || !fs::is_directory(assetFolder)) {
				purgeLink(hashLink);
				continue;
			} else {
				auto assetDataPath = assetFolder/"data";
				switch (validateDataSymlink(assetDataPath)) {
				case OUTDATED:
					cerr << "Warning; outdated asset detected, " << assetFolder << endl;
					purgeLink(hashLink);
					fs::remove(assetFolder/"meta");
				case OK:
					asset = boost::make_shared<Asset>(assetFolder);
					break;

				case BROKEN:
					cerr << "Warning; broken asset detected, " << assetFolder << endl;
					purgeLinkAndAsset(hashLink);
				default:
					continue;
				}
			}
			if (asset->hasRootHash()) {
				return asset;
			} else {
				cerr << "Unhashed asset detected, hashing" << endl;
				_threadPool.post(*new HashTask(asset, _ioSvc, boost::bind(&LinkedAssetStore::_addAsset, this, _1, &noop)));
			}
		}
	}
	return Asset::Ptr();
}

<|endoftext|>


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

#ifndef FORMS_COMPONENT_FILTER_HXX
#define FORMS_COMPONENT_FILTER_HXX

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_
#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_FORM_XBOUNDCOMPONENT_HPP_
#include <com/sun/star/form/XBoundComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_
#include <com/sun/star/util/XNumberFormatter.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_XTEXTCOMPONENT_HPP_
#include <com/sun/star/awt/XTextComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_
#include <com/sun/star/sdb/SQLContext.hpp>
#endif

#ifndef _TOOLKIT_CONTROLS_UNOCONTROL_HXX_
#include <toolkit/controls/unocontrol.hxx>
#endif

#ifndef _TOOLKIT_AWT_LISTENERMULTIPLEXER_HXX_
#include <toolkit/helper/listenermultiplexer.hxx>
#endif

#ifndef _CPPUHELPER_IMPLBASE5_HXX_
#include <cppuhelper/implbase5.hxx>
#endif

#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE4_HXX_
#include <cppuhelper/implbase4.hxx>
#endif
#ifndef _CONNECTIVITY_SQLPARSE_HXX
#include <connectivity/sqlparse.hxx>
#endif

#ifndef SVX_QUERYDESIGNCONTEXT_HXX
#include <svx/ParseContext.hxx>
#endif

class Window;

//.........................................................................
namespace frm
{
//.........................................................................

    //=====================================================================
    // OFilterControl
    //=====================================================================
    typedef ::cppu::ImplHelper5 <   ::com::sun::star::awt::XTextComponent
                                ,   ::com::sun::star::awt::XFocusListener
                                ,   ::com::sun::star::awt::XItemListener
                                ,   ::com::sun::star::form::XBoundComponent
                                ,   ::com::sun::star::lang::XInitialization
                                >   OFilterControl_BASE;

    class OFilterControl    :public UnoControl
                            ,public OFilterControl_BASE
                            ,public ::svxform::OParseContextClient
    {
        TextListenerMultiplexer     m_aTextListeners;

        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >        m_xORB;
        ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >               m_xField;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >            m_xFormatter;
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >           m_xMetaData;
        ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >                      m_xMessageParent;

        ::rtl::OUString                 m_aText;
        ::connectivity::OSQLParser      m_aParser;
        sal_Int16                       m_nControlClass;        // which kind of control do we use?
        sal_Bool                        m_bFilterList : 1;
        sal_Bool                        m_bMultiLine : 1;
        sal_Bool                        m_bFilterListFilled : 1;

    private:
//      OFilterControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB);

        void implInitFilterList();

    public:
        OFilterControl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB );

        DECLARE_UNO3_AGG_DEFAULTS(OFilterControl,OWeakAggObject);
        ::com::sun::star::uno::Any  SAL_CALL queryAggregation( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException);

        static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId();
        sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 > & rId );

        virtual ::rtl::OUString GetComponentServiceName();
        virtual void SAL_CALL   createPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > & rxToolkit, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >  & rParentPeer ) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::lang::XComponent
        virtual void SAL_CALL   dispose(void) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::awt::XTextComponent
        virtual void            SAL_CALL addTextListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextListener > & l ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL removeTextListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextListener > & l ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL setText( const ::rtl::OUString& aText ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw( ::com::sun::star::uno::RuntimeException );
        virtual ::rtl::OUString SAL_CALL getText() throw( ::com::sun::star::uno::RuntimeException );
        virtual ::rtl::OUString SAL_CALL getSelectedText() throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw( ::com::sun::star::uno::RuntimeException );
        virtual ::com::sun::star::awt::Selection SAL_CALL getSelection() throw( ::com::sun::star::uno::RuntimeException );
        virtual sal_Bool        SAL_CALL isEditable() throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL setEditable( sal_Bool bEditable ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL setMaxTextLen( sal_Int16 nLength ) throw( ::com::sun::star::uno::RuntimeException );
        virtual sal_Int16       SAL_CALL getMaxTextLen() throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::form::XBoundComponent
        virtual void            SAL_CALL addUpdateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener > & l) throw( ::com::sun::star::uno::RuntimeException ) {}
        virtual void            SAL_CALL removeUpdateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener > & l) throw( ::com::sun::star::uno::RuntimeException ) {}
        virtual sal_Bool        SAL_CALL commit() throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::lang::XEventListener
        virtual void            SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::awt::XFocusListener
        virtual void            SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& e) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& e) throw( ::com::sun::star::uno::RuntimeException ){}

    // ::com::sun::star::awt::XItemListener
        virtual void            SAL_CALL itemStateChanged(const ::com::sun::star::awt::ItemEvent& rEvent) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::util::XInitialization
        virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

        // XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);

        // com::sun::star::lang::XServiceInfo - static version
        static  ::rtl::OUString SAL_CALL getImplementationName_Static();
        static  ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static();
        static  ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory );

    protected:
        virtual void PrepareWindowDescriptor( ::com::sun::star::awt::WindowDescriptor& rDesc );
        virtual void ImplSetPeerProperty( const ::rtl::OUString& rPropName, const ::com::sun::star::uno::Any& rVal );

        sal_Bool ensureInitialized( );

        void displayException( const ::com::sun::star::sdb::SQLContext& _rExcept );
    };
//.........................................................................
}   // namespace frm
//.........................................................................

#endif // FORMS_COMPONENT_FILTER_HXX
<commit_msg>INTEGRATION: CWS dba12 (1.3.40); FILE MERGED 2004/04/28 06:54:32 fs 1.3.40.1: #i26720# use a OPredicateInputController to normalize the input<commit_after>/*************************************************************************
 *
 *  $RCSfile: Filter.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hjs $ $Date: 2004-06-28 17:09:14 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef FORMS_COMPONENT_FILTER_HXX
#define FORMS_COMPONENT_FILTER_HXX

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_FORM_XBOUNDCOMPONENT_HPP_
#include <com/sun/star/form/XBoundComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_
#include <com/sun/star/util/XNumberFormatter.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_XTEXTCOMPONENT_HPP_
#include <com/sun/star/awt/XTextComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_
#include <com/sun/star/sdb/SQLContext.hpp>
#endif

#ifndef _TOOLKIT_CONTROLS_UNOCONTROL_HXX_
#include <toolkit/controls/unocontrol.hxx>
#endif

#ifndef _TOOLKIT_AWT_LISTENERMULTIPLEXER_HXX_
#include <toolkit/helper/listenermultiplexer.hxx>
#endif

#ifndef _CPPUHELPER_IMPLBASE5_HXX_
#include <cppuhelper/implbase5.hxx>
#endif

#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE4_HXX_
#include <cppuhelper/implbase4.hxx>
#endif
#ifndef _CONNECTIVITY_SQLPARSE_HXX
#include <connectivity/sqlparse.hxx>
#endif

#ifndef SVX_QUERYDESIGNCONTEXT_HXX
#include <svx/ParseContext.hxx>
#endif

class Window;

//.........................................................................
namespace frm
{
//.........................................................................

    //=====================================================================
    // OFilterControl
    //=====================================================================
    typedef ::cppu::ImplHelper5 <   ::com::sun::star::awt::XTextComponent
                                ,   ::com::sun::star::awt::XFocusListener
                                ,   ::com::sun::star::awt::XItemListener
                                ,   ::com::sun::star::form::XBoundComponent
                                ,   ::com::sun::star::lang::XInitialization
                                >   OFilterControl_BASE;

    class OFilterControl    :public UnoControl
                            ,public OFilterControl_BASE
                            ,public ::svxform::OParseContextClient
    {
        TextListenerMultiplexer     m_aTextListeners;

        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >        m_xORB;
        ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >               m_xField;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >            m_xFormatter;
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >                 m_xConnection;
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >           m_xMetaData;
        ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >                      m_xMessageParent;

        ::rtl::OUString                 m_aText;
        ::connectivity::OSQLParser      m_aParser;
        sal_Int16                       m_nControlClass;        // which kind of control do we use?
        sal_Bool                        m_bFilterList : 1;
        sal_Bool                        m_bMultiLine : 1;
        sal_Bool                        m_bFilterListFilled : 1;

    private:
//      OFilterControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB);

        void implInitFilterList();

    public:
        OFilterControl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB );

        DECLARE_UNO3_AGG_DEFAULTS(OFilterControl,OWeakAggObject);
        ::com::sun::star::uno::Any  SAL_CALL queryAggregation( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException);

        static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId();
        sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 > & rId );

        virtual ::rtl::OUString GetComponentServiceName();
        virtual void SAL_CALL   createPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > & rxToolkit, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >  & rParentPeer ) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::lang::XComponent
        virtual void SAL_CALL   dispose(void) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::awt::XTextComponent
        virtual void            SAL_CALL addTextListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextListener > & l ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL removeTextListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextListener > & l ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL setText( const ::rtl::OUString& aText ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw( ::com::sun::star::uno::RuntimeException );
        virtual ::rtl::OUString SAL_CALL getText() throw( ::com::sun::star::uno::RuntimeException );
        virtual ::rtl::OUString SAL_CALL getSelectedText() throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw( ::com::sun::star::uno::RuntimeException );
        virtual ::com::sun::star::awt::Selection SAL_CALL getSelection() throw( ::com::sun::star::uno::RuntimeException );
        virtual sal_Bool        SAL_CALL isEditable() throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL setEditable( sal_Bool bEditable ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL setMaxTextLen( sal_Int16 nLength ) throw( ::com::sun::star::uno::RuntimeException );
        virtual sal_Int16       SAL_CALL getMaxTextLen() throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::form::XBoundComponent
        virtual void            SAL_CALL addUpdateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener > & l) throw( ::com::sun::star::uno::RuntimeException ) {}
        virtual void            SAL_CALL removeUpdateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XUpdateListener > & l) throw( ::com::sun::star::uno::RuntimeException ) {}
        virtual sal_Bool        SAL_CALL commit() throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::lang::XEventListener
        virtual void            SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::awt::XFocusListener
        virtual void            SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& e) throw( ::com::sun::star::uno::RuntimeException );
        virtual void            SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& e) throw( ::com::sun::star::uno::RuntimeException ){}

    // ::com::sun::star::awt::XItemListener
        virtual void            SAL_CALL itemStateChanged(const ::com::sun::star::awt::ItemEvent& rEvent) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::util::XInitialization
        virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

        // XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);

        // com::sun::star::lang::XServiceInfo - static version
        static  ::rtl::OUString SAL_CALL getImplementationName_Static();
        static  ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_Static();
        static  ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory );

    protected:
        virtual void PrepareWindowDescriptor( ::com::sun::star::awt::WindowDescriptor& rDesc );
        virtual void ImplSetPeerProperty( const ::rtl::OUString& rPropName, const ::com::sun::star::uno::Any& rVal );

        sal_Bool ensureInitialized( );

        void displayException( const ::com::sun::star::sdb::SQLContext& _rExcept );
    };
//.........................................................................
}   // namespace frm
//.........................................................................

#endif // FORMS_COMPONENT_FILTER_HXX
<|endoftext|>


<commit_before>#pragma once

namespace Channel9
{
	//round a number up to the nearest power of 2
	template<typename uint>
	inline uint ceil_power2(uint v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		if(sizeof(uint) >= 2) v |= v >> 8;
		if(sizeof(uint) >= 4) v |= v >> 16;
		if(sizeof(uint) >= 8) v |= v >> 32;
		v++;
		return v;
	}

	inline uint64_t ceil_power2(uint64_t v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v |= v >> 8;
		v |= v >> 16;
		v |= v >> 32;
		v++;
		return v;
	}
	inline uint32_t ceil_power2(uint32_t v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v |= v >> 8;
		v |= v >> 16;
		v++;
		return v;
	}
	inline uint16_t ceil_power2(uint16_t v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v |= v >> 8;
		v++;
		return v;
	}
	inline uint8_t ceil_power2(uint8_t v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v++;
		return v;
	}

	//returns true if exactly 1 bit is set
	template<typename uint>
	inline bool is_power2(uint n){
		return (n && !(n & (n - 1)));
	}

	template<typename uint>
	inline uint clear_bottom_bits(uint n, int num_bits){
		return (n & ~((1 << num_bits)-1));
	}

	//count the trailing zeroes, essentially what power of 2 is it
	template<typename uint>
	inline uint count_bottom_zeros1(uint n){
		if(n == 0)
			return 0;//sizeof(uint) * 8;

		uint count = 0;
		while((n & 1) == 0){
			++count;
			n >>= 1;
		}
		return count;
	}

	//count the trailing zeroes, essentially what power of 2 is it
	template<typename uint>
	inline uint count_bottom_zeros2(uint n){
		if(n == 0)
			return 0;//sizeof(uint) * 8;

		uint count = 0;
		uint bits = sizeof(uint) * 4;
		do {
			if((n & ((1 << bits) - 1)) == 0){
				count += bits;
				n >>= bits;
			}
			bits >>= 1;
		}while(bits);

		return count;
	}

	//count the trailing zeroes, essentially what power of 2 is it
	template<typename uint>
	inline uint count_bottom_zeros3(uint n){
		if(n == 0)
			return 0;//sizeof(uint) * 8;

		uint count = 0;
		uint bits = sizeof(uint) * 4;
		uint mask = (1 << bits) - 1;
		do {
			if((n & mask) == 0){
				count += bits;
				n >>= bits;
			}
			bits >>= 1;
			mask >>= bits;
		}while(bits && (n & 1) == 0);

		return count;
	}

	//count the trailing zeroes, essentially what power of 2 is it
	template<typename uint>
	inline uint count_bottom_zeros4(uint n){
		if(n == 0)
			return 0; //sizeof(uint) * 8;

		uint count = 0;

		if(sizeof(uint) >= 8 && (n & 0xFFFFFFFFULL) == 0){ count += 32; n >>= 32; }
		if(sizeof(uint) >= 4 && (n & 0x0000FFFFULL) == 0){ count += 16; n >>= 16; }
		if(sizeof(uint) >= 2 && (n & 0x000000FFULL) == 0){ count +=  8; n >>=  8; }
		if(sizeof(uint) >= 1 && (n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if(sizeof(uint) >= 1 && (n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if(sizeof(uint) >= 1 && (n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }

		return count;
	}
	inline uint8_t count_bottom_zeros4(uint8_t n){
		if(n == 0)
			return 0;
		uint8_t count = 0;
		if((n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if((n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if((n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }
		return count;
	}
	inline uint16_t count_bottom_zeros4(uint16_t n){
		if(n == 0)
			return 0;
		uint16_t count = 0;
		if((n & 0x000000FFULL) == 0){ count +=  8; n >>=  8; }
		if((n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if((n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if((n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }
		return count;
	}
	inline uint32_t count_bottom_zeros4(uint32_t n){
		if(n == 0)
			return 0;
		uint32_t count = 0;
		if((n & 0x0000FFFFULL) == 0){ count += 16; n >>= 16; }
		if((n & 0x000000FFULL) == 0){ count +=  8; n >>=  8; }
		if((n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if((n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if((n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }
		return count;
	}
	inline uint64_t count_bottom_zeros4(uint64_t n){
		if(n == 0)
			return 0;
		uint64_t count = 0;
		if((n & 0xFFFFFFFFULL) == 0){ count += 32; n >>= 32; }
		if((n & 0x0000FFFFULL) == 0){ count += 16; n >>= 16; }
		if((n & 0x000000FFULL) == 0){ count +=  8; n >>=  8; }
		if((n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if((n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if((n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }
		return count;
	}

	//count how many bits are set
	template<typename uint>
	inline uint count_bits_set(uint n){
		uint count = 0;
		while(n){
			++count;
			n &= (n - 1);
		}
		return count;
	}

	//give a good distribution over the hash space to have fewer collisions, both copied from MurmurHash
	inline uint32_t mix_bits(uint32_t h){
		h ^= h >> 16;
		h *= 0x85ebca6b;
		h ^= h >> 13;
		h *= 0xc2b2ae35;
		h ^= h >> 16;
		return h;
	}
	inline uint64_t mix_bits(uint64_t h){
		h ^= h >> 33;
		h *= 0xff51afd7ed558ccd;
		h ^= h >> 33;
		h *= 0xc4ceb9fe1a85ec53;
		h ^= h >> 33;
		return h;
	}
}
<commit_msg>Add a version of ceil_power2 that rounds up to a specific power of 2, this is useful for 8 byte alignment or similar<commit_after>#pragma once

namespace Channel9
{
	//round a number up to the nearest full power of 2
	template<typename uint>
	inline uint ceil_power2(uint v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		if(sizeof(uint) >= 2) v |= v >> 8;
		if(sizeof(uint) >= 4) v |= v >> 16;
		if(sizeof(uint) >= 8) v |= v >> 32;
		v++;
		return v;
	}

	inline uint64_t ceil_power2(uint64_t v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v |= v >> 8;
		v |= v >> 16;
		v |= v >> 32;
		v++;
		return v;
	}
	inline uint32_t ceil_power2(uint32_t v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v |= v >> 8;
		v |= v >> 16;
		v++;
		return v;
	}
	inline uint16_t ceil_power2(uint16_t v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v |= v >> 8;
		v++;
		return v;
	}
	inline uint8_t ceil_power2(uint8_t v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v++;
		return v;
	}

	//round up to a multiple of a specific power of 2
	template<typename uint>
	inline uint ceil_power2(uint n, int bits){
		uint p = 1 << bits;
		uint m = p-1;
		return (n + m) & ~m;
//		return n + ((p - (n & m)) & m);
//		return n + ((p - (n % p)) % p);
	}

	//returns true if exactly 1 bit is set
	template<typename uint>
	inline bool is_power2(uint n){
		return (n && !(n & (n - 1)));
	}

	template<typename uint>
	inline uint clear_bottom_bits(uint n, int num_bits){
		return (n & ~((1 << num_bits)-1));
	}

	//count the trailing zeroes, essentially what power of 2 is it
	template<typename uint>
	inline uint count_bottom_zeros1(uint n){
		if(n == 0)
			return 0;//sizeof(uint) * 8;

		uint count = 0;
		while((n & 1) == 0){
			++count;
			n >>= 1;
		}
		return count;
	}

	//count the trailing zeroes, essentially what power of 2 is it
	template<typename uint>
	inline uint count_bottom_zeros2(uint n){
		if(n == 0)
			return 0;//sizeof(uint) * 8;

		uint count = 0;
		uint bits = sizeof(uint) * 4;
		do {
			if((n & ((1 << bits) - 1)) == 0){
				count += bits;
				n >>= bits;
			}
			bits >>= 1;
		}while(bits);

		return count;
	}

	//count the trailing zeroes, essentially what power of 2 is it
	template<typename uint>
	inline uint count_bottom_zeros3(uint n){
		if(n == 0)
			return 0;//sizeof(uint) * 8;

		uint count = 0;
		uint bits = sizeof(uint) * 4;
		uint mask = (1 << bits) - 1;
		do {
			if((n & mask) == 0){
				count += bits;
				n >>= bits;
			}
			bits >>= 1;
			mask >>= bits;
		}while(bits && (n & 1) == 0);

		return count;
	}

	//count the trailing zeroes, essentially what power of 2 is it
	template<typename uint>
	inline uint count_bottom_zeros4(uint n){
		if(n == 0)
			return 0; //sizeof(uint) * 8;

		uint count = 0;

		if(sizeof(uint) >= 8 && (n & 0xFFFFFFFFULL) == 0){ count += 32; n >>= 32; }
		if(sizeof(uint) >= 4 && (n & 0x0000FFFFULL) == 0){ count += 16; n >>= 16; }
		if(sizeof(uint) >= 2 && (n & 0x000000FFULL) == 0){ count +=  8; n >>=  8; }
		if(sizeof(uint) >= 1 && (n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if(sizeof(uint) >= 1 && (n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if(sizeof(uint) >= 1 && (n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }

		return count;
	}
	inline uint8_t count_bottom_zeros4(uint8_t n){
		if(n == 0)
			return 0;
		uint8_t count = 0;
		if((n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if((n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if((n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }
		return count;
	}
	inline uint16_t count_bottom_zeros4(uint16_t n){
		if(n == 0)
			return 0;
		uint16_t count = 0;
		if((n & 0x000000FFULL) == 0){ count +=  8; n >>=  8; }
		if((n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if((n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if((n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }
		return count;
	}
	inline uint32_t count_bottom_zeros4(uint32_t n){
		if(n == 0)
			return 0;
		uint32_t count = 0;
		if((n & 0x0000FFFFULL) == 0){ count += 16; n >>= 16; }
		if((n & 0x000000FFULL) == 0){ count +=  8; n >>=  8; }
		if((n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if((n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if((n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }
		return count;
	}
	inline uint64_t count_bottom_zeros4(uint64_t n){
		if(n == 0)
			return 0;
		uint64_t count = 0;
		if((n & 0xFFFFFFFFULL) == 0){ count += 32; n >>= 32; }
		if((n & 0x0000FFFFULL) == 0){ count += 16; n >>= 16; }
		if((n & 0x000000FFULL) == 0){ count +=  8; n >>=  8; }
		if((n & 0x0000000FULL) == 0){ count +=  4; n >>=  4; }
		if((n & 0x00000003ULL) == 0){ count +=  2; n >>=  2; }
		if((n & 0x00000001ULL) == 0){ count +=  1; n >>=  1; }
		return count;
	}

	//count how many bits are set
	template<typename uint>
	inline uint count_bits_set(uint n){
		uint count = 0;
		while(n){
			++count;
			n &= (n - 1);
		}
		return count;
	}

	//give a good distribution over the hash space to have fewer collisions, both copied from MurmurHash
	inline uint32_t mix_bits(uint32_t h){
		h ^= h >> 16;
		h *= 0x85ebca6b;
		h ^= h >> 13;
		h *= 0xc2b2ae35;
		h ^= h >> 16;
		return h;
	}
	inline uint64_t mix_bits(uint64_t h){
		h ^= h >> 33;
		h *= 0xff51afd7ed558ccd;
		h ^= h >> 33;
		h *= 0xc4ceb9fe1a85ec53;
		h ^= h >> 33;
		return h;
	}
}

<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. 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 <string.h>

#include <node.h>
#include <nan.h>
#include "grpc/grpc.h"
#include "grpc/byte_buffer_reader.h"
#include "grpc/support/slice.h"

#include "byte_buffer.h"

namespace grpc {
namespace node {

using v8::Context;
using v8::Function;
using v8::Local;
using v8::Object;
using v8::Number;
using v8::Value;

grpc_byte_buffer *BufferToByteBuffer(Local<Value> buffer) {
  Nan::HandleScope scope;
  int length = ::node::Buffer::Length(buffer);
  char *data = ::node::Buffer::Data(buffer);
  gpr_slice slice = gpr_slice_malloc(length);
  memcpy(GPR_SLICE_START_PTR(slice), data, length);
  grpc_byte_buffer *byte_buffer(grpc_raw_byte_buffer_create(&slice, 1));
  gpr_slice_unref(slice);
  return byte_buffer;
}

namespace {
void delete_buffer(char *data, void *hint) { delete[] data; }
}

Local<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) {
  Nan::EscapableHandleScope scope;
  if (buffer == NULL) {
    return scope.Escape(Nan::Null());
  }
  size_t length = grpc_byte_buffer_length(buffer);
  char *result = new char[length];
  size_t offset = 0;
  grpc_byte_buffer_reader reader;
  grpc_byte_buffer_reader_init(&reader, buffer);
  gpr_slice next;
  while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
    memcpy(result + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next));
    offset += GPR_SLICE_LENGTH(next);
    gpr_slice_unref(next);
  }
  return scope.Escape(MakeFastBuffer(
      Nan::NewBuffer(result, length, delete_buffer, NULL).ToLocalChecked()));
}

Local<Value> MakeFastBuffer(Local<Value> slowBuffer) {
  Nan::EscapableHandleScope scope;
  Local<Object> globalObj = Nan::GetCurrentContext()->Global();
  Local<Function> bufferConstructor = Local<Function>::Cast(
      globalObj->Get(Nan::New("Buffer").ToLocalChecked()));
  Local<Value> consArgs[3] = {
    slowBuffer,
    Nan::New<Number>(::node::Buffer::Length(slowBuffer)),
    Nan::New<Number>(0)
  };
  Local<Object> fastBuffer = bufferConstructor->NewInstance(3, consArgs);
  return scope.Escape(fastBuffer);
}
}  // namespace node
}  // namespace grpc
<commit_msg>Make Node not segfault when it receives a compressed message<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. 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 <string.h>

#include <node.h>
#include <nan.h>
#include "grpc/grpc.h"
#include "grpc/byte_buffer_reader.h"
#include "grpc/support/slice.h"
#include "grpc/support/log.h"

#include "byte_buffer.h"

namespace grpc {
namespace node {

using v8::Context;
using v8::Function;
using v8::Local;
using v8::Object;
using v8::Number;
using v8::Value;

grpc_byte_buffer *BufferToByteBuffer(Local<Value> buffer) {
  Nan::HandleScope scope;
  int length = ::node::Buffer::Length(buffer);
  char *data = ::node::Buffer::Data(buffer);
  gpr_slice slice = gpr_slice_malloc(length);
  memcpy(GPR_SLICE_START_PTR(slice), data, length);
  grpc_byte_buffer *byte_buffer(grpc_raw_byte_buffer_create(&slice, 1));
  gpr_slice_unref(slice);
  return byte_buffer;
}

namespace {
void delete_buffer(char *data, void *hint) { delete[] data; }
}

Local<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) {
  Nan::EscapableHandleScope scope;
  if (buffer == NULL) {
    return scope.Escape(Nan::Null());
  }
  gpr_log(GPR_DEBUG, "Compressed size: %d", grpc_byte_buffer_length(buffer));
  grpc_byte_buffer_reader reader;
  grpc_byte_buffer_reader_init(&reader, buffer);
  gpr_slice slice = grpc_byte_buffer_reader_readall(&reader);
  size_t length = GPR_SLICE_LENGTH(slice);
  char *result = new char[length];
  memcpy(result, GPR_SLICE_START_PTR(slice), length);
  return scope.Escape(MakeFastBuffer(
      Nan::NewBuffer(result, length, delete_buffer, NULL).ToLocalChecked()));
}

Local<Value> MakeFastBuffer(Local<Value> slowBuffer) {
  Nan::EscapableHandleScope scope;
  Local<Object> globalObj = Nan::GetCurrentContext()->Global();
  Local<Function> bufferConstructor = Local<Function>::Cast(
      globalObj->Get(Nan::New("Buffer").ToLocalChecked()));
  Local<Value> consArgs[3] = {
    slowBuffer,
    Nan::New<Number>(::node::Buffer::Length(slowBuffer)),
    Nan::New<Number>(0)
  };
  Local<Object> fastBuffer = bufferConstructor->NewInstance(3, consArgs);
  return scope.Escape(fastBuffer);
}
}  // namespace node
}  // namespace grpc
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#include "fstream.hh"
#include "align.hh"
#include "circular_buffer.hh"
#include "semaphore.hh"
#include "reactor.hh"
#include <malloc.h>
#include <string.h>

class file_data_source_impl : public data_source_impl {
    file _file;
    uint64_t _pos;
    size_t _buffer_size;
public:
    file_data_source_impl(file f, uint64_t pos, size_t buffer_size)
            : _file(std::move(f)), _pos(pos), _buffer_size(buffer_size) {}
    virtual future<temporary_buffer<char>> get() override {
        using buf_type = temporary_buffer<char>;
        return _file.dma_read_bulk<char>(_pos, _buffer_size).then(
                [this] (buf_type buf) {
            _pos += buf.size();
            return std::move(buf);
        });
    }
};

class file_data_source : public data_source {
public:
    file_data_source(file f, uint64_t offset, size_t buffer_size)
        : data_source(std::make_unique<file_data_source_impl>(
                std::move(f), offset, buffer_size)) {}
};

input_stream<char> make_file_input_stream(
        file f, uint64_t offset, size_t buffer_size) {
    return input_stream<char>(file_data_source(std::move(f), offset, buffer_size));
}

class file_data_sink_impl : public data_sink_impl {
    file _file;
    file_output_stream_options _options;
    uint64_t _pos = 0;
    // At offsets < _preallocating_at, preallocation was completed.
    // At offsets >= _preallocating_at, we may be preallocating
    // disk space, so all writes must wait until _preallocation_done[i]
    // becomes ready (in _options.preallocation_size units)
    // At offsets >= _preallocating_at + _options.preallocation_size *
    //               _preallocation_done.size(), we have not yet started.
    uint64_t _preallocating_at = 0;
    // Each promise vector lists writes that are waiting for a single preallocation
    circular_buffer<std::vector<promise<>>> _preallocation_done;
    semaphore _write_behind_sem = { _options.write_behind };
    future<> _background_writes_done = make_ready_future<>();
    bool _failed = false;
public:
    file_data_sink_impl(file f, file_output_stream_options options)
            : _file(std::move(f)), _options(options) {}
    future<> put(net::packet data) { abort(); }
    virtual temporary_buffer<char> allocate_buffer(size_t size) override {
        return temporary_buffer<char>::aligned(file::dma_alignment, size);
    }
    virtual future<> put(temporary_buffer<char> buf) override {
        uint64_t pos = _pos;
        _pos += buf.size();
        if (!_options.write_behind) {
            return do_put(pos, std::move(buf));
        }
        // Write behind strategy:
        //
        // 1. Issue N writes in parallel, using a semphore to limit to N
        // 2. Collect results in _background_writes_done, merging exception futures
        // 3. If we've already seen a failure, don't issue more writes.
        return _write_behind_sem.wait().then([this, pos, buf = std::move(buf)] () mutable {
            if (_failed) {
                _write_behind_sem.signal();
                auto ret = std::move(_background_writes_done);
                _background_writes_done = make_ready_future<>();
                return ret;
            }
            auto this_write_done = do_put(pos, std::move(buf)).finally([this] {
                _write_behind_sem.signal();
            });
            _background_writes_done = when_all(std::move(_background_writes_done), std::move(this_write_done))
                    .then([this] (std::tuple<future<>, future<>> possible_errors) {
                // merge the two errors, preferring the first
                auto& e1 = std::get<0>(possible_errors);
                auto& e2 = std::get<1>(possible_errors);
                if (e1.failed()) {
                    e2.ignore_ready_future();
                    return std::move(e1);
                } else {
                    if (e2.failed()) {
                        _failed = true;
                    }
                    return std::move(e2);
                }
            });
            return make_ready_future<>();
        });
    }
private:
    virtual future<> do_put(uint64_t pos, temporary_buffer<char> buf) {
        // put() must usually be of chunks multiple of file::dma_alignment.
        // Only the last part can have an unaligned length. If put() was
        // called again with an unaligned pos, we have a bug in the caller.
        assert(!(pos & (file::dma_alignment - 1)));
        bool truncate = false;
        auto p = static_cast<const char*>(buf.get());
        size_t buf_size = buf.size();

        if ((buf.size() & (file::dma_alignment - 1)) != 0) {
            // If buf size isn't aligned, copy its content into a new aligned buf.
            // This should only happen when the user calls output_stream::flush().
            auto tmp = allocate_buffer(align_up(buf.size(), file::dma_alignment));
            ::memcpy(tmp.get_write(), buf.get(), buf.size());
            buf = std::move(tmp);
            p = buf.get();
            buf_size = buf.size();
            truncate = true;
        }
        auto prealloc = preallocate(pos, buf.size());
        return prealloc.then([this, pos, p, buf_size, truncate, buf = std::move(buf)] () mutable {
            return _file.dma_write(pos, p, buf_size).then(
                    [this, buf = std::move(buf), truncate] (size_t size) {
                if (truncate) {
                    return _file.truncate(_pos);
                }
                return make_ready_future<>();
            });
        });
    }
    future<> preallocate(uint64_t pos, uint64_t size) {
        auto ret = make_ready_future<>();
        if (pos + size <= _preallocating_at) {
            return ret;
        }
        auto skip = std::max(_preallocating_at, pos) - pos;
        pos += skip;
        size -= skip;
        size_t idx = (pos - _preallocating_at) / _options.preallocation_size;
        while (size) {
            if (idx == _preallocation_done.size()) {
                start_new_preallocation();
            }
            _preallocation_done[idx].emplace_back();
            auto this_prealloc_done = _preallocation_done[idx].back().get_future();
            ret = when_all(std::move(ret), std::move(this_prealloc_done)).discard_result();
            skip = std::min<uint64_t>(size, _options.preallocation_size);
            pos += skip;
            size -= skip;
            ++idx;
        }
        return ret;
    }
    void start_new_preallocation() {
        auto pos = _preallocating_at + _preallocation_done.size() * _options.preallocation_size;
        _preallocation_done.emplace_back();
        _file.allocate(pos, _options.preallocation_size).then_wrapped([this, pos] (future<> ret) {
            complete_preallocation(pos, std::move(ret));
        });
    }
    void complete_preallocation(uint64_t pos, future<> result) {
        // Preallocation may have failed.  But it's just preallocation,
        // so we can ignore the result.
        result.ignore_ready_future();
        size_t idx = (pos - _preallocating_at) / _options.preallocation_size;
        for (auto&& pr : _preallocation_done[idx]) {
            pr.set_value();
        }
        _preallocation_done[idx].clear();
        while (!_preallocation_done.empty() && _preallocation_done.front().empty()) {
            _preallocation_done.pop_front();
            _preallocating_at += _options.preallocation_size;
        }
    }
    future<> wait() {
        return _write_behind_sem.wait(_options.write_behind).then([this] {
            return _background_writes_done.then([this] {
                // restore to pristine state; for flush() + close() sequence
                // (we allow either flush, or close, or both)
                _write_behind_sem.signal(_options.write_behind);
                _background_writes_done = make_ready_future<>();
            });
        });
    }
public:
    virtual future<> flush() override {
        return wait().then([this] {
            return _file.flush();
        });
    }
    virtual future<> close() {
        return wait().then([this] {
            return _file.close();
        });
    }
};

class file_data_sink : public data_sink {
public:
    file_data_sink(file f, file_output_stream_options options)
        : data_sink(std::make_unique<file_data_sink_impl>(
                std::move(f), options)) {}
};

output_stream<char> make_file_output_stream(file f, size_t buffer_size) {
    file_output_stream_options options;
    options.buffer_size = buffer_size;
    return make_file_output_stream(std::move(f), options);
}

output_stream<char> make_file_output_stream(file f, file_output_stream_options options) {
    return output_stream<char>(file_data_sink(std::move(f), options), options.buffer_size, true);
}

<commit_msg>fstream: fix write-behind on filesystems that don't support fallocate()<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#include "fstream.hh"
#include "align.hh"
#include "circular_buffer.hh"
#include "semaphore.hh"
#include "reactor.hh"
#include <malloc.h>
#include <string.h>

class file_data_source_impl : public data_source_impl {
    file _file;
    uint64_t _pos;
    size_t _buffer_size;
public:
    file_data_source_impl(file f, uint64_t pos, size_t buffer_size)
            : _file(std::move(f)), _pos(pos), _buffer_size(buffer_size) {}
    virtual future<temporary_buffer<char>> get() override {
        using buf_type = temporary_buffer<char>;
        return _file.dma_read_bulk<char>(_pos, _buffer_size).then(
                [this] (buf_type buf) {
            _pos += buf.size();
            return std::move(buf);
        });
    }
};

class file_data_source : public data_source {
public:
    file_data_source(file f, uint64_t offset, size_t buffer_size)
        : data_source(std::make_unique<file_data_source_impl>(
                std::move(f), offset, buffer_size)) {}
};

input_stream<char> make_file_input_stream(
        file f, uint64_t offset, size_t buffer_size) {
    return input_stream<char>(file_data_source(std::move(f), offset, buffer_size));
}

class file_data_sink_impl : public data_sink_impl {
    file _file;
    file_output_stream_options _options;
    uint64_t _pos = 0;
    // At offsets < _preallocating_at, preallocation was completed.
    // At offsets >= _preallocating_at, we may be preallocating
    // disk space, so all writes must wait until _preallocation_done[i]
    // becomes ready (in _options.preallocation_size units)
    // At offsets >= _preallocating_at + _options.preallocation_size *
    //               _preallocation_done.size(), we have not yet started.
    uint64_t _preallocating_at = 0;
    // Each promise vector lists writes that are waiting for a single preallocation
    circular_buffer<std::vector<promise<>>> _preallocation_done;
    semaphore _write_behind_sem = { _options.write_behind };
    future<> _background_writes_done = make_ready_future<>();
    bool _failed = false;
public:
    file_data_sink_impl(file f, file_output_stream_options options)
            : _file(std::move(f)), _options(options) {}
    future<> put(net::packet data) { abort(); }
    virtual temporary_buffer<char> allocate_buffer(size_t size) override {
        return temporary_buffer<char>::aligned(file::dma_alignment, size);
    }
    virtual future<> put(temporary_buffer<char> buf) override {
        uint64_t pos = _pos;
        _pos += buf.size();
        if (!_options.write_behind) {
            return do_put(pos, std::move(buf));
        }
        // Write behind strategy:
        //
        // 1. Issue N writes in parallel, using a semphore to limit to N
        // 2. Collect results in _background_writes_done, merging exception futures
        // 3. If we've already seen a failure, don't issue more writes.
        return _write_behind_sem.wait().then([this, pos, buf = std::move(buf)] () mutable {
            if (_failed) {
                _write_behind_sem.signal();
                auto ret = std::move(_background_writes_done);
                _background_writes_done = make_ready_future<>();
                return ret;
            }
            auto this_write_done = do_put(pos, std::move(buf)).finally([this] {
                _write_behind_sem.signal();
            });
            _background_writes_done = when_all(std::move(_background_writes_done), std::move(this_write_done))
                    .then([this] (std::tuple<future<>, future<>> possible_errors) {
                // merge the two errors, preferring the first
                auto& e1 = std::get<0>(possible_errors);
                auto& e2 = std::get<1>(possible_errors);
                if (e1.failed()) {
                    e2.ignore_ready_future();
                    return std::move(e1);
                } else {
                    if (e2.failed()) {
                        _failed = true;
                    }
                    return std::move(e2);
                }
            });
            return make_ready_future<>();
        });
    }
private:
    virtual future<> do_put(uint64_t pos, temporary_buffer<char> buf) {
        // put() must usually be of chunks multiple of file::dma_alignment.
        // Only the last part can have an unaligned length. If put() was
        // called again with an unaligned pos, we have a bug in the caller.
        assert(!(pos & (file::dma_alignment - 1)));
        bool truncate = false;
        auto p = static_cast<const char*>(buf.get());
        size_t buf_size = buf.size();

        if ((buf.size() & (file::dma_alignment - 1)) != 0) {
            // If buf size isn't aligned, copy its content into a new aligned buf.
            // This should only happen when the user calls output_stream::flush().
            auto tmp = allocate_buffer(align_up(buf.size(), file::dma_alignment));
            ::memcpy(tmp.get_write(), buf.get(), buf.size());
            buf = std::move(tmp);
            p = buf.get();
            buf_size = buf.size();
            truncate = true;
        }
        auto prealloc = preallocate(pos, buf.size());
        return prealloc.then([this, pos, p, buf_size, truncate, buf = std::move(buf)] () mutable {
            return _file.dma_write(pos, p, buf_size).then(
                    [this, buf = std::move(buf), truncate] (size_t size) {
                if (truncate) {
                    return _file.truncate(_pos);
                }
                return make_ready_future<>();
            });
        });
    }
    future<> preallocate(uint64_t pos, uint64_t size) {
        auto ret = make_ready_future<>();
    restart:
        if (pos + size <= _preallocating_at) {
            return ret;
        }
        auto skip = std::max(_preallocating_at, pos) - pos;
        pos += skip;
        size -= skip;
        size_t idx = (pos - _preallocating_at) / _options.preallocation_size;
        while (size) {
            if (idx == _preallocation_done.size()) {
                start_new_preallocation();
                // May have caused _preallocating_at to change, so redo the loop
                goto restart;
            }
            _preallocation_done[idx].emplace_back();
            auto this_prealloc_done = _preallocation_done[idx].back().get_future();
            ret = when_all(std::move(ret), std::move(this_prealloc_done)).discard_result();
            skip = std::min<uint64_t>(size, _options.preallocation_size);
            pos += skip;
            size -= skip;
            ++idx;
        }
        return ret;
    }
    void start_new_preallocation() {
        auto pos = _preallocating_at + _preallocation_done.size() * _options.preallocation_size;
        _preallocation_done.emplace_back();
        _file.allocate(pos, _options.preallocation_size).then_wrapped([this, pos] (future<> ret) {
            complete_preallocation(pos, std::move(ret));
        });
    }
    void complete_preallocation(uint64_t pos, future<> result) {
        // Preallocation may have failed.  But it's just preallocation,
        // so we can ignore the result.
        result.ignore_ready_future();
        size_t idx = (pos - _preallocating_at) / _options.preallocation_size;
        for (auto&& pr : _preallocation_done[idx]) {
            pr.set_value();
        }
        _preallocation_done[idx].clear();
        while (!_preallocation_done.empty() && _preallocation_done.front().empty()) {
            _preallocation_done.pop_front();
            _preallocating_at += _options.preallocation_size;
        }
    }
    future<> wait() {
        return _write_behind_sem.wait(_options.write_behind).then([this] {
            return _background_writes_done.then([this] {
                // restore to pristine state; for flush() + close() sequence
                // (we allow either flush, or close, or both)
                _write_behind_sem.signal(_options.write_behind);
                _background_writes_done = make_ready_future<>();
            });
        });
    }
public:
    virtual future<> flush() override {
        return wait().then([this] {
            return _file.flush();
        });
    }
    virtual future<> close() {
        return wait().then([this] {
            return _file.close();
        });
    }
};

class file_data_sink : public data_sink {
public:
    file_data_sink(file f, file_output_stream_options options)
        : data_sink(std::make_unique<file_data_sink_impl>(
                std::move(f), options)) {}
};

output_stream<char> make_file_output_stream(file f, size_t buffer_size) {
    file_output_stream_options options;
    options.buffer_size = buffer_size;
    return make_file_output_stream(std::move(f), options);
}

output_stream<char> make_file_output_stream(file f, file_output_stream_options options) {
    return output_stream<char>(file_data_sink(std::move(f), options), options.buffer_size, true);
}

<|endoftext|>


<commit_before>#include <vector>
#include <cstdio>
#include <mutex>
#include <thread>
#include <condition_variable>

struct LogMetaData
{
  struct OneLogData { int line; const char* fmt; };
  std::vector<OneLogData> logs;

  int registering(int line, const char* fmt)
  {
    logs.push_back( OneLogData{line,fmt} );
    return logs.size() - 1;
  }
};
static LogMetaData g_logmetadata;

struct OneLog
{
  OneLog(int line, const char *fmt)
  { id = g_logmetadata.registering (line, fmt); }
  int id;
};

struct Logger
{
  template <typename T>
  void print(int id, T value);
};

#define LOG(fmt,value) { static const OneLog log(__LINE__,fmt); logger.print(log.id,value); }

bool run = true;

int main (int argc, char **argv)
{
  Logger logger;
  for (int i = 0; i < argc+1; ++i)
  {
    LOG("argc   =%d",argc   );
    LOG("argv[0]=%s",argv[0]);
  }
  run = false;
}

/*
template <typename T>
void Logger::print(int id, T value)
{
  std::printf("\nLogID=%d at line=%d message=", id, g_logmetadata.logs[id].line);
  std::printf(g_logmetadata.logs[id].fmt, value);
}
*/

template <typename T>
void Logger::print(int id, T value)
{
    static T static_value;
    static std::mutex m;
    std::condition_variable cv;
    static std::thread t([&]{
        while(run)
        {
            T local_value;
            {
                std::unique_lock<std::mutex> lk(m);
                cv.wait(lk);
                local_value = static_value;
            }
            std::printf("\nLogID=%d at line=%d message=", id, g_logmetadata.logs[id].line);
            std::printf(g_logmetadata.logs[id].fmt, local_value);
        }
    });
    {
        std::unique_lock<std::mutex> lk(m);
        static_value = value;
    }
    cv.notify_one();
}
<commit_msg>Use std::lock_guard<commit_after>#include <vector>
#include <cstdio>
#include <mutex>
#include <thread>
#include <condition_variable>

struct LogMetaData
{
  struct OneLogData { int line; const char* fmt; };
  std::vector<OneLogData> logs;

  int registering(int line, const char* fmt)
  {
    logs.push_back( OneLogData{line,fmt} );
    return logs.size() - 1;
  }
};
static LogMetaData g_logmetadata;

struct OneLog
{
  OneLog(int line, const char *fmt)
  { id = g_logmetadata.registering (line, fmt); }
  int id;
};

struct Logger
{
  template <typename T>
  void print(int id, T value);
};

#define LOG(fmt,value) { static const OneLog log(__LINE__,fmt); logger.print(log.id,value); }

bool run = true;

int main (int argc, char **argv)
{
  Logger logger;
  for (int i = 0; i < argc+1; ++i)
  {
    LOG("argc   =%d",argc   );
    LOG("argv[0]=%s",argv[0]);
  }
  run = false;
}

/*
template <typename T>
void Logger::print(int id, T value)
{
  std::printf("\nLogID=%d at line=%d message=", id, g_logmetadata.logs[id].line);
  std::printf(g_logmetadata.logs[id].fmt, value);
}
*/

template <typename T>
void Logger::print(int id, T value)
{
    static T static_value;
    static std::mutex m;
    std::condition_variable cv;
    static std::thread t([&]{
        while(run)
        {
            T local_value;
            {
                std::unique_lock<std::mutex> lock(m);
                cv.wait(lock);
                local_value = static_value;
            }
            std::printf("\nLogID=%d at line=%d message=", id, g_logmetadata.logs[id].line);
            std::printf(g_logmetadata.logs[id].fmt, local_value);
        }
    });
    {
        std::lock_guard<std::mutex> lock(m);
        static_value = value;
    }
    cv.notify_one();
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkCommon.h"
#include "mitkTestingMacros.h"
#include <itkMultiThreader.h>
#include <itksys/SystemTools.hxx>

/** Documentation
  *
  * @brief Objects of this class can start an internal thread by calling the Start() method.
  *        The thread is then logging messages until the method Stop() is called. The class
  *        can be used to test if logging is thread-save by using multiple objects and let
  *        them log simuntanously.
  */
class mitkTestLoggingThread
{
protected:

bool LoggingRunning;

int ThreadID;

itk::MultiThreader::Pointer m_MultiThreader;

void LogMessages()
  {

  while(LoggingRunning)
    {
    MITK_INFO << "Test info stream in thread " << ThreadID;
    MITK_WARN << "Test warning stream in thread " << ThreadID;
    MITK_DEBUG << "Test debugging stream in thread " << ThreadID;
    MITK_ERROR << "Test error stream in thread " << ThreadID;
    MITK_FATAL << "Test fatal stream in thread " << ThreadID;
    }
  }

static ITK_THREAD_RETURN_TYPE mitkTestLoggingThread::ThreadStartTracking(void* pInfoStruct)
  {
  /* extract this pointer from Thread Info structure */
  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
  if (pInfo == NULL)
  {
    return ITK_THREAD_RETURN_VALUE;
  }
  if (pInfo->UserData == NULL)
  {
    return ITK_THREAD_RETURN_VALUE;
  }
  mitkTestLoggingThread *thisthread = (mitkTestLoggingThread*)pInfo->UserData;

  if (thisthread != NULL)
    thisthread->LogMessages();

  return ITK_THREAD_RETURN_VALUE;
  }

public:

mitkTestLoggingThread(int number, itk::MultiThreader::Pointer MultiThreader)
  {
  ThreadID = number;
  m_MultiThreader = MultiThreader;
  }

void Start()
  {
  LoggingRunning = true;
  m_MultiThreader->SpawnThread(this->ThreadStartTracking, this);
  }

void Stop()
  {
  LoggingRunning = false;
  }

};

/** Documentation
 *
 *  @brief This class holds static test methods to sturcture the test of the mitk logging mechanism.
 */
class mitkLogTestClass
{

public:

static void TestSimpleLog()
    {
    bool testSucceded = true;
    try
      {
      MITK_INFO << "Test info stream.";
      MITK_WARN << "Test warning stream.";
      MITK_DEBUG << "Test debugging stream."; //only activated if cmake variable is on!
                                              //so no worries if you see no output for this line
      MITK_ERROR << "Test error stream.";
      MITK_FATAL << "Test fatal stream.";
      }
    catch(mitk::Exception e)
      {
      testSucceded = false;
      }
    MITK_TEST_CONDITION_REQUIRED(testSucceded,"Test logging streams.");
    }

static void TestThreadSaveLog()
    {
    bool testSucceded = true;

    try
      {
      //initialize two threads...
      itk::MultiThreader::Pointer myThreader = itk::MultiThreader::New();
      mitkTestLoggingThread myThreadClass1 = mitkTestLoggingThread(1,myThreader);
      mitkTestLoggingThread myThreadClass2 = mitkTestLoggingThread(2,myThreader);

      //start them
      myThreadClass1.Start();
      myThreadClass2.Start();

      //wait for 500 ms
      itksys::SystemTools::Delay(500);

      //stop them
      myThreadClass1.Stop();
      myThreadClass2.Stop();

      //sleep again to let all threads end
      itksys::SystemTools::Delay(200);
      }
    catch(...)
      {
      testSucceded = false;
      }

    //if no error occured until now, everything is ok
    MITK_TEST_CONDITION_REQUIRED(testSucceded,"Test logging in different threads.");
    }

static void TestLoggingToFile()
    {

    }

static void TestAddAndRemoveBackends()
    {
    mbilog::BackendCout myBackend = mbilog::BackendCout();
    mbilog::RegisterBackend(&myBackend);
    MITK_INFO << "Test logging";
    mbilog::UnregisterBackend(&myBackend);

    //if no error occured until now, everything is ok
    MITK_TEST_CONDITION_REQUIRED(true,"Test add/remove logging backend.");
    }

static void  TestDefaultBackend()
    {
    //not possible now, because we cannot unregister the mitk logging backend in the moment. If such a method is added to mbilog utility one may add this test.
    }

};

int mitkLogTest(int /* argc */, char* /*argv*/[])
{
  // always start with this!
  MITK_TEST_BEGIN("Log")

  MITK_TEST_OUTPUT(<<"TESTING ALL LOGGING OUTPUTS, ERROR MESSAGES ARE ALSO TESTED AND NOT MEANING AN ERROR OCCURED!")

  mitkLogTestClass::TestSimpleLog();
  mitkLogTestClass::TestThreadSaveLog();
  mitkLogTestClass::TestLoggingToFile();
  mitkLogTestClass::TestAddAndRemoveBackends();

  // always end with this!
  MITK_TEST_END()
}
<commit_msg>implemented test method for logging to file<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkCommon.h"
#include "mitkTestingMacros.h"
#include <mitkLog.h>
#include <itkMultiThreader.h>
#include <itksys/SystemTools.hxx>
#include <mitkStandardFileLocations.h>

/** Documentation
  *
  * @brief Objects of this class can start an internal thread by calling the Start() method.
  *        The thread is then logging messages until the method Stop() is called. The class
  *        can be used to test if logging is thread-save by using multiple objects and let
  *        them log simuntanously.
  */
class mitkTestLoggingThread
{
protected:

bool LoggingRunning;

int ThreadID;

itk::MultiThreader::Pointer m_MultiThreader;

void LogMessages()
  {

  while(LoggingRunning)
    {
    MITK_INFO << "Test info stream in thread " << ThreadID;
    MITK_WARN << "Test warning stream in thread " << ThreadID;
    MITK_DEBUG << "Test debugging stream in thread " << ThreadID;
    MITK_ERROR << "Test error stream in thread " << ThreadID;
    MITK_FATAL << "Test fatal stream in thread " << ThreadID;
    }
  }

static ITK_THREAD_RETURN_TYPE mitkTestLoggingThread::ThreadStartTracking(void* pInfoStruct)
  {
  /* extract this pointer from Thread Info structure */
  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
  if (pInfo == NULL)
  {
    return ITK_THREAD_RETURN_VALUE;
  }
  if (pInfo->UserData == NULL)
  {
    return ITK_THREAD_RETURN_VALUE;
  }
  mitkTestLoggingThread *thisthread = (mitkTestLoggingThread*)pInfo->UserData;

  if (thisthread != NULL)
    thisthread->LogMessages();

  return ITK_THREAD_RETURN_VALUE;
  }

public:

mitkTestLoggingThread(int number, itk::MultiThreader::Pointer MultiThreader)
  {
  ThreadID = number;
  m_MultiThreader = MultiThreader;
  }

void Start()
  {
  LoggingRunning = true;
  m_MultiThreader->SpawnThread(this->ThreadStartTracking, this);
  }

void Stop()
  {
  LoggingRunning = false;
  }

};

/** Documentation
 *
 *  @brief This class holds static test methods to sturcture the test of the mitk logging mechanism.
 */
class mitkLogTestClass
{

public:

static void TestSimpleLog()
    {
    bool testSucceded = true;
    try
      {
      MITK_INFO << "Test info stream.";
      MITK_WARN << "Test warning stream.";
      MITK_DEBUG << "Test debugging stream."; //only activated if cmake variable is on!
                                              //so no worries if you see no output for this line
      MITK_ERROR << "Test error stream.";
      MITK_FATAL << "Test fatal stream.";
      }
    catch(mitk::Exception e)
      {
      testSucceded = false;
      }
    MITK_TEST_CONDITION_REQUIRED(testSucceded,"Test logging streams.");
    }

static void TestThreadSaveLog()
    {
    bool testSucceded = true;

    try
      {
      //initialize two threads...
      itk::MultiThreader::Pointer myThreader = itk::MultiThreader::New();
      mitkTestLoggingThread myThreadClass1 = mitkTestLoggingThread(1,myThreader);
      mitkTestLoggingThread myThreadClass2 = mitkTestLoggingThread(2,myThreader);

      //start them
      myThreadClass1.Start();
      myThreadClass2.Start();

      //wait for 500 ms
      itksys::SystemTools::Delay(500);

      //stop them
      myThreadClass1.Stop();
      myThreadClass2.Stop();

      //sleep again to let all threads end
      itksys::SystemTools::Delay(200);
      }
    catch(...)
      {
      testSucceded = false;
      }

    //if no error occured until now, everything is ok
    MITK_TEST_CONDITION_REQUIRED(testSucceded,"Test logging in different threads.");
    }

static void TestLoggingToFile()
    {
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + "/testlog.log";
    mitk::LoggingBackend::SetLogFile(filename.c_str());
    MITK_INFO << "Test logging to default filename: " << mitk::LoggingBackend::GetLogFile();
    MITK_TEST_CONDITION_REQUIRED(itksys::SystemTools::FileExists(filename.c_str()),"Testing if log file exists.");
    //TODO delete log file?
    }

static void TestAddAndRemoveBackends()
    {
    mbilog::BackendCout myBackend = mbilog::BackendCout();
    mbilog::RegisterBackend(&myBackend);
    MITK_INFO << "Test logging";
    mbilog::UnregisterBackend(&myBackend);

    //if no error occured until now, everything is ok
    MITK_TEST_CONDITION_REQUIRED(true,"Test add/remove logging backend.");
    }

static void  TestDefaultBackend()
    {
    //not possible now, because we cannot unregister the mitk logging backend in the moment. If such a method is added to mbilog utility one may add this test.
    }

};

int mitkLogTest(int /* argc */, char* /*argv*/[])
{
  // always start with this!
  MITK_TEST_BEGIN("Log")

  MITK_TEST_OUTPUT(<<"TESTING ALL LOGGING OUTPUTS, ERROR MESSAGES ARE ALSO TESTED AND NOT MEANING AN ERROR OCCURED!")

  mitkLogTestClass::TestSimpleLog();
  mitkLogTestClass::TestThreadSaveLog();
  mitkLogTestClass::TestLoggingToFile();
  mitkLogTestClass::TestAddAndRemoveBackends();

  // always end with this!
  MITK_TEST_END()
}
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2010-01-14 14:20:26 +0100 (Thu, 14 Jan 2010) $
Version:   $Revision: 21047 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkTextOverlay.h"

#include "mitkProperties.h"
#include "mitkColorProperty.h"
#include "mitkPropertyList.h"

#include <itkCommand.h>

#include <QLayout>

QmitkTextOverlay::QmitkTextOverlay( const char* id ):
QmitkOverlay(id), m_Widget( NULL )
{
  m_Widget = new QLabel();
  m_Widget->setStyleSheet("");
}

QmitkTextOverlay::~QmitkTextOverlay()
{
  m_Widget = NULL;
}

void QmitkTextOverlay::GenerateData( mitk::PropertyList::Pointer pl )
{
  if ( pl.IsNull() )
    return;

  m_PropertyList = pl;

  if ( m_PropertyList.IsNotNull() )
  {
    this->SetupCallback( m_PropertyList->GetProperty( m_Id ) );

    this->GetTextProperties( pl );
    this->SetText();
  }
  else
  {
    MITK_ERROR << "invalid propList";
  }

}

void QmitkTextOverlay::SetText()
{
  std::string text = "";
  if ( m_PropertyList.IsNull() || !m_PropertyList->GetStringProperty( m_Id, text ) )
  {
    MITK_WARN << "Property " << m_Id << " could not be found";
  }
  m_Widget->setText( text.c_str() );
}

void QmitkTextOverlay::GetTextProperties( mitk::PropertyList::Pointer pl )
{
  if ( pl.IsNull() )
    return;

  mitk::PropertyList::Pointer propertyList = pl;
  QPalette palette = QPalette();
  QFont font = QFont();

  // get the desired color of the textOverlays
  mitk::ColorProperty::Pointer colorProp =
    dynamic_cast<mitk::ColorProperty*>( propertyList->GetProperty( "overlay.color" ) );

  if ( colorProp.IsNull() )
  {
    MITK_ERROR << "creating new colorProperty";
    colorProp = mitk::ColorProperty::New( 127.0, 196.0, 232.0 );
  }

  mitk::Color color = colorProp->GetColor();
  palette.setColor( QPalette::Foreground, QColor( color[0],color[1],color[2],255 ) );
  palette.setColor( QPalette::Window, Qt::transparent);
  m_Widget->setPalette( palette );

  // get the desired opacity of the overlays
  //mitk::FloatProperty::Pointer opacityProperty =
  //  dynamic_cast<mitk::FloatProperty*>( propertyList->GetProperty( "overlay.opacity" ) );

  //if ( opacityProperty.IsNull() )
  //{
  //  m_Widget->setWindowOpacity( 1 );
  //}
  //else
  //{
  //  m_Widget->setWindowOpacity( opacityProperty->GetValue() );
  //}

   //set the desired font-size of the overlays
  int fontSize = 0;
  if ( !propertyList->GetIntProperty( "overlay.fontSize", fontSize ) )
  {
    fontSize = 16;
  }
  font.setPointSize( fontSize );

  bool useKerning = false;
  if ( !propertyList->GetBoolProperty( "overlay.kerning", useKerning ) )
  {
    useKerning = true;
  }
  font.setKerning( useKerning );

  std::string fontFamily = "";
  if ( !propertyList->GetStringProperty( "overlay.fontFamily", fontFamily ) )
  {
    fontFamily = "Verdana";
  }
  font.setFamily(  QString(fontFamily.c_str()) );

  m_Widget->setFont( font );

}

QLabel* QmitkTextOverlay::GetWidget()
{
  return m_Widget;
}

void QmitkTextOverlay::SetupCallback( mitk::BaseProperty::Pointer prop )
{
  if ( prop.IsNotNull() )
  {
    typedef itk::SimpleMemberCommand< QmitkTextOverlay > MemberCommandType;
    MemberCommandType::Pointer propModifiedCommand;
    propModifiedCommand = MemberCommandType::New();
    propModifiedCommand->SetCallbackFunction( this, &QmitkTextOverlay::SetText );
    prop->AddObserver( itk::ModifiedEvent(), propModifiedCommand );
  }
  else
  {
    MITK_ERROR << "invalid property";
  }
}

<commit_msg>FIX (#5038): adding QLabel::repaint to immediately re-render the text when the textProperty has changed<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2010-01-14 14:20:26 +0100 (Thu, 14 Jan 2010) $
Version:   $Revision: 21047 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkTextOverlay.h"

#include "mitkProperties.h"
#include "mitkColorProperty.h"
#include "mitkPropertyList.h"

#include <itkCommand.h>

#include <QLayout>

QmitkTextOverlay::QmitkTextOverlay( const char* id ):
QmitkOverlay(id), m_Widget( NULL )
{
  m_Widget = new QLabel();
  m_Widget->setStyleSheet("");
}

QmitkTextOverlay::~QmitkTextOverlay()
{
  m_Widget = NULL;
}

void QmitkTextOverlay::GenerateData( mitk::PropertyList::Pointer pl )
{
  if ( pl.IsNull() )
    return;

  m_PropertyList = pl;

  if ( m_PropertyList.IsNotNull() )
  {
    this->SetupCallback( m_PropertyList->GetProperty( m_Id ) );

    this->GetTextProperties( pl );
    this->SetText();
  }
  else
  {
    MITK_ERROR << "invalid propList";
  }

}

void QmitkTextOverlay::SetText()
{
  std::string text = "";
  if ( m_PropertyList.IsNull() || !m_PropertyList->GetStringProperty( m_Id, text ) )
  {
    MITK_WARN << "Property " << m_Id << " could not be found";
  }
  m_Widget->setText( text.c_str() );
  m_Widget->repaint();
}

void QmitkTextOverlay::GetTextProperties( mitk::PropertyList::Pointer pl )
{
  if ( pl.IsNull() )
    return;

  mitk::PropertyList::Pointer propertyList = pl;
  QPalette palette = QPalette();
  QFont font = QFont();

  // get the desired color of the textOverlays
  mitk::ColorProperty::Pointer colorProp =
    dynamic_cast<mitk::ColorProperty*>( propertyList->GetProperty( "overlay.color" ) );

  if ( colorProp.IsNull() )
  {
    MITK_ERROR << "creating new colorProperty";
    colorProp = mitk::ColorProperty::New( 127.0, 196.0, 232.0 );
  }

  mitk::Color color = colorProp->GetColor();
  palette.setColor( QPalette::Foreground, QColor( color[0],color[1],color[2],255 ) );
  palette.setColor( QPalette::Window, Qt::transparent);
  m_Widget->setPalette( palette );

  // get the desired opacity of the overlays
  //mitk::FloatProperty::Pointer opacityProperty =
  //  dynamic_cast<mitk::FloatProperty*>( propertyList->GetProperty( "overlay.opacity" ) );

  //if ( opacityProperty.IsNull() )
  //{
  //  m_Widget->setWindowOpacity( 1 );
  //}
  //else
  //{
  //  m_Widget->setWindowOpacity( opacityProperty->GetValue() );
  //}

   //set the desired font-size of the overlays
  int fontSize = 0;
  if ( !propertyList->GetIntProperty( "overlay.fontSize", fontSize ) )
  {
    fontSize = 16;
  }
  font.setPointSize( fontSize );

  bool useKerning = false;
  if ( !propertyList->GetBoolProperty( "overlay.kerning", useKerning ) )
  {
    useKerning = true;
  }
  font.setKerning( useKerning );

  std::string fontFamily = "";
  if ( !propertyList->GetStringProperty( "overlay.fontFamily", fontFamily ) )
  {
    fontFamily = "Verdana";
  }
  font.setFamily(  QString(fontFamily.c_str()) );

  m_Widget->setFont( font );

}

QLabel* QmitkTextOverlay::GetWidget()
{
  return m_Widget;
}

void QmitkTextOverlay::SetupCallback( mitk::BaseProperty::Pointer prop )
{
  if ( prop.IsNotNull() )
  {
    typedef itk::SimpleMemberCommand< QmitkTextOverlay > MemberCommandType;
    MemberCommandType::Pointer propModifiedCommand;
    propModifiedCommand = MemberCommandType::New();
    propModifiedCommand->SetCallbackFunction( this, &QmitkTextOverlay::SetText );
    prop->AddObserver( itk::ModifiedEvent(), propModifiedCommand );
  }
  else
  {
    MITK_ERROR << "invalid property";
  }
}

<|endoftext|>