<commit_before>/*************************************************************************
 *
 *  $RCSfile: index.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2004-08-12 12:02:58 $
 *
 *  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 _INDEX_HXX
#define _INDEX_HXX

#include <limits.h>

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif

#ifndef _RTTI_HXX
#include <tools/rtti.hxx>               // for RTTI of SwIndexReg
#endif
#ifndef _STRING_HXX
#include <tools/string.hxx>             // for xub_StrLen
#endif

#define INVALID_INDEX STRING_NOTFOUND

// Maximale Anzahl von Indizies im IndexArray (zum Abtesten auf Ueberlaeufe)
class SwIndex;
class SwIndexReg;

#ifdef PRODUCT
#define INLINE inline
#else
#define INLINE
#endif

class SwIndex
{
    friend class SwIndexReg;

#ifndef PRODUCT
    static int nSerial;
    int MySerial;
#endif

    xub_StrLen  nIndex;
    SwIndexReg* pArray;
    SwIndex *pNext, *pPrev;

    SwIndex& ChgValue( const SwIndex& rIdx, xub_StrLen nNewValue );
    void Remove();                  // Ausketten

public:
    SwIndex( SwIndexReg * pReg, xub_StrLen nIdx = 0 );
    SwIndex( const SwIndex & );
    SwIndex( const SwIndex &, short nDiff );
    ~SwIndex() { Remove(); }

    INLINE xub_StrLen operator++();
    INLINE xub_StrLen operator--();
#ifndef CFRONT
    INLINE xub_StrLen operator++(int);
    INLINE xub_StrLen operator--(int);
#endif

    INLINE xub_StrLen operator+=( xub_StrLen );
    INLINE xub_StrLen operator-=( xub_StrLen );
    INLINE xub_StrLen operator+=( const SwIndex& );
    INLINE xub_StrLen operator-=( const SwIndex& );

    INLINE BOOL operator<( const SwIndex& ) const;
    INLINE BOOL operator<=( const SwIndex& ) const;
    INLINE BOOL operator>( const SwIndex& ) const;
    INLINE BOOL operator>=( const SwIndex& ) const;
    BOOL operator==( const SwIndex& rSwIndex ) const
    { return (nIndex == rSwIndex.nIndex) &&  (pArray == rSwIndex.pArray); }

    BOOL operator!=( const SwIndex& rSwIndex ) const
    { return (nIndex != rSwIndex.nIndex) ||  (pArray != rSwIndex.pArray); }

    BOOL operator<( xub_StrLen nWert ) const    { return nIndex <  nWert; }
    BOOL operator<=( xub_StrLen nWert ) const   { return nIndex <= nWert; }
    BOOL operator>( xub_StrLen nWert ) const    { return nIndex >  nWert; }
    BOOL operator>=( xub_StrLen nWert ) const   { return nIndex >= nWert; }
    BOOL operator==( xub_StrLen nWert ) const   { return nIndex == nWert; }
    BOOL operator!=( xub_StrLen nWert ) const   { return nIndex != nWert; }

    INLINE SwIndex& operator=( xub_StrLen );
    SwIndex& operator=( const SwIndex & );

    // gebe den Wert vom Index als xub_StrLen zurueck
    xub_StrLen GetIndex() const { return nIndex; }

    // ermoeglicht Zuweisungen ohne Erzeugen eines temporaeren
    // Objektes
    SwIndex &Assign(SwIndexReg *,xub_StrLen);

        // Herausgabe des Pointers auf das IndexArray,
        // (fuers RTTI am SwIndexReg)
    const SwIndexReg* GetIdxReg() const { return pArray; }
};

#undef INLINE

class SwIndexReg
{
    friend class SwIndex;
    const SwIndex *pFirst, *pLast, *pMiddle;

    // ein globales Array, in das Indizies verschoben werden, die mal
    // temporaer "ausgelagert" werden muessen; oder die zum Zeitpunkt des
    // anlegens kein gueltiges Array kennen (SwPaM/SwPosition!)
    friend void _InitCore();
    friend void _FinitCore();
    static SwIndexReg* pEmptyIndexArray;

protected:
    virtual void Update( const SwIndex & aPos, xub_StrLen nLen,
                         BOOL bNegativ = FALSE, BOOL bDelete = FALSE );

    void ChkArr();

    BOOL HasAnyIndex() const { return 0 != pFirst; }

public:
    SwIndexReg();
#ifndef PRODUCT
    ~SwIndexReg();
#endif

    // rtti, abgeleitete moegens gleichtun oder nicht. Wenn sie es gleichtun
    // kann ueber das SwIndexReg typsicher gecastet werden.
    TYPEINFO();

    void SetDefMiddle( const SwIndex* pIdx ) { pMiddle = pIdx; }
    void MoveTo( SwIndexReg& rArr );
};

#ifdef PRODUCT

inline xub_StrLen SwIndex::operator++()
{
    return ChgValue( *this, nIndex+1 ).nIndex;
}
inline xub_StrLen SwIndex::operator--()
{
    return ChgValue( *this, nIndex-1 ).nIndex;
}
#ifndef CFRONT
inline xub_StrLen SwIndex::operator++(int)
{
    xub_StrLen nOldIndex = nIndex;
    ChgValue( *this, nIndex+1 );
    return nOldIndex;
}
inline xub_StrLen SwIndex::operator--(int)
{
    xub_StrLen nOldIndex = nIndex;
    ChgValue( *this, nIndex-1 );
    return nOldIndex;
}
#endif

inline xub_StrLen SwIndex::operator+=( xub_StrLen nWert )
{
    return ChgValue( *this, nIndex + nWert ).nIndex;
}
inline xub_StrLen SwIndex::operator-=( xub_StrLen nWert )
{
    return ChgValue( *this, nIndex - nWert ).nIndex;
}
inline xub_StrLen SwIndex::operator+=( const  SwIndex& rIndex )
{
    return ChgValue( *this, nIndex + rIndex.nIndex ).nIndex;
}
inline xub_StrLen SwIndex::operator-=( const SwIndex& rIndex )
{
    return ChgValue( *this, nIndex - rIndex.nIndex ).nIndex;
}

inline BOOL SwIndex::operator<( const SwIndex& rIndex ) const
{
    return nIndex < rIndex.nIndex;
}
inline BOOL SwIndex::operator<=( const SwIndex& rIndex ) const
{
    return nIndex <= rIndex.nIndex;
}
inline BOOL SwIndex::operator>( const SwIndex& rIndex ) const
{
    return nIndex > rIndex.nIndex;
}
inline BOOL SwIndex::operator>=( const SwIndex& rIndex ) const
{
    return nIndex >= rIndex.nIndex;
}
inline SwIndex& SwIndex::operator=( xub_StrLen nWert )
{
    if( nIndex != nWert )
        ChgValue( *this, nWert );
    return *this;
}

// PRODUCT
#endif

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.4.600); FILE MERGED 2005/09/05 13:36:14 rt 1.4.600.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: index.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 01:58:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _INDEX_HXX
#define _INDEX_HXX

#include <limits.h>

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif

#ifndef _RTTI_HXX
#include <tools/rtti.hxx>               // for RTTI of SwIndexReg
#endif
#ifndef _STRING_HXX
#include <tools/string.hxx>             // for xub_StrLen
#endif

#define INVALID_INDEX STRING_NOTFOUND

// Maximale Anzahl von Indizies im IndexArray (zum Abtesten auf Ueberlaeufe)
class SwIndex;
class SwIndexReg;

#ifdef PRODUCT
#define INLINE inline
#else
#define INLINE
#endif

class SwIndex
{
    friend class SwIndexReg;

#ifndef PRODUCT
    static int nSerial;
    int MySerial;
#endif

    xub_StrLen  nIndex;
    SwIndexReg* pArray;
    SwIndex *pNext, *pPrev;

    SwIndex& ChgValue( const SwIndex& rIdx, xub_StrLen nNewValue );
    void Remove();                  // Ausketten

public:
    SwIndex( SwIndexReg * pReg, xub_StrLen nIdx = 0 );
    SwIndex( const SwIndex & );
    SwIndex( const SwIndex &, short nDiff );
    ~SwIndex() { Remove(); }

    INLINE xub_StrLen operator++();
    INLINE xub_StrLen operator--();
#ifndef CFRONT
    INLINE xub_StrLen operator++(int);
    INLINE xub_StrLen operator--(int);
#endif

    INLINE xub_StrLen operator+=( xub_StrLen );
    INLINE xub_StrLen operator-=( xub_StrLen );
    INLINE xub_StrLen operator+=( const SwIndex& );
    INLINE xub_StrLen operator-=( const SwIndex& );

    INLINE BOOL operator<( const SwIndex& ) const;
    INLINE BOOL operator<=( const SwIndex& ) const;
    INLINE BOOL operator>( const SwIndex& ) const;
    INLINE BOOL operator>=( const SwIndex& ) const;
    BOOL operator==( const SwIndex& rSwIndex ) const
    { return (nIndex == rSwIndex.nIndex) &&  (pArray == rSwIndex.pArray); }

    BOOL operator!=( const SwIndex& rSwIndex ) const
    { return (nIndex != rSwIndex.nIndex) ||  (pArray != rSwIndex.pArray); }

    BOOL operator<( xub_StrLen nWert ) const    { return nIndex <  nWert; }
    BOOL operator<=( xub_StrLen nWert ) const   { return nIndex <= nWert; }
    BOOL operator>( xub_StrLen nWert ) const    { return nIndex >  nWert; }
    BOOL operator>=( xub_StrLen nWert ) const   { return nIndex >= nWert; }
    BOOL operator==( xub_StrLen nWert ) const   { return nIndex == nWert; }
    BOOL operator!=( xub_StrLen nWert ) const   { return nIndex != nWert; }

    INLINE SwIndex& operator=( xub_StrLen );
    SwIndex& operator=( const SwIndex & );

    // gebe den Wert vom Index als xub_StrLen zurueck
    xub_StrLen GetIndex() const { return nIndex; }

    // ermoeglicht Zuweisungen ohne Erzeugen eines temporaeren
    // Objektes
    SwIndex &Assign(SwIndexReg *,xub_StrLen);

        // Herausgabe des Pointers auf das IndexArray,
        // (fuers RTTI am SwIndexReg)
    const SwIndexReg* GetIdxReg() const { return pArray; }
};

#undef INLINE

class SwIndexReg
{
    friend class SwIndex;
    const SwIndex *pFirst, *pLast, *pMiddle;

    // ein globales Array, in das Indizies verschoben werden, die mal
    // temporaer "ausgelagert" werden muessen; oder die zum Zeitpunkt des
    // anlegens kein gueltiges Array kennen (SwPaM/SwPosition!)
    friend void _InitCore();
    friend void _FinitCore();
    static SwIndexReg* pEmptyIndexArray;

protected:
    virtual void Update( const SwIndex & aPos, xub_StrLen nLen,
                         BOOL bNegativ = FALSE, BOOL bDelete = FALSE );

    void ChkArr();

    BOOL HasAnyIndex() const { return 0 != pFirst; }

public:
    SwIndexReg();
#ifndef PRODUCT
    ~SwIndexReg();
#endif

    // rtti, abgeleitete moegens gleichtun oder nicht. Wenn sie es gleichtun
    // kann ueber das SwIndexReg typsicher gecastet werden.
    TYPEINFO();

    void SetDefMiddle( const SwIndex* pIdx ) { pMiddle = pIdx; }
    void MoveTo( SwIndexReg& rArr );
};

#ifdef PRODUCT

inline xub_StrLen SwIndex::operator++()
{
    return ChgValue( *this, nIndex+1 ).nIndex;
}
inline xub_StrLen SwIndex::operator--()
{
    return ChgValue( *this, nIndex-1 ).nIndex;
}
#ifndef CFRONT
inline xub_StrLen SwIndex::operator++(int)
{
    xub_StrLen nOldIndex = nIndex;
    ChgValue( *this, nIndex+1 );
    return nOldIndex;
}
inline xub_StrLen SwIndex::operator--(int)
{
    xub_StrLen nOldIndex = nIndex;
    ChgValue( *this, nIndex-1 );
    return nOldIndex;
}
#endif

inline xub_StrLen SwIndex::operator+=( xub_StrLen nWert )
{
    return ChgValue( *this, nIndex + nWert ).nIndex;
}
inline xub_StrLen SwIndex::operator-=( xub_StrLen nWert )
{
    return ChgValue( *this, nIndex - nWert ).nIndex;
}
inline xub_StrLen SwIndex::operator+=( const  SwIndex& rIndex )
{
    return ChgValue( *this, nIndex + rIndex.nIndex ).nIndex;
}
inline xub_StrLen SwIndex::operator-=( const SwIndex& rIndex )
{
    return ChgValue( *this, nIndex - rIndex.nIndex ).nIndex;
}

inline BOOL SwIndex::operator<( const SwIndex& rIndex ) const
{
    return nIndex < rIndex.nIndex;
}
inline BOOL SwIndex::operator<=( const SwIndex& rIndex ) const
{
    return nIndex <= rIndex.nIndex;
}
inline BOOL SwIndex::operator>( const SwIndex& rIndex ) const
{
    return nIndex > rIndex.nIndex;
}
inline BOOL SwIndex::operator>=( const SwIndex& rIndex ) const
{
    return nIndex >= rIndex.nIndex;
}
inline SwIndex& SwIndex::operator=( xub_StrLen nWert )
{
    if( nIndex != nWert )
        ChgValue( *this, nWert );
    return *this;
}

// PRODUCT
#endif

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

# include  "netlist.h"
# include  "netmisc.h"
# include  <assert.h>

/*
 * Search for the hierarchical name.
 */
NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
                       pform_name_t path,
		       NetNet*&net,
		       const NetExpr*&par,
		       NetEvent*&eve,
		       const NetExpr*&ex1, const NetExpr*&ex2)
{
      assert(scope);

	/* Get the tail name of the object we are looking for. */
      perm_string key = peek_tail_name(path);
      path.pop_back();

	/* Initialize output argument to cleared. */
      net = 0;
      par = 0;
      eve = 0;

	/* If the path has a scope part, then search for the specified
	   scope that we are supposed to search. */
      if (! path.empty()) {
	    list<hname_t> path_list = eval_scope_path(des, scope, path);
	    assert(path_list.size() <= path.size());

	      // If eval_scope_path returns a short list, then some
	      // part of the scope was not found. Abort.
	    if (path_list.size() < path.size())
		  return 0;

	    scope = des->find_scope(scope, path_list);

            if (scope && scope->is_auto() && li) {
                  cerr << li->get_fileline() << ": error: Hierarchical "
                        "reference to automatically allocated item "
                        "`" << key << "' in path `" << path << "'" << endl;
            	  des->errors += 1;
            }
      }

      while (scope) {
	    if ( (net = scope->find_signal(key)) )
		  return scope;

	    if ( (eve = scope->find_event(key)) )
		  return scope;

	    if ( (par = scope->get_parameter(key, ex1, ex2)) )
		  return scope;

	    if (scope->type() == NetScope::MODULE)
		  scope = 0;
	    else
		  scope = scope->parent();
      }

      return 0;
}
<commit_msg>Do not search up for a symbol if a hierarchical path was given.<commit_after>/*
 * Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

# include  "netlist.h"
# include  "netmisc.h"
# include  <assert.h>

/*
 * Search for the hierarchical name.
 */
NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
                       pform_name_t path,
		       NetNet*&net,
		       const NetExpr*&par,
		       NetEvent*&eve,
		       const NetExpr*&ex1, const NetExpr*&ex2)
{
      assert(scope);
      bool hier_path = false;

	/* Get the tail name of the object we are looking for. */
      perm_string key = peek_tail_name(path);
      path.pop_back();

	/* Initialize output argument to cleared. */
      net = 0;
      par = 0;
      eve = 0;

	/* If the path has a scope part, then search for the specified
	   scope that we are supposed to search. */
      if (! path.empty()) {
	    list<hname_t> path_list = eval_scope_path(des, scope, path);
	    assert(path_list.size() <= path.size());

	      // If eval_scope_path returns a short list, then some
	      // part of the scope was not found. Abort.
	    if (path_list.size() < path.size())
		  return 0;

	    scope = des->find_scope(scope, path_list);

            if (scope && scope->is_auto() && li) {
                  cerr << li->get_fileline() << ": error: Hierarchical "
                        "reference to automatically allocated item "
                        "`" << key << "' in path `" << path << "'" << endl;
            	  des->errors += 1;
            }

	    hier_path = true;
      }

      while (scope) {
	    if ( (net = scope->find_signal(key)) )
		  return scope;

	    if ( (eve = scope->find_event(key)) )
		  return scope;

	    if ( (par = scope->get_parameter(key, ex1, ex2)) )
		  return scope;

	      /* We can't look up if we are at the enclosing module scope
	       * or if a hierarchical path was given. */
	    if ((scope->type() == NetScope::MODULE) || hier_path)
		  scope = 0;
	    else
		  scope = scope->parent();
      }

      return 0;
}
<|endoftext|>


<commit_before>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.
#include "Addressing.hpp"
#include "Communicator.hpp"
#include "Collective.hpp"
#include "Cache.hpp"

namespace Grappa {

/// Initialize an array of elements of generic type with a given value.
///
/// This version sends a large number of active messages, the same way as the Incoherent
/// releaser, to set each part of a global array. In theory, this version should be able
/// to be called from multiple locations at the same time (to initialize different regions of global memory).
///
/// @param base Base address of the array to be set.
/// @param value Value to set every element of array to (will be copied to all the nodes)
/// @param count Number of elements to set, starting at the base address.
template< typename T, typename S >
void memset(GlobalAddress<T> base, S value, size_t count) {
  on_all_cores([base,count,value]{
    T * local_base = base.localize();
    T * local_end = (base+count).localize();
    for (size_t i=0; i<local_end-local_base; i++) {
      local_base[i] = value;
    }
  });
}

template< typename T >
void memcpy(GlobalAddress<T> dst, GlobalAddress<T> src, size_t nelem) {
  on_all_cores([dst,src,nelem]{
    typedef typename Incoherent<T>::WO Writeback;

    T * local_base = src.localize(), * local_end = (src+nelem).localize();
    const size_t nblock = block_size / sizeof(T);
    const size_t nlocalblocks = (local_end-local_base)/nblock;
    Writeback ** putters = new Writeback*[nlocalblocks];
    for (size_t i=0; i < nlocalblocks; i++) {
      size_t j = make_linear(local_base+(i*nblock))-src;
      size_t n = (i < nlocalblocks-1) ? nblock : (local_end-local_base)-(i*nblock);

      // initialize WO cache to read from this block locally and write to corresponding block in dest
      putters[i] = new Writeback(dst+j, n, local_base+(i*nblock));
      putters[i]->start_release();
    }
    for (size_t i=0; i < nlocalblocks; i++) { delete putters[i]; }
    delete [] putters;
  });
}

template< typename T >
void prefix_sum(GlobalAddress<T> array, size_t nelem) {

}

} // namespace Grappa

/// Legacy: @see { Grappa::memset() }
template< typename T , typename S >
void Grappa_memset(GlobalAddress<T> request_address, S value, size_t count) {
  Grappa::memset(request_address, value, count);
}

/// Legacy: @see { Grappa::memset() }
template< typename T, typename S >
void Grappa_memset_local(GlobalAddress<T> base, S value, size_t count) {
  Grappa::memset(base, value, count);
}

template< typename T >
void Grappa_memcpy(GlobalAddress<T> dst, GlobalAddress<T> src, size_t nelem) {
  Grappa::memcpy(dst,src,nelem);
}
<commit_msg>Do memset in message handler to avoid deadlock case.<commit_after>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.
#include "Addressing.hpp"
#include "Communicator.hpp"
#include "Collective.hpp"
#include "Cache.hpp"

namespace Grappa {

/// Initialize an array of elements of generic type with a given value.
///
/// This version sends a large number of active messages, the same way as the Incoherent
/// releaser, to set each part of a global array. In theory, this version should be able
/// to be called from multiple locations at the same time (to initialize different regions of global memory).
///
/// @param base Base address of the array to be set.
/// @param value Value to set every element of array to (will be copied to all the nodes)
/// @param count Number of elements to set, starting at the base address.
template< typename T, typename S >
void memset(GlobalAddress<T> base, S value, size_t count) {
  call_on_all_cores([base,count,value]{
    T * local_base = base.localize();
    T * local_end = (base+count).localize();
    for (size_t i=0; i<local_end-local_base; i++) {
      local_base[i] = value;
    }
  });
}

template< typename T >
void memcpy(GlobalAddress<T> dst, GlobalAddress<T> src, size_t nelem) {
  on_all_cores([dst,src,nelem]{
    typedef typename Incoherent<T>::WO Writeback;

    T * local_base = src.localize(), * local_end = (src+nelem).localize();
    const size_t nblock = block_size / sizeof(T);
    const size_t nlocalblocks = (local_end-local_base)/nblock;
    Writeback ** putters = new Writeback*[nlocalblocks];
    for (size_t i=0; i < nlocalblocks; i++) {
      size_t j = make_linear(local_base+(i*nblock))-src;
      size_t n = (i < nlocalblocks-1) ? nblock : (local_end-local_base)-(i*nblock);

      // initialize WO cache to read from this block locally and write to corresponding block in dest
      putters[i] = new Writeback(dst+j, n, local_base+(i*nblock));
      putters[i]->start_release();
    }
    for (size_t i=0; i < nlocalblocks; i++) { delete putters[i]; }
    delete [] putters;
  });
}

template< typename T >
void prefix_sum(GlobalAddress<T> array, size_t nelem) {

}

} // namespace Grappa

/// Legacy: @see { Grappa::memset() }
template< typename T , typename S >
void Grappa_memset(GlobalAddress<T> request_address, S value, size_t count) {
  Grappa::memset(request_address, value, count);
}

/// Legacy: @see { Grappa::memset() }
template< typename T, typename S >
void Grappa_memset_local(GlobalAddress<T> base, S value, size_t count) {
  Grappa::memset(base, value, count);
}

template< typename T >
void Grappa_memcpy(GlobalAddress<T> dst, GlobalAddress<T> src, size_t nelem) {
  Grappa::memcpy(dst,src,nelem);
}
<|endoftext|>


<commit_before>/* $Id$ $Revision$ */
/* vim:set shiftwidth=4 ts=8: */

/**********************************************************
*      This software is part of the graphviz package      *
*                http://www.graphviz.org/                 *
*                                                         *
*            Copyright (c) 1994-2004 AT&T Corp.           *
*                and is licensed under the                *
*            Common Public License, Version 1.0           *
*                      by AT&T Corp.                      *
*                                                         *
*        Information and Software Systems Research        *
*              AT&T Research, Florham Park NJ             *
**********************************************************/

#define BUILTINS
#include "gvc.h"

GVC_t *gvc;

static void gvinit()
{
    gvc = gvContext();
}

Agraph_t *digraph(char *name)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agopen(name, AGDIGRAPH);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *digraphstrict(char *name)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agopen(name, AGDIGRAPHSTRICT);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *graph(char *name)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agopen(name, AGRAPH);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *graphstrict(char *name)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agopen(name, AGRAPHSTRICT);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *stringgraph(char *graphstring)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agmemread(graphstring);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *readgraph(char *filename)
{
    FILE *f;
    Agraph_t *g;

    if (!gvc)
	gvinit();
    f = fopen(filename, "r");
    g = agread(f);
    fclose(f);
    GD_drawing(g) = NULL;
    return g;
}

/* create a subgraph of an existing graph */
Agraph_t *graph(Agraph_t *g, char *name)
{
    if (!gvc)
	return NULL;
    return agsubg(g, name);
}

Agnode_t *node(Agraph_t *g, char *name)
{
    if (!gvc)
	return NULL;
    return agnode(g, name);
}

Agedge_t *edge(Agnode_t *t, Agnode_t *h)
{
    return agedge(t->graph, t, h);
}

char *set(Agraph_t *g, char *attr, char *val)
{
    Agsym_t *a;

    a = agfindattr(g->root, attr);
    if (val) {
	if (!a)
	    a = agraphattr(g->root, attr, "");
	agxset(g, a->index, val);
    }
    else {
	if (a)
	    val = agxget(g, a->index);
	else
	    val = "";
    }
    return val;
}

char *set(Agraph_t *g, char *attr)
{
    Agsym_t *a;

    a = agfindattr(g->root, attr);
    if (a)
	return agxget(g, a->index);
    else
	return "";
}

char *set(Agnode_t *n, char *attr, char *val)
{
    Agraph_t *g;
    Agsym_t *a;

    g = n->graph->root;
    a = agfindattr(g->proto->n, attr);
    if (val) {
        if (!a)
            a = agnodeattr(g, attr, "");
        agxset(n, a->index, val);
    }
    else {
        if (a)
            val = agxget(n, a->index);
        else
            val = "";
    }
    return val;
}

char *set(Agnode_t *n, char *attr)
{
    Agsym_t *a;

    a = agfindattr(n->graph->root->proto->n, attr);
    if (a)
        return agxget(n, a->index);
    else
        return "";
}

char *set(Agedge_t *e, char *attr, char *val)
{
    Agraph_t *g;
    Agsym_t *a;

    g = e->tail->graph->root;
    a = agfindattr(g->proto->e, attr);
    if (val) {
        if (!a)
            a = agedgeattr(g, attr, "");
        agxset(e, a->index, val);
    }
    else {
        if (a)
            val = agxget(e, a->index);
        else
            val = "";
    }
    return val;
}

char *set(Agedge_t *e, char *attr)
{
    Agsym_t *a;

    a = agfindattr(e->tail->graph->root->proto->e, attr);
    if (a)
        return agxget(e, a->index);
    else
        return "";
}

Agnode_t *headof(Agedge_t *e)
{
    if (!e)
	return NULL;
    return e->head;
}

Agnode_t *tailof(Agedge_t *e)
{
    if (!e)
	return NULL;
    return e->tail;
}

Agraph_t *graphof(Agraph_t *g)
{
    if (!g || g == g->root)
	return NULL;
    return g->root;
}

Agraph_t *graphof(Agedge_t *e)
{
    if (!e)
	return NULL;
    return e->tail->graph;
}

Agraph_t *graphof(Agnode_t *n)
{
    if (!n)
	return NULL;
    return n->graph;
}

Agraph_t *rootof(Agraph_t *g)
{
    if (!g)
	return NULL;
    return g->root;
}

Agraph_t *firstsubg(Agraph_t *g)
{
    Agraph_t *mg;
    Agnode_t *n;
    Agedge_t *e;

    if (!g)
	return NULL;
    n = g->meta_node;
    if (!n)
	return NULL;
    mg = n->graph;
    if (!mg)
	return NULL;
    e = agfstout(mg, n);
    if (!e)
	return NULL;
    return agusergraph(e->head);
}

Agraph_t *nextsubg(Agraph_t *g, Agraph_t *sg)
{
    Agraph_t *mg;
    Agnode_t *ng, *nsg;
    Agedge_t *e;

    if (!g || !sg)
	return NULL;
    ng = g->meta_node;
    nsg = sg->meta_node;
    if (!ng || !nsg)
	return NULL;
    mg = ng->graph;
    if (!mg)
	return NULL;
    e = agfindedge(mg, ng, nsg);
    if (!e)
	return NULL;
    e = agnxtout(mg, e);
    if (!e)
	return NULL;
    return agusergraph(e->head);
}

Agraph_t *firstsupg(Agraph_t *g)
{
    Agraph_t *mg;
    Agnode_t *n;
    Agedge_t *e;

    if (!g)
	return NULL;
    n = g->meta_node;
    if (!n)
	return NULL;
    mg = n->graph;
    if (!mg)
	return NULL;
    e = agfstin(mg, n);
    if (!e)
	return NULL;
    return agusergraph(e->tail);
}

Agraph_t *nextsupg(Agraph_t *g, Agraph_t *sg)
{
    Agraph_t *mg;
    Agnode_t *ng, *nsg;
    Agedge_t *e;

    if (!g || !sg)
	return NULL;
    ng = g->meta_node;
    nsg = sg->meta_node;
    if (!ng || !nsg)
	return NULL;
    mg = ng->graph;
    if (!mg)
	return NULL;
    e = agfindedge(mg, nsg, ng);
    if (!e)
	return NULL;
    e = agnxtin(mg, e);
    if (!e)
	return NULL;
    return agusergraph(e->tail);
}

Agedge_t *firstout(Agraph_t *g)
{
    Agnode_t *n;

    if (!g)
	return NULL;
    n = agfstnode(g);
    if (!n)
	return NULL;
    return agfstout(g, n);
}

Agedge_t *nextout(Agraph_t *g, Agedge_t *e)
{
    Agnode_t *n;

    if (!g || !e)
	return NULL;
    e = agnxtout(g, e);
    if (e)
	return (e);
    n = agnxtnode(g, n);
    if (!n)
	return NULL;
    return agfstout(g, n);
}

Agedge_t *firstout(Agedge_t *e)
{ return NULL; }

Agedge_t *nextout(Agedge_t *e, Agedge_t *ee)
{ return NULL; }

Agedge_t *firstout(Agnode_t *n)
{
    if (!n)
	return NULL;
    return agfstout(n->graph, n);
}

Agedge_t *nextout(Agnode_t *n, Agedge_t *e)
{
    if (!n || !e)
	return NULL;
    return (agnxtout(n->graph, e));
}

Agedge_t *firstin(Agraph_t *g)
{
    Agnode_t *n;

    if (!g)
	return NULL;
    n = agfstnode(g);
    if (!n)
	return NULL;
    return(agfstin(g, n));
}

Agedge_t *nextin(Agraph_t *g, Agedge_t *e)
{
    Agnode_t *n;

    if (!g || !e)
	return NULL;
    e = agnxtin(g, e);
    if (e)
	return (e);
    n = agnxtnode(g, n);
    if (!n)
	return NULL;
    return (agfstin(g, n));
}

Agedge_t *firstin(Agedge_t *e)
{ return NULL; }

Agedge_t *nextin(Agedge_t *e, Agedge_t *ee)
{ return NULL; }

Agedge_t *firstin(Agnode_t *n)
{
    if (!n)
	return NULL;
    return(agfstin(n->graph, n));
}

Agedge_t *nextin(Agnode_t *n, Agedge_t *e)
{
    if (!n || !e)
	return NULL;
    return (agnxtin(n->graph, e));
}

Agnode_t *first(Agraph_t *g)
{
    return (agfstnode(g));
}

Agnode_t *next(Agraph_t *g, Agnode_t *n)
{
    return (agnxtnode(g, n));
}

Agnode_t *first(Agedge_t *e)
{
    if (!e)
	return NULL;
    return (e->tail);
}

Agnode_t *next(Agedge_t *e, Agnode_t *n)
{
    if (!e || n != e->tail)
	return NULL;
    return (e->head);
}

Agnode_t *first(Agnode_t *n)
{ return NULL; }

Agnode_t *next(Agnode_t *n, Agnode_t *nn)
{ return NULL; }

void rm(Agraph_t *g)
{
    Agedge_t *e;

    if (g->meta_node) {
	for (e = agfstout(g->meta_node->graph, g->meta_node); e;
			e = agnxtout(g->meta_node->graph, e)) {
	    rm(agusergraph(e->head));
        }
        if (g == g->root) {
            agclose(g);
        } else {
            agdelete(g->meta_node->graph, g->meta_node);
        }
    } else {
        fprintf(stderr, "subgraph has no meta_node\n");
    }
}

void rm(Agnode_t *n)
{
    agdelete(n->graph, n);
}

void rm(Agedge_t *e)
{
    agdelete(e->head->graph->root, e);
}

void layout(Agraph_t *g, char *engine)
{
    int err;

    err = gvLayout(gvc, g, engine);
}

void writegraph(Agraph_t *g, char *filename, char *format)
{
    int err;

    err = gvRenderFilename(gvc, g, format, filename);
}
<commit_msg>swig'ify the new iterator functions<commit_after>/* $Id$ $Revision$ */
/* vim:set shiftwidth=4 ts=8: */

/**********************************************************
*      This software is part of the graphviz package      *
*                http://www.graphviz.org/                 *
*                                                         *
*            Copyright (c) 1994-2004 AT&T Corp.           *
*                and is licensed under the                *
*            Common Public License, Version 1.0           *
*                      by AT&T Corp.                      *
*                                                         *
*        Information and Software Systems Research        *
*              AT&T Research, Florham Park NJ             *
**********************************************************/

#define BUILTINS
#include "gvc.h"

GVC_t *gvc;

static void gvinit()
{
    gvc = gvContext();
}

Agraph_t *digraph(char *name)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agopen(name, AGDIGRAPH);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *digraphstrict(char *name)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agopen(name, AGDIGRAPHSTRICT);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *graph(char *name)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agopen(name, AGRAPH);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *graphstrict(char *name)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agopen(name, AGRAPHSTRICT);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *stringgraph(char *graphstring)
{
    Agraph_t *g;

    if (!gvc)
	gvinit();
    g = agmemread(graphstring);
    GD_drawing(g) = NULL;
    return g;
}

Agraph_t *readgraph(char *filename)
{
    FILE *f;
    Agraph_t *g;

    if (!gvc)
	gvinit();
    f = fopen(filename, "r");
    g = agread(f);
    fclose(f);
    GD_drawing(g) = NULL;
    return g;
}

/* create a subgraph of an existing graph */
Agraph_t *graph(Agraph_t *g, char *name)
{
    if (!gvc)
	return NULL;
    return agsubg(g, name);
}

Agnode_t *node(Agraph_t *g, char *name)
{
    if (!gvc)
	return NULL;
    return agnode(g, name);
}

Agedge_t *edge(Agnode_t *t, Agnode_t *h)
{
    return agedge(t->graph, t, h);
}

char *set(Agraph_t *g, char *attr, char *val)
{
    Agsym_t *a;

    a = agfindattr(g->root, attr);
    if (val) {
	if (!a)
	    a = agraphattr(g->root, attr, "");
	agxset(g, a->index, val);
    }
    else {
	if (a)
	    val = agxget(g, a->index);
	else
	    val = "";
    }
    return val;
}

char *set(Agraph_t *g, char *attr)
{
    Agsym_t *a;

    a = agfindattr(g->root, attr);
    if (a)
	return agxget(g, a->index);
    else
	return "";
}

char *set(Agnode_t *n, char *attr, char *val)
{
    Agraph_t *g;
    Agsym_t *a;

    g = n->graph->root;
    a = agfindattr(g->proto->n, attr);
    if (val) {
        if (!a)
            a = agnodeattr(g, attr, "");
        agxset(n, a->index, val);
    }
    else {
        if (a)
            val = agxget(n, a->index);
        else
            val = "";
    }
    return val;
}

char *set(Agnode_t *n, char *attr)
{
    Agsym_t *a;

    a = agfindattr(n->graph->root->proto->n, attr);
    if (a)
        return agxget(n, a->index);
    else
        return "";
}

char *set(Agedge_t *e, char *attr, char *val)
{
    Agraph_t *g;
    Agsym_t *a;

    g = e->tail->graph->root;
    a = agfindattr(g->proto->e, attr);
    if (val) {
        if (!a)
            a = agedgeattr(g, attr, "");
        agxset(e, a->index, val);
    }
    else {
        if (a)
            val = agxget(e, a->index);
        else
            val = "";
    }
    return val;
}

char *set(Agedge_t *e, char *attr)
{
    Agsym_t *a;

    a = agfindattr(e->tail->graph->root->proto->e, attr);
    if (a)
        return agxget(e, a->index);
    else
        return "";
}

Agnode_t *headof(Agedge_t *e)
{
    if (!e)
	return NULL;
    return e->head;
}

Agnode_t *tailof(Agedge_t *e)
{
    if (!e)
	return NULL;
    return e->tail;
}

Agraph_t *graphof(Agraph_t *g)
{
    if (!g || g == g->root)
	return NULL;
    return g->root;
}

Agraph_t *graphof(Agedge_t *e)
{
    if (!e)
	return NULL;
    return e->tail->graph;
}

Agraph_t *graphof(Agnode_t *n)
{
    if (!n)
	return NULL;
    return n->graph;
}

Agraph_t *rootof(Agraph_t *g)
{
    if (!g)
	return NULL;
    return g->root;
}

Agraph_t *firstsubg(Agraph_t *g)
{
    Agraph_t *mg;
    Agnode_t *n;
    Agedge_t *e;

    if (!g)
	return NULL;
    n = g->meta_node;
    if (!n)
	return NULL;
    mg = n->graph;
    if (!mg)
	return NULL;
    e = agfstout(mg, n);
    if (!e)
	return NULL;
    return agusergraph(e->head);
}

Agraph_t *nextsubg(Agraph_t *g, Agraph_t *sg)
{
    Agraph_t *mg;
    Agnode_t *ng, *nsg;
    Agedge_t *e;

    if (!g || !sg)
	return NULL;
    ng = g->meta_node;
    nsg = sg->meta_node;
    if (!ng || !nsg)
	return NULL;
    mg = ng->graph;
    if (!mg)
	return NULL;
    e = agfindedge(mg, ng, nsg);
    if (!e)
	return NULL;
    e = agnxtout(mg, e);
    if (!e)
	return NULL;
    return agusergraph(e->head);
}

Agraph_t *firstsupg(Agraph_t *g)
{
    Agraph_t *mg;
    Agnode_t *n;
    Agedge_t *e;

    if (!g)
	return NULL;
    n = g->meta_node;
    if (!n)
	return NULL;
    mg = n->graph;
    if (!mg)
	return NULL;
    e = agfstin(mg, n);
    if (!e)
	return NULL;
    return agusergraph(e->tail);
}

Agraph_t *nextsupg(Agraph_t *g, Agraph_t *sg)
{
    Agraph_t *mg;
    Agnode_t *ng, *nsg;
    Agedge_t *e;

    if (!g || !sg)
	return NULL;
    ng = g->meta_node;
    nsg = sg->meta_node;
    if (!ng || !nsg)
	return NULL;
    mg = ng->graph;
    if (!mg)
	return NULL;
    e = agfindedge(mg, nsg, ng);
    if (!e)
	return NULL;
    e = agnxtin(mg, e);
    if (!e)
	return NULL;
    return agusergraph(e->tail);
}

Agedge_t *firstout(Agraph_t *g)
{
    Agnode_t *n;

    if (!g)
	return NULL;
    n = agfstnode(g);
    if (!n)
	return NULL;
    return agfstout(g, n);
}

Agedge_t *nextout(Agraph_t *g, Agedge_t *e)
{
    Agnode_t *n;

    if (!g || !e)
	return NULL;
    e = agnxtout(g, e);
    if (e)
	return (e);
    n = agnxtnode(g, n);
    if (!n)
	return NULL;
    return agfstout(g, n);
}

Agedge_t *firstout(Agedge_t *e)
{
    return NULL;
}

Agedge_t *nextout(Agedge_t *e, Agedge_t *ee)
{
    return NULL;
}

Agedge_t *firstout(Agnode_t *n)
{
    if (!n)
	return NULL;
    return agfstout(n->graph, n);
}

Agedge_t *nextout(Agnode_t *n, Agedge_t *e)
{
    if (!n || !e)
	return NULL;
    return (agnxtout(n->graph, e));
}

Agedge_t *firstin(Agraph_t *g)
{
    Agnode_t *n;

    if (!g)
	return NULL;
    n = agfstnode(g);
    if (!n)
	return NULL;
    return(agfstin(g, n));
}

Agedge_t *nextin(Agraph_t *g, Agedge_t *e)
{
    Agnode_t *n;

    if (!g || !e)
	return NULL;
    e = agnxtin(g, e);
    if (e)
	return (e);
    n = agnxtnode(g, n);
    if (!n)
	return NULL;
    return (agfstin(g, n));
}

Agedge_t *firstin(Agedge_t *e)
{
    return NULL;
}

Agedge_t *nextin(Agedge_t *e, Agedge_t *ee)
{
    return NULL;
}

Agedge_t *firstin(Agnode_t *n)
{
    if (!n)
	return NULL;
    return(agfstin(n->graph, n));
}

Agedge_t *nextin(Agnode_t *n, Agedge_t *e)
{
    if (!n || !e)
	return NULL;
    return (agnxtin(n->graph, e));
}

Agnode_t *first(Agraph_t *g)
{
    return (agfstnode(g));
}

Agnode_t *next(Agraph_t *g, Agnode_t *n)
{
    return (agnxtnode(g, n));
}

Agnode_t *first(Agedge_t *e)
{
    if (!e)
	return NULL;
    return (e->tail);
}

Agnode_t *next(Agedge_t *e, Agnode_t *n)
{
    if (!e || n != e->tail)
	return NULL;
    return (e->head);
}

Agnode_t *first(Agnode_t *n)
{
    return NULL;
}

Agnode_t *next(Agnode_t *n, Agnode_t *nn)
{
    return NULL;
}

void rm(Agraph_t *g)
{
    Agedge_t *e;

    if (g->meta_node) {
	for (e = agfstout(g->meta_node->graph, g->meta_node); e;
			e = agnxtout(g->meta_node->graph, e)) {
	    rm(agusergraph(e->head));
        }
        if (g == g->root) {
            agclose(g);
        } else {
            agdelete(g->meta_node->graph, g->meta_node);
        }
    } else {
        fprintf(stderr, "subgraph has no meta_node\n");
    }
}

void rm(Agnode_t *n)
{
    agdelete(n->graph, n);
}

void rm(Agedge_t *e)
{
    agdelete(e->head->graph->root, e);
}

void layout(Agraph_t *g, char *engine)
{
    int err;

    err = gvLayout(gvc, g, engine);
}

void writegraph(Agraph_t *g, char *filename, char *format)
{
    int err;

    err = gvRenderFilename(gvc, g, format, filename);
}
<|endoftext|>


<commit_before>#ifndef ABSTRACT_EVENT__HPP
#define ABSTRACT_EVENT__HPP

#include "ConnectionList.hpp"

class AbstractEvent
{
protected:
	AbstractEvent() {}
	~AbstractEvent() {}
public:
	size_t connectionCount() const
	{
		return connections_.connectionCount();
	}
	size_t connectionCount(AbstractDelegate const & deleg) const
	{
		return connections_.connectionCount(deleg);
	}

	template<class T, class Y> size_t connectionCount(T * obj, Y pMemberFunc) const
	{
		return connectionCount(AbstractDelegate(obj, pMemberFunc));
	}

	bool hasConnections() const
	{
		return connections_.hasConnections();
	}
	bool hasConnections(AbstractDelegate const & deleg) const
	{
		return connections_.hasConnections(deleg);
	}

	template<class T, class Y> bool hasConnections(T * obj, Y pMemberFunc) const
	{
		return hasConnections(AbstractDelegate(obj, pMemberFunc));
	}

	size_t disconnectAll()
	{
		return connections_.disconnectAll();
	}
	size_t disconnectAll(AbstractDelegate const & deleg)
	{
		return connections_.disconnectAll(deleg);
	}

	inline bool disconnectOne(AbstractDelegate const & deleg);

	template<class T, class Y> size_t disconnectAll(T * obj, Y pMemberFunc)
	{
		return disconnectAll(AbstractDelegate(obj, pMemberFunc));
	}
	template<class T, class Y> bool disconnectOne(T * obj, Y pMemberFunc)
	{
		return disconnectOne(AbstractDelegate(obj, pMemberFunc));
	}
protected:
	typedef ConnectionList::ConnectionsVector ConnectionsVector;

	class FireLock
	{
	public:
		FireLock(AbstractEvent const * e)
			: connections_(e->connections())
			, locker_(e->connectionsLock())
		{}

		ConnectionsVector const & connections() const
		{
			return connections_;
		}
	private:
		ConnectionsVector connections_;
		ThreadDataLocker locker_;
	};

	void addConnection(ConnectionList * tracker, AbstractDelegate const & deleg, ExtraDelegateData * data)
	{
		connections_.connect(tracker, deleg, data);
	}
private:
	ConnectionList connections_;

	ThreadDataRef & connectionsLock() const { return connections_.lock_; }
	ConnectionsVector const & connections() const { return connections_.connections_; }
};

class AbstractEventRef
{
public:
	AbstractEventRef(AbstractEvent * ev)
		: event_(ev)
	{}
	AbstractEventRef(AbstractEventRef const & other)
		: event_(other.event_)
	{}

	bool operator==(AbstractEventRef const & other) const
	{
		return event_ == other.event_;
	}

	bool operator!=(AbstractEventRef const & other) const
	{
		return event_ != other.event_;
	}

	size_t connectionCount() const
	{
		return event_->connectionCount();
	}
	size_t connectionCount(AbstractDelegate const & deleg) const
	{
		return event_->connectionCount(deleg);
	}
	template<class T, class Y> size_t connectionCount(T * reciever, Y pMemberFunc) const
	{
		return event_->connectionCount(reciever, pMemberFunc);
	}

	bool hasConnections() const
	{
		return event_->hasConnections();
	}
	bool hasConnections(AbstractDelegate const & deleg) const
	{
		return event_->hasConnections(deleg);
	}
	template<class T, class Y> bool hasConnections(T * reciever, Y pMemberFunc) const
	{
		return event_->hasConnections(reciever, pMemberFunc);
	}

	size_t disconnectAll()
	{
		return event_->disconnectAll();
	}
	size_t disconnectAll(AbstractDelegate const & deleg)
	{
		return event_->disconnectAll(deleg);
	}
	template<class T, class Y> size_t disconnectAll(T * reciever, Y pMemberFunc)
	{
		return event_->disconnectAll(reciever, pMemberFunc);
	}
	bool disconnectOne(AbstractDelegate const & deleg)
	{
		return event_->disconnectOne(deleg);
	}
	template<class T, class Y> bool disconnectOne(T * reciever, Y pMemberFunc)
	{
		return event_->disconnectOne(reciever, pMemberFunc);
	}
protected:
	AbstractEvent * senderEvent() const { return event_; }
private:
	AbstractEvent * event_;
};

inline bool AbstractEvent::disconnectOne(AbstractDelegate const & deleg)
{
	return connections_.disconnectOne(deleg);
}

#endif //ABSTRACT_EVENT__HPP<commit_msg>*: AbstractEvent::connections_ renamed into AbstractEvent::connectionList_<commit_after>#ifndef ABSTRACT_EVENT__HPP
#define ABSTRACT_EVENT__HPP

#include "ConnectionList.hpp"

class AbstractEvent
{
protected:
	AbstractEvent() {}
	~AbstractEvent() {}
public:
	size_t connectionCount() const
	{
		return connectionList_.connectionCount();
	}
	size_t connectionCount(AbstractDelegate const & deleg) const
	{
		return connectionList_.connectionCount(deleg);
	}

	template<class T, class Y> size_t connectionCount(T * obj, Y pMemberFunc) const
	{
		return connectionCount(AbstractDelegate(obj, pMemberFunc));
	}

	bool hasConnections() const
	{
		return connectionList_.hasConnections();
	}
	bool hasConnections(AbstractDelegate const & deleg) const
	{
		return connectionList_.hasConnections(deleg);
	}

	template<class T, class Y> bool hasConnections(T * obj, Y pMemberFunc) const
	{
		return hasConnections(AbstractDelegate(obj, pMemberFunc));
	}

	size_t disconnectAll()
	{
		return connectionList_.disconnectAll();
	}
	size_t disconnectAll(AbstractDelegate const & deleg)
	{
		return connectionList_.disconnectAll(deleg);
	}

	inline bool disconnectOne(AbstractDelegate const & deleg);

	template<class T, class Y> size_t disconnectAll(T * obj, Y pMemberFunc)
	{
		return disconnectAll(AbstractDelegate(obj, pMemberFunc));
	}
	template<class T, class Y> bool disconnectOne(T * obj, Y pMemberFunc)
	{
		return disconnectOne(AbstractDelegate(obj, pMemberFunc));
	}
protected:
	typedef ConnectionList::ConnectionsVector ConnectionsVector;

	class FireLock
	{
	public:
		FireLock(AbstractEvent const * e)
			: connections_(e->connections())
			, locker_(e->connectionsLock())
		{}

		ConnectionsVector const & connections() const
		{
			return connections_;
		}
	private:
		ConnectionsVector connections_;
		ThreadDataLocker locker_;
	};

	void addConnection(ConnectionList * tracker, AbstractDelegate const & deleg, ExtraDelegateData * data)
	{
		connectionList_.connect(tracker, deleg, data);
	}
private:
	ConnectionList connectionList_;

	ThreadDataRef & connectionsLock() const { return connectionList_.lock_; }
	ConnectionsVector const & connections() const { return connectionList_.connections_; }
};

class AbstractEventRef
{
public:
	AbstractEventRef(AbstractEvent * ev)
		: event_(ev)
	{}
	AbstractEventRef(AbstractEventRef const & other)
		: event_(other.event_)
	{}

	bool operator==(AbstractEventRef const & other) const
	{
		return event_ == other.event_;
	}

	bool operator!=(AbstractEventRef const & other) const
	{
		return event_ != other.event_;
	}

	size_t connectionCount() const
	{
		return event_->connectionCount();
	}
	size_t connectionCount(AbstractDelegate const & deleg) const
	{
		return event_->connectionCount(deleg);
	}
	template<class T, class Y> size_t connectionCount(T * reciever, Y pMemberFunc) const
	{
		return event_->connectionCount(reciever, pMemberFunc);
	}

	bool hasConnections() const
	{
		return event_->hasConnections();
	}
	bool hasConnections(AbstractDelegate const & deleg) const
	{
		return event_->hasConnections(deleg);
	}
	template<class T, class Y> bool hasConnections(T * reciever, Y pMemberFunc) const
	{
		return event_->hasConnections(reciever, pMemberFunc);
	}

	size_t disconnectAll()
	{
		return event_->disconnectAll();
	}
	size_t disconnectAll(AbstractDelegate const & deleg)
	{
		return event_->disconnectAll(deleg);
	}
	template<class T, class Y> size_t disconnectAll(T * reciever, Y pMemberFunc)
	{
		return event_->disconnectAll(reciever, pMemberFunc);
	}
	bool disconnectOne(AbstractDelegate const & deleg)
	{
		return event_->disconnectOne(deleg);
	}
	template<class T, class Y> bool disconnectOne(T * reciever, Y pMemberFunc)
	{
		return event_->disconnectOne(reciever, pMemberFunc);
	}
protected:
	AbstractEvent * senderEvent() const { return event_; }
private:
	AbstractEvent * event_;
};

inline bool AbstractEvent::disconnectOne(AbstractDelegate const & deleg)
{
	return connectionList_.disconnectOne(deleg);
}

#endif //ABSTRACT_EVENT__HPP<|endoftext|>


<commit_before>#include "matcher.h"

#include "3rd-party/catch.hpp"

#include <map>

#include "matchable.h"
#include "matcherexception.h"

using namespace newsboat;

class MatcherMockMatchable : public Matchable {
public:
	MatcherMockMatchable() = default;

	MatcherMockMatchable(
		std::initializer_list<std::pair<const std::string, std::string>>
		data)
		: m_data(data)
	{}

	virtual bool has_attribute(const std::string& attribname)
	{
		return m_data.find(attribname) != m_data.cend();
	}

	virtual std::string get_attribute(const std::string& attribname)
	{
		const auto it = m_data.find(attribname);
		if (it != m_data.cend()) {
			return it->second;
		}

		return "";
	}

private:
	std::map<std::string, std::string> m_data;
};

TEST_CASE("Operator `=` checks if field has given value", "[Matcher]")
{
	MatcherMockMatchable mock({{"abcd", "xyz"}});
	Matcher m;

	m.parse("abcd = \"xyz\"");
	REQUIRE(m.matches(&mock));

	m.parse("abcd = \"uiop\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `!=` checks if field doesn't have given value", "[Matcher]")
{
	MatcherMockMatchable mock({{"abcd", "xyz"}});
	Matcher m;

	m.parse("abcd != \"uiop\"");
	REQUIRE(m.matches(&mock));

	m.parse("abcd != \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `=~` checks if field matches given regex", "[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA =~ \".\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"123\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"234\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"45\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"^12345$\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"^123456$\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Matcher throws if expression contains undefined fields", "[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("BBBB =~ \"foo\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB # \"foo\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB < 0");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB > 0");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB between 1:23");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);
}

TEST_CASE("Matcher throws if regex passed to `=~` or `!~` is invalid",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA =~ \"[[\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("AAAA !~ \"[[\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);
}

TEST_CASE("Operator `!~` checks if field doesn't match given regex",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA !~ \".\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"123\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"234\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"45\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"^12345$\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `#` checks if \"tags\" field contains given value",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"tags", "foo bar baz quux"}});
	Matcher m;

	m.parse("tags # \"foo\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"baz\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"quux\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo bar\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo\" and tags # \"bar\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"foo\" and tags # \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo\" or tags # \"xyz\"");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Operator `!#` checks if \"tags\" field doesn't contain given value",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"tags", "foo bar baz quux"}});
	Matcher m;

	m.parse("tags !# \"nein\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags !# \"foo\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE(
	"Operators `>`, `>=`, `<` and `<=` compare field's value to given "
	"value",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA > 12344");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA > 12345");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA >= 12345");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA < 12345");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA <= 12345");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Operator `between` checks if field's value is in given range",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA between 0:12345");
	REQUIRE(m.get_parse_error() == "");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA between 12345:12345");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA between 23:12344");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA between 0");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA between 12346:12344");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Invalid expression results in parsing error", "[Matcher]")
{
	Matcher m;

	REQUIRE_FALSE(m.parse("AAAA between 0:15:30"));
	REQUIRE(m.get_parse_error() != "");
}

TEST_CASE("get_expression() returns previously parsed expression", "[Matcher]")
{
	Matcher m2("AAAA between 1:30000");
	REQUIRE(m2.get_expression() == "AAAA between 1:30000");
}

TEST_CASE("Regexes are matched case-insensitively", "[Matcher]")
{
	// Inspired by https://github.com/newsboat/newsboat/issues/642

	const auto require_matches = [](std::string regex) {
		MatcherMockMatchable mock({{"abcd", "xyz"}});
		Matcher m;

		m.parse("abcd =~ \"" + regex + "\"");
		REQUIRE(m.matches(&mock));
	};

	require_matches("xyz");
	require_matches("xYz");
	require_matches("xYZ");
	require_matches("Xyz");
	require_matches("yZ");
	require_matches("^xYZ");
	require_matches("xYz$");
	require_matches("^Xyz$");
	require_matches("^xY");
	require_matches("yZ$");
}

TEST_CASE("=~ and !~ use POSIX extended regex syntax", "[Matcher]")
{
	// This syntax is documented in The Open Group Base Specifications Issue 7,
	// IEEE Std 1003.1-2008 Section 9, "Regular Expressions":
	// https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/basedefs/V1_chap09.html

	// Since POSIX extended regular expressions are pretty basic, it's hard to
	// find stuff that they support but other engines don't. So in order to
	// ensure that we're using EREs, these tests try stuff that's *not*
	// supported by EREs.
	//
	// Ideas gleaned from https://www.regular-expressions.info/refcharacters.html

	Matcher m;

	// Supported by Perl, PCRE, PHP and others
	SECTION("No support for escape sequence") {
		MatcherMockMatchable mock({{"attr", "*]+"}});

		m.parse(R"#(attr =~ "\Q*]+\E")#");
		REQUIRE_FALSE(m.matches(&mock));

		m.parse(R"#(attr !~ "\Q*]+\E")#");
		REQUIRE(m.matches(&mock));
	}

	SECTION("No support for hexadecimal escape") {
		MatcherMockMatchable mock({{"attr", "value"}});

		m.parse(R"#(attr =~ "^va\x6Cue")#");
		REQUIRE_FALSE(m.matches(&mock));

		m.parse(R"#(attr !~ "^va\x6Cue")#");
		REQUIRE(m.matches(&mock));
	}

	SECTION("No support for \\a as alert/bell control character") {
		MatcherMockMatchable mock({{"attr", "\x07"}});

		m.parse(R"#(attr =~ "\a")#");
		REQUIRE_FALSE(m.matches(&mock));

		m.parse(R"#(attr !~ "\a")#");
		REQUIRE(m.matches(&mock));
	}

	SECTION("No support for \\b as backspace control character") {
		MatcherMockMatchable mock({{"attr", "\x08"}});

		m.parse(R"#(attr =~ "\b")#");
		REQUIRE_FALSE(m.matches(&mock));

		m.parse(R"#(attr !~ "\b")#");
		REQUIRE(m.matches(&mock));
	}

	// If you add more checks to this test, consider adding the same to RegexManager tests
}

TEST_CASE("get_parse_error() returns textual description of last "
	"filter-expression parsing error",
	"[Matcher]")
{
	Matcher m;

	REQUIRE_FALSE(m.parse("=!"));
	REQUIRE(m.get_parse_error() != "");
}
<commit_msg>Matcher: test whitespace in filter expressions<commit_after>#include "matcher.h"

#include "3rd-party/catch.hpp"

#include <map>

#include "matchable.h"
#include "matcherexception.h"

using namespace newsboat;

class MatcherMockMatchable : public Matchable {
public:
	MatcherMockMatchable() = default;

	MatcherMockMatchable(
		std::initializer_list<std::pair<const std::string, std::string>>
		data)
		: m_data(data)
	{}

	virtual bool has_attribute(const std::string& attribname)
	{
		return m_data.find(attribname) != m_data.cend();
	}

	virtual std::string get_attribute(const std::string& attribname)
	{
		const auto it = m_data.find(attribname);
		if (it != m_data.cend()) {
			return it->second;
		}

		return "";
	}

private:
	std::map<std::string, std::string> m_data;
};

TEST_CASE("Operator `=` checks if field has given value", "[Matcher]")
{
	MatcherMockMatchable mock({{"abcd", "xyz"}});
	Matcher m;

	m.parse("abcd = \"xyz\"");
	REQUIRE(m.matches(&mock));

	m.parse("abcd = \"uiop\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `!=` checks if field doesn't have given value", "[Matcher]")
{
	MatcherMockMatchable mock({{"abcd", "xyz"}});
	Matcher m;

	m.parse("abcd != \"uiop\"");
	REQUIRE(m.matches(&mock));

	m.parse("abcd != \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `=~` checks if field matches given regex", "[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA =~ \".\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"123\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"234\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"45\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"^12345$\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"^123456$\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Matcher throws if expression contains undefined fields", "[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("BBBB =~ \"foo\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB # \"foo\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB < 0");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB > 0");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB between 1:23");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);
}

TEST_CASE("Matcher throws if regex passed to `=~` or `!~` is invalid",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA =~ \"[[\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("AAAA !~ \"[[\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);
}

TEST_CASE("Operator `!~` checks if field doesn't match given regex",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA !~ \".\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"123\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"234\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"45\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"^12345$\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `#` checks if \"tags\" field contains given value",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"tags", "foo bar baz quux"}});
	Matcher m;

	m.parse("tags # \"foo\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"baz\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"quux\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo bar\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo\" and tags # \"bar\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"foo\" and tags # \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo\" or tags # \"xyz\"");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Operator `!#` checks if \"tags\" field doesn't contain given value",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"tags", "foo bar baz quux"}});
	Matcher m;

	m.parse("tags !# \"nein\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags !# \"foo\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE(
	"Operators `>`, `>=`, `<` and `<=` compare field's value to given "
	"value",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA > 12344");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA > 12345");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA >= 12345");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA < 12345");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA <= 12345");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Operator `between` checks if field's value is in given range",
	"[Matcher]")
{
	MatcherMockMatchable mock({{"AAAA", "12345"}});
	Matcher m;

	m.parse("AAAA between 0:12345");
	REQUIRE(m.get_parse_error() == "");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA between 12345:12345");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA between 23:12344");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA between 0");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA between 12346:12344");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Invalid expression results in parsing error", "[Matcher]")
{
	Matcher m;

	REQUIRE_FALSE(m.parse("AAAA between 0:15:30"));
	REQUIRE(m.get_parse_error() != "");
}

TEST_CASE("get_expression() returns previously parsed expression", "[Matcher]")
{
	Matcher m2("AAAA between 1:30000");
	REQUIRE(m2.get_expression() == "AAAA between 1:30000");
}

TEST_CASE("Regexes are matched case-insensitively", "[Matcher]")
{
	// Inspired by https://github.com/newsboat/newsboat/issues/642

	const auto require_matches = [](std::string regex) {
		MatcherMockMatchable mock({{"abcd", "xyz"}});
		Matcher m;

		m.parse("abcd =~ \"" + regex + "\"");
		REQUIRE(m.matches(&mock));
	};

	require_matches("xyz");
	require_matches("xYz");
	require_matches("xYZ");
	require_matches("Xyz");
	require_matches("yZ");
	require_matches("^xYZ");
	require_matches("xYz$");
	require_matches("^Xyz$");
	require_matches("^xY");
	require_matches("yZ$");
}

TEST_CASE("=~ and !~ use POSIX extended regex syntax", "[Matcher]")
{
	// This syntax is documented in The Open Group Base Specifications Issue 7,
	// IEEE Std 1003.1-2008 Section 9, "Regular Expressions":
	// https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/basedefs/V1_chap09.html

	// Since POSIX extended regular expressions are pretty basic, it's hard to
	// find stuff that they support but other engines don't. So in order to
	// ensure that we're using EREs, these tests try stuff that's *not*
	// supported by EREs.
	//
	// Ideas gleaned from https://www.regular-expressions.info/refcharacters.html

	Matcher m;

	// Supported by Perl, PCRE, PHP and others
	SECTION("No support for escape sequence") {
		MatcherMockMatchable mock({{"attr", "*]+"}});

		m.parse(R"#(attr =~ "\Q*]+\E")#");
		REQUIRE_FALSE(m.matches(&mock));

		m.parse(R"#(attr !~ "\Q*]+\E")#");
		REQUIRE(m.matches(&mock));
	}

	SECTION("No support for hexadecimal escape") {
		MatcherMockMatchable mock({{"attr", "value"}});

		m.parse(R"#(attr =~ "^va\x6Cue")#");
		REQUIRE_FALSE(m.matches(&mock));

		m.parse(R"#(attr !~ "^va\x6Cue")#");
		REQUIRE(m.matches(&mock));
	}

	SECTION("No support for \\a as alert/bell control character") {
		MatcherMockMatchable mock({{"attr", "\x07"}});

		m.parse(R"#(attr =~ "\a")#");
		REQUIRE_FALSE(m.matches(&mock));

		m.parse(R"#(attr !~ "\a")#");
		REQUIRE(m.matches(&mock));
	}

	SECTION("No support for \\b as backspace control character") {
		MatcherMockMatchable mock({{"attr", "\x08"}});

		m.parse(R"#(attr =~ "\b")#");
		REQUIRE_FALSE(m.matches(&mock));

		m.parse(R"#(attr !~ "\b")#");
		REQUIRE(m.matches(&mock));
	}

	// If you add more checks to this test, consider adding the same to RegexManager tests
}

TEST_CASE("get_parse_error() returns textual description of last "
	"filter-expression parsing error",
	"[Matcher]")
{
	Matcher m;

	REQUIRE_FALSE(m.parse("=!"));
	REQUIRE(m.get_parse_error() != "");
}

TEST_CASE("Space characters in filter expression don't affect parsing",
	"[Matcher]")
{
	const auto check = [](std::string expression) {
		INFO("input expression: " << expression);

		MatcherMockMatchable mock({{"array", "foo bar baz"}});
		Matcher m;

		m.parse(expression);
		REQUIRE(m.get_parse_error() == "");
		REQUIRE(m.matches(&mock));
	};

	check("array # \"bar\"");
	check("   array # \"bar\"");
	check("array   # \"bar\"");
	check("array #   \"bar\"");
	check("array # \"bar\"     ");
	check("array#  \"bar\"  ");
	check("     array         #         \"bar\"      ");
}

TEST_CASE("Only space characters are considered whitespace by filter parser",
	"[Matcher]")
{
	const auto check = [](std::string expression) {
		INFO("input expression: " << expression);

		MatcherMockMatchable mock({{"attr", "value"}});
		Matcher m;

		m.parse(expression);
		REQUIRE_FALSE(m.get_parse_error() == "");
	};

	check("attr\t= \"value\"");
	check("attr =\t\"value\"");
	check("attr\n=\t\"value\"");
	check("attr\v=\"value\"");
	check("attr=\"value\"\r\n");
}
<|endoftext|>


<commit_before>//
// gsl-lite is based on GSL: Guideline Support Library.
// For more information see https://github.com/martinmoene/gsl-lite
//
// Copyright (c) 2015 Martin Moene
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "gsl-lite.t.h"

CASE( "owner<>: Allows its use as the (pointer) type it stands for" )
{
#if gsl_HAVE_OWNER_TEMPLATE
    struct F { static void incr( int * i ) { *i += 1; } };

    owner<int*> p = new int( 120 );

    EXPECT( (p != NULL) );
    EXPECT(  p != nullptr_void() );
# if gsl_HAVE_NULLPTR
    EXPECT(  p != nullptr );
# endif
    EXPECT( *p == 120 );

    F::incr( p );

    EXPECT( *p == 121 );
#else
    EXPECT( !!"owner<> alias template is not available." );
#endif
}

CASE( "Owner(): Allows its use as the (pointer) type it stands for" )
{
#if gsl_FEATURE_HAVE_OWNER_MACRO
    struct F { static void incr( int * i ) { *i += 1; } };

    Owner(int*) p = new int( 120 );

    EXPECT( (p != NULL) );
    EXPECT(  p != nullptr_void() );
# if gsl_HAVE_NULLPTR
    EXPECT(  p != nullptr );
# endif
    EXPECT( *p == 120 );

    F::incr( p );

    EXPECT( *p == 121 );
#else
    EXPECT( !!"Owner() macro is not available." );
#endif
}

// end of file
<commit_msg>Fixed memory leak, which prevents tests to pass with address sanitizing.<commit_after>//
// gsl-lite is based on GSL: Guideline Support Library.
// For more information see https://github.com/martinmoene/gsl-lite
//
// Copyright (c) 2015 Martin Moene
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "gsl-lite.t.h"

CASE( "owner<>: Allows its use as the (pointer) type it stands for" )
{
#if gsl_HAVE_OWNER_TEMPLATE
    struct F { static void incr( int * i ) { *i += 1; } };

    owner<int*> p = new int( 120 );

    EXPECT( (p != NULL) );
    EXPECT(  p != nullptr_void() );
# if gsl_HAVE_NULLPTR
    EXPECT(  p != nullptr );
# endif
    EXPECT( *p == 120 );

    F::incr( p );

    EXPECT( *p == 121 );
    delete p;
#else
    EXPECT( !!"owner<> alias template is not available." );
#endif
}

CASE( "Owner(): Allows its use as the (pointer) type it stands for" )
{
#if gsl_FEATURE_HAVE_OWNER_MACRO
    struct F { static void incr( int * i ) { *i += 1; } };

    Owner(int*) p = new int( 120 );

    EXPECT( (p != NULL) );
    EXPECT(  p != nullptr_void() );
# if gsl_HAVE_NULLPTR
    EXPECT(  p != nullptr );
# endif
    EXPECT( *p == 120 );

    F::incr( p );

    EXPECT( *p == 121 );
    delete p;
#else
    EXPECT( !!"Owner() macro is not available." );
#endif
}

// end of file
<|endoftext|>


<commit_before>// This file is part of the dune-grid-multiscale project:
//   http://users.dune-project.org/projects/dune-grid-multiscale
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include <dune/stuff/test/main.hh> // <- has to come first

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/grid/sgrid.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/stuff/common/string.hh>

#include <dune/grid/multiscale/provider/cube.hh>

using namespace Dune;
typedef SGrid< 2, 2 > GridType;

template< class GridPartType >
void measureTiming(const GridPartType& gridPart, Dune::Stuff::Common::LogStream& out, const std::string name = "")
{
  out << "  walking " << name << " grid part... " << std::flush;
  Dune::Timer timer;
  unsigned int elements = 0;
  for (typename GridPartType::template Codim< 0 >::IteratorType it = gridPart.template begin< 0 >();
       it != gridPart.template end< 0 >();
       ++it)
    ++elements;
  out << " done (has " << elements << " elements, took " << timer.elapsed() << " sek)" << std::endl;
} // void measureTiming()

template< class GlobalGridPartType, class LocalGridPartType, class OutStreamType >
struct Inspect
{
  template< int dim, int codim >
  struct Codim
  {
    static void entities(const GlobalGridPartType& globalGridPart, const LocalGridPartType& localGridPart, const std::string prefix, OutStreamType& out)
    {
      // walk all codim entitites
      for (auto entityIt = localGridPart.template begin< codim >(); entityIt != localGridPart.template end< codim >(); ++entityIt) {
        const auto& entity = *entityIt;
        const auto& geometryType = entity.type();
        const auto globalIndex = globalGridPart.indexSet().index(entity);
        const auto localIndex = localGridPart.indexSet().index(entity);
        out << prefix << geometryType << ", global index " << globalIndex << ", local index " << localIndex << std::endl;
        out << prefix << "  corners: ";
        auto geometry = entity.geometry();
        for (int i = 0; i < (geometry.corners() - 1); ++i)
          out << "(" << geometry.corner(i) << "), ";
        out << "(" << geometry.corner(geometry.corners() - 1) << ")" << std::endl;
      } // walk all codim entitites
      // increase Codim
      Inspect< GlobalGridPartType, LocalGridPartType, OutStreamType >::Codim< dim, codim + 1 >::entities(globalGridPart, localGridPart, prefix, out);
    }
  }; // struct Codim
}; // struct Inspect

template< class GlobalGridPartType, class LocalGridPartType, class OutStreamType >
template< int codim >
struct Inspect< GlobalGridPartType, LocalGridPartType, OutStreamType >::Codim< codim, codim >
{
  static void entities(const GlobalGridPartType& globalGridPart, const LocalGridPartType& localGridPart, const std::string prefix, OutStreamType& out)
  {
    // walk all codim entitites
    for (auto entityIt = localGridPart.template begin< codim >(); entityIt != localGridPart.template end< codim >(); ++entityIt) {
      const auto& entity = *entityIt;
      const auto& geometryType = entity.type();
      const auto globalIndex = globalGridPart.indexSet().index(entity);
      const auto localIndex = localGridPart.indexSet().index(entity);
      out << prefix << geometryType << ", global index " << globalIndex << ", local index " << localIndex << std::endl;
      out << prefix << "  corners: (" << entity.geometry().center() << ")" << std::endl;
    } // walk all codim entitites
  }
};

class CubeProvider
  : public ::testing::Test
{
protected:
  typedef grid::Multiscale::Providers::Cube< GridType > ProviderType;
  typedef typename ProviderType::MsGridType MsGridType;

  CubeProvider()
    : ms_grid_(ProviderType::create()->ms_grid())
  {}

  std::shared_ptr< const MsGridType > ms_grid_;
}; // class CubeProvider

TEST_F(CubeProvider, global_gridpart)
{
  const auto& globalGridPart = *(ms_grid_->globalGridPart());
  Inspect< MsGridType::GlobalGridPartType, MsGridType::GlobalGridPartType, Dune::Stuff::Common::LogStream >
      ::Codim< GridType::dimension, 0 >
      ::entities(globalGridPart, globalGridPart, "  ", DSC_LOG_INFO);
}

TEST_F(CubeProvider, local_grid_parts)
{
  const auto& globalGridPart = *(ms_grid_->globalGridPart());
  for (unsigned int subdomain = 0; subdomain < ms_grid_->size(); ++subdomain) {
    DSC_LOG_INFO << "subdomain " << subdomain << std::endl;
    const auto& localGridPart = *(ms_grid_->localGridPart(subdomain));
    Inspect< MsGridType::GlobalGridPartType, MsGridType::LocalGridPartType, Dune::Stuff::Common::LogStream >
        ::Codim< GridType::dimension, 0 >
        ::entities(globalGridPart, localGridPart, "  ", DSC_LOG_INFO);
  }
}

TEST_F(CubeProvider, boundary_grid_parts)
{
  const auto& globalGridPart = *(ms_grid_->globalGridPart());
    for (unsigned int subdomain = 0; subdomain < ms_grid_->size(); ++subdomain) {
      if (ms_grid_->boundary(subdomain)) {
        DSC_LOG_INFO << "subdomain " << subdomain << std::endl;
        const auto& boundaryGridPart = *(ms_grid_->boundaryGridPart(subdomain));
        Inspect< MsGridType::GlobalGridPartType, MsGridType::BoundaryGridPartType, Dune::Stuff::Common::LogStream >
            ::Codim< GridType::dimension, 0 >
            ::entities(globalGridPart, boundaryGridPart, "  ", DSC_LOG_INFO);
      }
    }
}

TEST_F(CubeProvider, coupling_grid_parts)
{
  const auto& globalGridPart = *(ms_grid_->globalGridPart());
  for (size_t ss = 0; ss < ms_grid_->size(); ++ss) {
    for (auto nn : ms_grid_->neighborsOf(ss)) {
      const auto& coupling_grid_part = *(ms_grid_->couplingGridPart(ss, nn));
      DSC_LOG_INFO << "testing coupling grid part: " << ss << ", " << nn << std::endl;
      // walk the grid part
      for (auto entityIterator = coupling_grid_part.begin< 0 >();
           entityIterator != coupling_grid_part.end< 0 >();
           ++entityIterator) {
        const auto& entity = *entityIterator;
        const unsigned int entityIndex = coupling_grid_part.indexSet().index(entity);
        DSC_LOG_INFO << "entity " << entityIndex << ", neighbors " << std::flush;
        // walk the intersections
        for (auto intersectionIterator = coupling_grid_part.ibegin(entity);
             intersectionIterator != coupling_grid_part.iend(entity);
             ++intersectionIterator) {
          const auto& intersection = *intersectionIterator;
          const auto neighborPtr = intersection.outside();
          const auto& neighbor = *neighborPtr;
          const unsigned int neighborIndex = globalGridPart.indexSet().index(neighbor);
          DSC_LOG_INFO << neighborIndex << " ";
        } // walk the intersections
        DSC_LOG_INFO << std::endl;
      } // walk the grid part
    }
  }
}

TEST_F(CubeProvider, timings)
{
  // time grid parts
  DSC_LOG_INFO << "timing grid parts:" << std::endl;
  const auto globalGridPart = ms_grid_->globalGridPart();
  measureTiming(*globalGridPart, DSC_LOG_INFO, "global");
  const unsigned int neighbor = *(ms_grid_->neighborsOf(0).begin());
  const auto couplingGridPart = ms_grid_->couplingGridPart(0, neighbor);
  measureTiming(*couplingGridPart, DSC_LOG_INFO, "coupling (subdomain 0 with " + DSC::toString(neighbor) + ")");
  const auto firstLocalGridPart = ms_grid_->localGridPart(0);
  measureTiming(*firstLocalGridPart, DSC_LOG_INFO, "local (subdomain 0)");
  for (unsigned int subdomain = 1; subdomain < ms_grid_->size(); ++subdomain) {
    const auto localGridPart = ms_grid_->localGridPart(subdomain);
    measureTiming(*localGridPart, DSC_LOG_DEBUG, "local (subdomain " + DSC::toString(subdomain) + ")");
  }
}
<commit_msg>[test.provider] fix unsafe ineter conversion<commit_after>// This file is part of the dune-grid-multiscale project:
//   http://users.dune-project.org/projects/dune-grid-multiscale
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include <dune/stuff/test/main.hh> // <- has to come first

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/grid/sgrid.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/stuff/common/string.hh>

#include <dune/grid/multiscale/provider/cube.hh>

using namespace Dune;
typedef SGrid< 2, 2 > GridType;

template< class GridPartType >
void measureTiming(const GridPartType& gridPart, Dune::Stuff::Common::LogStream& out, const std::string name = "")
{
  out << "  walking " << name << " grid part... " << std::flush;
  Dune::Timer timer;
  unsigned int elements = 0;
  for (typename GridPartType::template Codim< 0 >::IteratorType it = gridPart.template begin< 0 >();
       it != gridPart.template end< 0 >();
       ++it)
    ++elements;
  out << " done (has " << elements << " elements, took " << timer.elapsed() << " sek)" << std::endl;
} // void measureTiming()

template< class GlobalGridPartType, class LocalGridPartType, class OutStreamType >
struct Inspect
{
  template< int dim, int codim >
  struct Codim
  {
    static void entities(const GlobalGridPartType& globalGridPart, const LocalGridPartType& localGridPart, const std::string prefix, OutStreamType& out)
    {
      // walk all codim entitites
      for (auto entityIt = localGridPart.template begin< codim >(); entityIt != localGridPart.template end< codim >(); ++entityIt) {
        const auto& entity = *entityIt;
        const auto& geometryType = entity.type();
        const auto globalIndex = globalGridPart.indexSet().index(entity);
        const auto localIndex = localGridPart.indexSet().index(entity);
        out << prefix << geometryType << ", global index " << globalIndex << ", local index " << localIndex << std::endl;
        out << prefix << "  corners: ";
        auto geometry = entity.geometry();
        for (int i = 0; i < (geometry.corners() - 1); ++i)
          out << "(" << geometry.corner(i) << "), ";
        out << "(" << geometry.corner(geometry.corners() - 1) << ")" << std::endl;
      } // walk all codim entitites
      // increase Codim
      Inspect< GlobalGridPartType, LocalGridPartType, OutStreamType >::Codim< dim, codim + 1 >::entities(globalGridPart, localGridPart, prefix, out);
    }
  }; // struct Codim
}; // struct Inspect

template< class GlobalGridPartType, class LocalGridPartType, class OutStreamType >
template< int codim >
struct Inspect< GlobalGridPartType, LocalGridPartType, OutStreamType >::Codim< codim, codim >
{
  static void entities(const GlobalGridPartType& globalGridPart, const LocalGridPartType& localGridPart, const std::string prefix, OutStreamType& out)
  {
    // walk all codim entitites
    for (auto entityIt = localGridPart.template begin< codim >(); entityIt != localGridPart.template end< codim >(); ++entityIt) {
      const auto& entity = *entityIt;
      const auto& geometryType = entity.type();
      const auto globalIndex = globalGridPart.indexSet().index(entity);
      const auto localIndex = localGridPart.indexSet().index(entity);
      out << prefix << geometryType << ", global index " << globalIndex << ", local index " << localIndex << std::endl;
      out << prefix << "  corners: (" << entity.geometry().center() << ")" << std::endl;
    } // walk all codim entitites
  }
};

class CubeProvider
  : public ::testing::Test
{
protected:
  typedef grid::Multiscale::Providers::Cube< GridType > ProviderType;
  typedef typename ProviderType::MsGridType MsGridType;

  CubeProvider()
    : ms_grid_(ProviderType::create()->ms_grid())
  {}

  std::shared_ptr< const MsGridType > ms_grid_;
}; // class CubeProvider

TEST_F(CubeProvider, global_gridpart)
{
  const auto& globalGridPart = *(ms_grid_->globalGridPart());
  Inspect< MsGridType::GlobalGridPartType, MsGridType::GlobalGridPartType, Dune::Stuff::Common::LogStream >
      ::Codim< GridType::dimension, 0 >
      ::entities(globalGridPart, globalGridPart, "  ", DSC_LOG_INFO);
}

TEST_F(CubeProvider, local_grid_parts)
{
  const auto& globalGridPart = *(ms_grid_->globalGridPart());
  for (unsigned int subdomain = 0; subdomain < ms_grid_->size(); ++subdomain) {
    DSC_LOG_INFO << "subdomain " << subdomain << std::endl;
    const auto& localGridPart = *(ms_grid_->localGridPart(subdomain));
    Inspect< MsGridType::GlobalGridPartType, MsGridType::LocalGridPartType, Dune::Stuff::Common::LogStream >
        ::Codim< GridType::dimension, 0 >
        ::entities(globalGridPart, localGridPart, "  ", DSC_LOG_INFO);
  }
}

TEST_F(CubeProvider, boundary_grid_parts)
{
  const auto& globalGridPart = *(ms_grid_->globalGridPart());
    for (unsigned int subdomain = 0; subdomain < ms_grid_->size(); ++subdomain) {
      if (ms_grid_->boundary(subdomain)) {
        DSC_LOG_INFO << "subdomain " << subdomain << std::endl;
        const auto& boundaryGridPart = *(ms_grid_->boundaryGridPart(subdomain));
        Inspect< MsGridType::GlobalGridPartType, MsGridType::BoundaryGridPartType, Dune::Stuff::Common::LogStream >
            ::Codim< GridType::dimension, 0 >
            ::entities(globalGridPart, boundaryGridPart, "  ", DSC_LOG_INFO);
      }
    }
}

TEST_F(CubeProvider, coupling_grid_parts)
{
  const auto& globalGridPart = *(ms_grid_->globalGridPart());
  for (size_t ss = 0; ss < ms_grid_->size(); ++ss) {
    for (auto nn : ms_grid_->neighborsOf(ss)) {
      const auto& coupling_grid_part = *(ms_grid_->couplingGridPart(ss, nn));
      DSC_LOG_INFO << "testing coupling grid part: " << ss << ", " << nn << std::endl;
      // walk the grid part
      for (auto entityIterator = coupling_grid_part.begin< 0 >();
           entityIterator != coupling_grid_part.end< 0 >();
           ++entityIterator) {
        const auto& entity = *entityIterator;
        const unsigned int entityIndex = coupling_grid_part.indexSet().index(entity);
        DSC_LOG_INFO << "entity " << entityIndex << ", neighbors " << std::flush;
        // walk the intersections
        for (auto intersectionIterator = coupling_grid_part.ibegin(entity);
             intersectionIterator != coupling_grid_part.iend(entity);
             ++intersectionIterator) {
          const auto& intersection = *intersectionIterator;
          const auto neighborPtr = intersection.outside();
          const auto& neighbor = *neighborPtr;
          const unsigned int neighborIndex = globalGridPart.indexSet().index(neighbor);
          DSC_LOG_INFO << neighborIndex << " ";
        } // walk the intersections
        DSC_LOG_INFO << std::endl;
      } // walk the grid part
    }
  }
}

TEST_F(CubeProvider, timings)
{
  // time grid parts
  DSC_LOG_INFO << "timing grid parts:" << std::endl;
  const auto globalGridPart = ms_grid_->globalGridPart();
  measureTiming(*globalGridPart, DSC_LOG_INFO, "global");
  const auto neighbor = *(ms_grid_->neighborsOf(0).begin());
  const auto couplingGridPart = ms_grid_->couplingGridPart(0, neighbor);
  measureTiming(*couplingGridPart, DSC_LOG_INFO, "coupling (subdomain 0 with " + DSC::toString(neighbor) + ")");
  const auto firstLocalGridPart = ms_grid_->localGridPart(0);
  measureTiming(*firstLocalGridPart, DSC_LOG_INFO, "local (subdomain 0)");
  for (unsigned int subdomain = 1; subdomain < ms_grid_->size(); ++subdomain) {
    const auto localGridPart = ms_grid_->localGridPart(subdomain);
    measureTiming(*localGridPart, DSC_LOG_DEBUG, "local (subdomain " + DSC::toString(subdomain) + ")");
  }
}
<|endoftext|>


<commit_before>//
// Created by Dennis Goldfarb on 1/3/17.
//

#include <iostream>
#include <fstream>
#include <random>

#include <OpenMS/CHEMISTRY/Element.h>
#include <OpenMS/CHEMISTRY/AASequence.h>
#include <OpenMS/CHEMISTRY/ResidueDB.h>
#include <OpenMS/CHEMISTRY/ElementDB.h>

#include "FASTAParser.h"

static const ElementDB* elementDB = ElementDB::getInstance();
static const OpenMS::ResidueDB* residueDB = OpenMS::ResidueDB::getInstance();

static std::string AMINO_ACIDS = "ADEFGHIKLNPQRSTVWYCM";
static std::string AMINO_ACIDS_NO_SULFUR = "ADEFGHIKLNPQRSTVWY";
static std::string AMINO_ACIDS_SULFUR = "CM";

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis_AA(0, AMINO_ACIDS.length()-1);
std::uniform_int_distribution<> dis_AA_NS(0, AMINO_ACIDS_NO_SULFUR.length()-1);
std::uniform_int_distribution<> dis_S(0, AMINO_ACIDS_SULFUR.length()-1);

std::ofstream* openOutputFiles(std::string base_path, int max_depth)
{
    // create all output files and write header to each
    std::ofstream* outfiles = new std::ofstream[max_depth];
    for (int precursor_isotope = 0; precursor_isotope < max_depth; ++precursor_isotope)
    {
        std::string filename = "Precursor" + std::to_string(precursor_isotope) + ".tab";

        outfiles[precursor_isotope].open(base_path + filename);
        outfiles[precursor_isotope] << "probability" << "\tprecursor.mass" << std::endl;
    }

    return outfiles;
}

void closeOutputFiles(std::ofstream* outfiles, int max_depth)
{
    // close all output files
    for (int precursor_isotope = 0; precursor_isotope < max_depth; ++precursor_isotope)
    {
        outfiles[precursor_isotope].close();
    }
    delete[] outfiles;
}

void write_distribution(const OpenMS::AASequence &p, std::ofstream* outfiles, int max_depth, bool mono)
{
    OpenMS::EmpiricalFormula precursor_ef = p.getFormula();
    OpenMS::IsotopeDistribution precursor_id = precursor_ef.getIsotopeDistribution(0);

    for (int precursor_isotope = 0; precursor_isotope < max_depth && precursor_isotope < precursor_id.size(); ++precursor_isotope)
    {
        double mass = mono ? precursor_ef.getMonoWeight() : precursor_ef.getAverageWeight();

        outfiles[precursor_isotope] << precursor_id.getContainer()[precursor_isotope].second << "\t" << mass << std::endl;
    }
}

void proteome_isotopic_distributions(std::string base_path, std::string fasta_path, float max_mass, int num_sulfurs, int max_depth, bool mono)
{
    std::ofstream* outfiles = openOutputFiles(base_path, max_depth);

    FASTAParser parser(fasta_path, max_mass, 1, 100);
    for (auto itr = parser.begin(); itr != parser.end(); ++itr)
    {
        if (num_sulfurs < 0 || itr->getFormula().getNumberOf(elementDB->getElement("Sulfur")) == num_sulfurs)
        {
            write_distribution(*itr, outfiles, max_depth, mono);
        }
    }

    closeOutputFiles(outfiles, max_depth);
}

OpenMS::AASequence create_random_peptide_sequence(int peptide_length, int num_sulfurs)
{
    OpenMS::AASequence random_peptide;

    if (num_sulfurs < 0)
    {
        for (int aa_index = 0; aa_index < peptide_length; ++aa_index)
        {
            random_peptide += residueDB->getResidue(AMINO_ACIDS[dis_AA(gen)]);
        }
    }
    else
    {
        // for insertion of sulfur containing amino acids
        for (int i = 0; i < num_sulfurs; ++i)
        {
            random_peptide += residueDB->getResidue(AMINO_ACIDS_SULFUR[dis_S(gen)]);
        }

        // random amino acid insertion (non Sulfur and Selenium amino acids)
        for (int aa_index = 0; aa_index < peptide_length; ++aa_index)
        {
            random_peptide += residueDB->getResidue(AMINO_ACIDS_NO_SULFUR[dis_AA_NS(gen)]);
        }
    }

    return random_peptide;
}

void sample_isotopic_distributions(std::string base_path, float max_mass, int num_sulfurs, int max_depth, bool mono)
{
    std::ofstream* outfiles = openOutputFiles(base_path, max_depth);

    int max_length = max_mass/100;

    std::cout << max_length << "\t" << max_mass << std::endl;

    for (int peptide_length = 0; peptide_length <= max_length; ++peptide_length)
    {
        for (int sample = 0; sample < 100; ++sample)
        {
            OpenMS::AASequence random_sequence = create_random_peptide_sequence(peptide_length, num_sulfurs);

            if (random_sequence.size() > 0 && random_sequence.getMonoWeight() <= max_mass)
            {
                write_distribution(random_sequence, outfiles, max_depth, mono);
            }
        }
    }

    closeOutputFiles(outfiles, max_depth);
}

void usage()
{
    std::cout << "GenerateTrainingData fasta_path out_path max_mass num_samples S max_depth mono" << std::endl;
    std::cout << "fasta_path: The path to the fasta file to train the splines on." << std::endl;
    std::cout << "out_path: The path to the directory that will store the training data, e.g. ~/data/" << std::endl;
    std::cout << "max_mass: maximum mass allowed for sampled peptides, e.g. 8500" << std::endl;
    std::cout << "S: number of sulfurs that should be in the fragment ion. Use -1 for all (e.g. 0,1,2..)" << std::endl;
    std::cout << "max_depth: The number of isotopes to generate training data for, e.g. 3 = M0,M1,M2" << std::endl;
    std::cout << "mono: should monoisotopic masses be used or average? 1=mono, 0=average" << std::endl;
    std::cout << std::endl;
}

int main(int argc, const char ** argv)
{
    if (argc != 7)
    {
        usage();
        return 0;
    }

    std::string fasta_path = argv[1];
    std::string out_path = argv[2];
    float max_mass = atof(argv[3]);
    int S = atoi(argv[4]);
    int max_depth = atoi(argv[5]);
    bool mono = strncmp(argv[6], "1", 1) == 0 ? true : false;

    //proteome_isotopic_distributions(out_path, fasta_path, max_mass, S, max_depth, mono);
    sample_isotopic_distributions(out_path, max_mass, S, max_depth, mono);

    return 0;
}<commit_msg>added stochastic peptide sampling<commit_after>//
// Created by Dennis Goldfarb on 1/3/17.
//

#include <iostream>
#include <fstream>
#include <random>
#include <algorithm>

#include <OpenMS/CHEMISTRY/Element.h>
#include <OpenMS/CHEMISTRY/AASequence.h>
#include <OpenMS/CHEMISTRY/ResidueDB.h>
#include <OpenMS/CHEMISTRY/ElementDB.h>

#include "FASTAParser.h"

static const ElementDB* elementDB = ElementDB::getInstance();
static const OpenMS::ResidueDB* residueDB = OpenMS::ResidueDB::getInstance();

static std::string AMINO_ACIDS = "ADEFGHIKLNPQRSTVWYCM";
static std::string AMINO_ACIDS_NO_SULFUR = "ADEFGHIKLNPQRSTVWY";
static std::string AMINO_ACIDS_SULFUR = "CM";

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis_AA(0,1);

std::ofstream* openOutputFiles(std::string base_path, int max_depth)
{
    // create all output files and write header to each
    std::ofstream* outfiles = new std::ofstream[max_depth];
    for (int precursor_isotope = 0; precursor_isotope < max_depth; ++precursor_isotope)
    {
        std::string filename = "Precursor" + std::to_string(precursor_isotope) + ".tab";

        outfiles[precursor_isotope].open(base_path + filename);
        outfiles[precursor_isotope] << "probability" << "\tprecursor.mass" << std::endl;
    }

    return outfiles;
}

void closeOutputFiles(std::ofstream* outfiles, int max_depth)
{
    // close all output files
    for (int precursor_isotope = 0; precursor_isotope < max_depth; ++precursor_isotope)
    {
        outfiles[precursor_isotope].close();
    }
    delete[] outfiles;
}

void write_distribution(const OpenMS::AASequence &p, std::ofstream* outfiles, int max_depth, bool mono)
{
    OpenMS::EmpiricalFormula precursor_ef = p.getFormula();
    OpenMS::IsotopeDistribution precursor_id = precursor_ef.getIsotopeDistribution(0);

    for (int precursor_isotope = 0; precursor_isotope < max_depth && precursor_isotope < precursor_id.size(); ++precursor_isotope)
    {
        double mass = mono ? precursor_ef.getMonoWeight() : precursor_ef.getAverageWeight();

        outfiles[precursor_isotope] << precursor_id.getContainer()[precursor_isotope].second << "\t" << mass << std::endl;
    }
}

void proteome_isotopic_distributions(std::string base_path, std::string fasta_path, float max_mass, int num_sulfurs, int max_depth, bool mono)
{
    std::ofstream* outfiles = openOutputFiles(base_path, max_depth);

    FASTAParser parser(fasta_path, max_mass, 1, 100);
    for (auto itr = parser.begin(); itr != parser.end(); ++itr)
    {
        if (num_sulfurs < 0 || itr->getFormula().getNumberOf(elementDB->getElement("Sulfur")) == num_sulfurs)
        {
            write_distribution(*itr, outfiles, max_depth, mono);
        }
    }

    closeOutputFiles(outfiles, max_depth);
}

OpenMS::AASequence create_random_peptide_sequence(int peptide_length, std::vector<double> aa2prob, int num_sulfurs)
{
    OpenMS::AASequence random_peptide;

    if (num_sulfurs < 0)
    {
        for (int aa_index = 0; aa_index < peptide_length; ++aa_index)
        {
            double rand = dis_AA(gen);
            int index = std::lower_bound(aa2prob.begin(), aa2prob.end(), rand) - aa2prob.begin();
            random_peptide += residueDB->getResidue(AMINO_ACIDS[index]);
        }
    }
    else
    {
        // for insertion of sulfur containing amino acids
        for (int i = 0; i < num_sulfurs; ++i)
        {
            random_peptide += residueDB->getResidue(AMINO_ACIDS_SULFUR[0]);
        }

        // random amino acid insertion (non Sulfur and Selenium amino acids)
        for (int aa_index = 0; aa_index < peptide_length; ++aa_index)
        {
            double rand = dis_AA(gen);
            int index = std::lower_bound(aa2prob.begin(), aa2prob.end(), rand) - aa2prob.begin();
            random_peptide += residueDB->getResidue(AMINO_ACIDS_NO_SULFUR[index]);
        }
    }

    return random_peptide;
}

std::map<char, double> getAAProbabilities(std::string fasta_path, bool sulfur)
{
    std::map<char, double> aa2prob;
    for (char aa : AMINO_ACIDS)
    {
        aa2prob[aa] = 0.0;
    }

    std::vector<FASTAFile::FASTAEntry> proteins;
    FASTAFile().load(fasta_path, proteins);

    int count = 0;
    for (Size i = 0; i < proteins.size(); ++i)
    {
        for (int j = 0; j < proteins[i].sequence.size(); ++j)
        {
            char aa = proteins[i].sequence[j];
            if ((sulfur && AMINO_ACIDS.find(aa) != -1) || (!sulfur && AMINO_ACIDS_NO_SULFUR.find(aa) != -1))
            {
                aa2prob[aa]++;
                count++;
            }
        }
    }

    for (auto &aa : aa2prob)
    {
        aa.second /= count;
    }

    return aa2prob;
}

std::vector<double> void calcPrefixSum(std::map<char, double> aa2prob, bool sulfur)
{
    std::string AAs = sulfur ? AMINO_ACIDS : AMINO_ACIDS_NO_SULFUR;
    std::vector<double> prefixSum;

    prefixSum.push_back(0d);

    for (int i = 0; i < AAs.size(); ++i)
    {
        prefixSum.push_back(aa2prob[AAs[i]] + prefixSum[i]);
    }

    return prefixSum;
}

void sample_isotopic_distributions(std::string base_path, std::string fasta_path, float max_mass, int num_sulfurs, int max_depth, bool mono)
{

    std::vector<double> aa2prob = calcPrefixSum(getAAProbabilities(fasta_path, num_sulfurs == -1), num_sulfurs == -1);

    std::ofstream* outfiles = openOutputFiles(base_path, max_depth);

    int max_length = max_mass/100;

    for (int peptide_length = 0; peptide_length <= max_length; ++peptide_length)
    {
        for (int sample = 0; sample < 100; ++sample)
        {
            OpenMS::AASequence random_sequence = create_random_peptide_sequence(peptide_length, aa2prob, num_sulfurs);

            if (random_sequence.size() > 0 && random_sequence.getMonoWeight() <= max_mass)
            {
                write_distribution(random_sequence, outfiles, max_depth, mono);
            }
        }
    }

    closeOutputFiles(outfiles, max_depth);
}

void usage()
{
    std::cout << "GenerateTrainingData fasta_path out_path max_mass num_samples S max_depth mono" << std::endl;
    std::cout << "fasta_path: The path to the fasta file to train the splines on." << std::endl;
    std::cout << "out_path: The path to the directory that will store the training data, e.g. ~/data/" << std::endl;
    std::cout << "max_mass: maximum mass allowed for sampled peptides, e.g. 8500" << std::endl;
    std::cout << "S: number of sulfurs that should be in the fragment ion. Use -1 for all (e.g. 0,1,2..)" << std::endl;
    std::cout << "max_depth: The number of isotopes to generate training data for, e.g. 3 = M0,M1,M2" << std::endl;
    std::cout << "mono: should monoisotopic masses be used or average? 1=mono, 0=average" << std::endl;
    std::cout << std::endl;
}

int main(int argc, const char ** argv)
{
    if (argc != 7)
    {
        usage();
        return 0;
    }

    std::string fasta_path = argv[1];
    std::string out_path = argv[2];
    float max_mass = atof(argv[3]);
    int S = atoi(argv[4]);
    int max_depth = atoi(argv[5]);
    bool mono = strncmp(argv[6], "1", 1) == 0 ? true : false;

    //proteome_isotopic_distributions(out_path, fasta_path, max_mass, S, max_depth, mono);
    sample_isotopic_distributions(out_path, fasta_path, max_mass, S, max_depth, mono);

    return 0;
}<|endoftext|>