<commit_before>/******************************************************************************\
* LuaValue.hpp                                                                 *
* A class that somewhat mimics a Lua value.                                    *
* Leandro Motta Barros                                                         *
\******************************************************************************/

#ifndef _DILUCULUM_LUA_VALUE_HPP_
#define _DILUCULUM_LUA_VALUE_HPP_

extern "C"
{
#  include <lua.h>
}
#include <map>
#include <stdexcept>
#include <string>
#include <boost/any.hpp>

namespace Diluculum
{
   // Just a forward declaration.
   class LuaValue;

   /** Type mapping from <tt>LuaValue</tt>s to <tt>LuaValue</tt>s. Think of it
    *  as a C++ approximation of a Lua table.
    */
   typedef std::map<LuaValue, LuaValue> LuaValueMap;

   /// A generic <tt>LuaValue</tt>-related error.
   class LuaValueError: public std::runtime_error
   {
      public:
         /** Constructs a \c LuaValueError object.
          *  @param what The message associated with the error.
          */
         LuaValueError (const char* what)
            : std::runtime_error (what)
         { }
   };

   /** An error in a \c LuaValueError that happens when a certain type is
    *  expected but another one is found.
    */
   class TypeMismatchError: public LuaValueError
   {
      public:
         /** Constructs a \c TypeMismatchError object.
          *  @param expectedType The type that was expected.
          *  @param expectedType The type that was actually found.
          */
         TypeMismatchError (const std::string& expectedType,
                            const std::string& foundType);

         /** Destroys a \c TypeMismatchError object.
          *  @note This was defined just to pretend that the destructor does not
          *        throw any exception. While this is something that I cannot
          *        guarantee (at least whit this implementation), I believe this
          *        not a very dangerous lie.
          */
         ~TypeMismatchError() throw() { };

         /// Returns the type that was expected.
         std::string getExpectedType() { return expectedType_; }

         /// Returns the type that was actually found.
         std::string getFoundType() { return foundType_; }

      private:
         /// The type that was expected.
         std::string expectedType_;

         /// The type that was actually found.
         std::string foundType_;
   };

   /// A class that somewhat mimics a Lua value.
   class LuaValue
   {
      public:
         /// Constructs a \c LuaValue with a \c nil value.
         LuaValue() { };

         /// Constructs a \c LuaValue with boolean type and \c b value.
         LuaValue (bool b)
            : value_(b)
         { }

         /// Constructs a \c LuaValue with number type and \c n value.
         LuaValue (lua_Number n)
            : value_(n)
         { }

         /// Constructs a \c LuaValue with string type and \c s value.
         LuaValue (const std::string& s)
            : value_(s)
         { }

         /// Constructs a \c LuaValue with string type and \c s value.
         LuaValue (const char* s)
            : value_(std::string(s))
         { }

         /// Constructs a \c LuaValue with table type and \c t value.
         LuaValue (const LuaValueMap& t)
            : value_(t)
         { }

         /** Returns one of the <tt>LUA_T*</tt> constants from <tt>lua.h</tt>,
          *  representing the type stored in this \c LuaValue.
          */
         int type() const;

         /** Returns the type of this \c LuaValue as a string, just like the Lua
          *  built-in function \c type().
          *  @return One of the following strings: <tt>"nil"</tt>,
          *          <tt>"boolean"</tt>, <tt>"number"</tt>, <tt>"string"</tt>,
          *          <tt>"table"</tt>. If the stored value is different than
          *          those for some reason, returns an empty string
          *          (<tt>""</tt>).
          */
         std::string typeName() const;

         /** Return the value as a number.
          *  @throw TypeMismatchError If the value is not a number (this is a
          *         strict check; no type conversion is performed).
          */
         lua_Number asNumber() const;

         /** Return the value as a string.
          *  @throw TypeMismatchError If the value is not a string (this is a
          *         strict check; no type conversion is performed).
          */
         std::string asString() const;

         /** Return the value as a boolean.
          *  @throw TypeMismatchError If the value is not a boolean (this is a
          *         strict check; no type conversion is performed).
          */
         bool asBoolean() const;

         /** Return the value as a table (\c LuaValueMap).
          *  @throw TypeMismatchError If the value is not a table (this is a
          *         strict check; no type conversion is performed).
          */
         LuaValueMap asTable() const;

         /** "Less than" operator for <tt>LuaValue</tt>s.
          *  @return The order relationship is quite arbitrary for
          *          <tt>LuaValue</tt>s, but this has to be defined in order to
          *          \c LuaValueMap work nicely. Anyway, here are the rules used
          *          to determine who is less than who:
          *          - First, \c typeName() is called for both
          *            <tt>LuaValue</tt>s and they are compared with the usual
          *            "less than" operator for strings.
          *          - If both type names are equal, but something different
          *            than <tt>"nil"</tt> or <tt>"table"</tt>, then the values
          *            contained in the <tt>LuaValue</tt>s are compared using
          *            the usual "less than" operator for that type.
          *          - If both type names are <tt>"nil"</tt>, the function
          *            returns \c false.
          *          - If both type names are <tt>"table"</tt>, then the number
          *            of elements in each table are compared. The shorter table
          *            is "less than" the larger table.
          *          - If both tables have the same size, then each entry is
          *            recursively compared (that is, using the rules described
          *            here). For each entry, the key is compared first, than
          *            the value. This is done until finding something "less
          *            than" the other thing.
          *          - If no differences are found, \c false is obviously
          *            returned.
          */
         bool operator< (const LuaValue& rhs) const;

         /** "Greater than" operator for <tt>LuaValue</tt>s.
          *  @return The rules for determining who is greater than who are
          *          similar to the ones described in \c operator<.
          */
         bool operator> (const LuaValue& rhs) const;

         // TODO: A shortcut for table-like access:
         //       LuaValue& operator[] (const LuaValue& key) { return ...; }
         // TODO: Notice the reference return value above. Is this supported by
         //       'boost::any'? If not, will have to use a more traditional
         //       design ('union' anyone?)
         // TODO: 'operator==()' for all supported types:
         //       if (myLuaValue == "bl")
         //          ...;
         //       (perhaps also do this for '<', '>' and '!=')
         // TODO: Replace those 'lua_Number's with 'double's and add explicit
         //       support for 'int's and friends. This makes the typical use
         //       much more natural. I don't think I'll ever compile Lua to use
         //       integers instead of floating point numbers...
         // TODO: After doing the previous TODO, change the tests in
         //       'TestLuaStateDoStringMultiRet()' to use integer indices, not
         //       those ugly floats.
      private:
         /// Stores the value (and the type) stored in this \c LuaValue.
         boost::any value_;
   };

   /// A constant with the value of \c nil.
   const LuaValue Nil;

   /// A constant with value of an empty table.
   const LuaValueMap EmptyLuaValueMap;
   const LuaValue EmptyTable (EmptyLuaValueMap);

} // namespace Diluculum

#endif // _DILUCULUM_LUA_VALUE_HPP_
<commit_msg>Fixed two typos in 'LuaValue' documentation.<commit_after>/******************************************************************************\
* LuaValue.hpp                                                                 *
* A class that somewhat mimics a Lua value.                                    *
* Leandro Motta Barros                                                         *
\******************************************************************************/

#ifndef _DILUCULUM_LUA_VALUE_HPP_
#define _DILUCULUM_LUA_VALUE_HPP_

extern "C"
{
#  include <lua.h>
}
#include <map>
#include <stdexcept>
#include <string>
#include <boost/any.hpp>

namespace Diluculum
{
   // Just a forward declaration.
   class LuaValue;

   /** Type mapping from <tt>LuaValue</tt>s to <tt>LuaValue</tt>s. Think of it
    *  as a C++ approximation of a Lua table.
    */
   typedef std::map<LuaValue, LuaValue> LuaValueMap;

   /// A generic <tt>LuaValue</tt>-related error.
   class LuaValueError: public std::runtime_error
   {
      public:
         /** Constructs a \c LuaValueError object.
          *  @param what The message associated with the error.
          */
         LuaValueError (const char* what)
            : std::runtime_error (what)
         { }
   };

   /** An error in a \c LuaValue that happens when a certain type is expected
    *  but another one is found.
    */
   class TypeMismatchError: public LuaValueError
   {
      public:
         /** Constructs a \c TypeMismatchError object.
          *  @param expectedType The type that was expected.
          *  @param foundType The type that was actually found.
          */
         TypeMismatchError (const std::string& expectedType,
                            const std::string& foundType);

         /** Destroys a \c TypeMismatchError object.
          *  @note This was defined just to pretend that the destructor does not
          *        throw any exception. While this is something that I cannot
          *        guarantee (at least whit this implementation), I believe this
          *        not a very dangerous lie.
          */
         ~TypeMismatchError() throw() { };

         /// Returns the type that was expected.
         std::string getExpectedType() { return expectedType_; }

         /// Returns the type that was actually found.
         std::string getFoundType() { return foundType_; }

      private:
         /// The type that was expected.
         std::string expectedType_;

         /// The type that was actually found.
         std::string foundType_;
   };

   /// A class that somewhat mimics a Lua value.
   class LuaValue
   {
      public:
         /// Constructs a \c LuaValue with a \c nil value.
         LuaValue() { };

         /// Constructs a \c LuaValue with boolean type and \c b value.
         LuaValue (bool b)
            : value_(b)
         { }

         /// Constructs a \c LuaValue with number type and \c n value.
         LuaValue (lua_Number n)
            : value_(n)
         { }

         /// Constructs a \c LuaValue with string type and \c s value.
         LuaValue (const std::string& s)
            : value_(s)
         { }

         /// Constructs a \c LuaValue with string type and \c s value.
         LuaValue (const char* s)
            : value_(std::string(s))
         { }

         /// Constructs a \c LuaValue with table type and \c t value.
         LuaValue (const LuaValueMap& t)
            : value_(t)
         { }

         /** Returns one of the <tt>LUA_T*</tt> constants from <tt>lua.h</tt>,
          *  representing the type stored in this \c LuaValue.
          */
         int type() const;

         /** Returns the type of this \c LuaValue as a string, just like the Lua
          *  built-in function \c type().
          *  @return One of the following strings: <tt>"nil"</tt>,
          *          <tt>"boolean"</tt>, <tt>"number"</tt>, <tt>"string"</tt>,
          *          <tt>"table"</tt>. If the stored value is different than
          *          those for some reason, returns an empty string
          *          (<tt>""</tt>).
          */
         std::string typeName() const;

         /** Return the value as a number.
          *  @throw TypeMismatchError If the value is not a number (this is a
          *         strict check; no type conversion is performed).
          */
         lua_Number asNumber() const;

         /** Return the value as a string.
          *  @throw TypeMismatchError If the value is not a string (this is a
          *         strict check; no type conversion is performed).
          */
         std::string asString() const;

         /** Return the value as a boolean.
          *  @throw TypeMismatchError If the value is not a boolean (this is a
          *         strict check; no type conversion is performed).
          */
         bool asBoolean() const;

         /** Return the value as a table (\c LuaValueMap).
          *  @throw TypeMismatchError If the value is not a table (this is a
          *         strict check; no type conversion is performed).
          */
         LuaValueMap asTable() const;

         /** "Less than" operator for <tt>LuaValue</tt>s.
          *  @return The order relationship is quite arbitrary for
          *          <tt>LuaValue</tt>s, but this has to be defined in order to
          *          \c LuaValueMap work nicely. Anyway, here are the rules used
          *          to determine who is less than who:
          *          - First, \c typeName() is called for both
          *            <tt>LuaValue</tt>s and they are compared with the usual
          *            "less than" operator for strings.
          *          - If both type names are equal, but something different
          *            than <tt>"nil"</tt> or <tt>"table"</tt>, then the values
          *            contained in the <tt>LuaValue</tt>s are compared using
          *            the usual "less than" operator for that type.
          *          - If both type names are <tt>"nil"</tt>, the function
          *            returns \c false.
          *          - If both type names are <tt>"table"</tt>, then the number
          *            of elements in each table are compared. The shorter table
          *            is "less than" the larger table.
          *          - If both tables have the same size, then each entry is
          *            recursively compared (that is, using the rules described
          *            here). For each entry, the key is compared first, than
          *            the value. This is done until finding something "less
          *            than" the other thing.
          *          - If no differences are found, \c false is obviously
          *            returned.
          */
         bool operator< (const LuaValue& rhs) const;

         /** "Greater than" operator for <tt>LuaValue</tt>s.
          *  @return The rules for determining who is greater than who are
          *          similar to the ones described in \c operator<.
          */
         bool operator> (const LuaValue& rhs) const;

         // TODO: A shortcut for table-like access:
         //       LuaValue& operator[] (const LuaValue& key) { return ...; }
         // TODO: Notice the reference return value above. Is this supported by
         //       'boost::any'? If not, will have to use a more traditional
         //       design ('union' anyone?)
         // TODO: 'operator==()' for all supported types:
         //       if (myLuaValue == "bl")
         //          ...;
         //       (perhaps also do this for '<', '>' and '!=')
         // TODO: Replace those 'lua_Number's with 'double's and add explicit
         //       support for 'int's and friends. This makes the typical use
         //       much more natural. I don't think I'll ever compile Lua to use
         //       integers instead of floating point numbers...
         // TODO: After doing the previous TODO, change the tests in
         //       'TestLuaStateDoStringMultiRet()' to use integer indices, not
         //       those ugly floats.
      private:
         /// Stores the value (and the type) stored in this \c LuaValue.
         boost::any value_;
   };

   /// A constant with the value of \c nil.
   const LuaValue Nil;

   /// A constant with value of an empty table.
   const LuaValueMap EmptyLuaValueMap;
   const LuaValue EmptyTable (EmptyLuaValueMap);

} // namespace Diluculum

#endif // _DILUCULUM_LUA_VALUE_HPP_
<|endoftext|>


<commit_before>// dune-multiscale
// Copyright Holders: Patrick Henning, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef SUBGRIDLIST_HH
#define SUBGRIDLIST_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <boost/noncopyable.hpp>
#include <boost/multi_array.hpp>

#include <dune/common/fmatrix.hh>
#include <dune/common/shared_ptr.hh>
#include <dune/common/exceptions.hh>
#include <dune/stuff/grid/entity.hh>

#include <dune/multiscale/tools/subgrid_io.hh>
#include <dune/subgrid/subgrid.hh>

#include <dune/fem/quadrature/cachingquadrature.hh>
#include <dune/fem/operator/common/operator.hh>
#include <dune/fem/gridpart/adaptiveleafgridpart.hh>
#include <dune/fem/space/lagrange.hh>
//#include <dune/fem/function/adaptivefunction.hh>
#include <dune/fem/operator/2order/lagrangematrixsetup.hh>

#include <dune/multiscale/msfem/msfem_traits.hh>
#include <dune/multiscale/msfem/msfem_grid_specifier.hh>

namespace Dune {
namespace Multiscale {
namespace MsFEM {

//! container for cell problem subgrids
class SubGridList : public boost::noncopyable
{
  typedef typename CommonTraits::DiscreteFunctionType HostDiscreteFunctionImp;
  typedef MsFEMTraits::SubGridType SubGridImp;
  typedef MsFEMTraits::MacroMicroGridSpecifierType MacroMicroGridSpecifierImp;

public:
  //! ---------------- typedefs for the HostDiscreteFunctionSpace -----------------------

  typedef MacroMicroGridSpecifierImp MacroMicroGridSpecifierType;
  typedef HostDiscreteFunctionImp HostDiscreteFunctionType;
  //! type of discrete function space
  typedef typename HostDiscreteFunctionType::DiscreteFunctionSpaceType HostDiscreteFunctionSpaceType;
  //! type of grid partition
  typedef typename HostDiscreteFunctionSpaceType::GridPartType HostGridPartType;

  //! type of grid
private:
  typedef typename HostDiscreteFunctionSpaceType::GridType HostGridType;
  typedef typename HostGridType::Traits::LeafIndexSet HostGridLeafIndexSet;
  typedef typename HostDiscreteFunctionSpaceType::IteratorType HostGridEntityIteratorType;
  typedef typename HostGridEntityIteratorType::Entity HostEntityType;
  typedef typename HostEntityType::EntityPointer HostEntityPointerType;
  typedef typename HostEntityType::Codim< HostGridType::dimension >::EntityPointer HostNodePointer;
  typedef typename HostGridPartType::IntersectionIteratorType HostIntersectionIterator;

  typedef typename MsFEMTraits::CoarseEntityType CoarseEntityType;

  //! type of (non-discrete )function space
  typedef typename HostDiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;

  //! type of domain
  typedef typename FunctionSpaceType::DomainType DomainType;

public:
  typedef std::vector< DomainType > CoarseNodeVectorType;

private:
  typedef std::vector< CoarseNodeVectorType > CoarseGridNodeStorageType;
  typedef boost::multi_array<bool, 3> EnrichmentMatrixType;
  //! @todo this should eventually be changed to the type of the coarse space
  typedef typename HostGridPartType::Codim<0>::EntityType::Geometry::LocalCoordinate LocalCoordinateType;
  typedef GenericReferenceElements< typename  LocalCoordinateType::value_type,  LocalCoordinateType::dimension >
          CoarseRefElementType;
  typedef std::vector<std::vector<HostEntityPointerType>> EntityPointerCollectionType;

public:
  //! ---------------- typedefs for the SubgridDiscreteFunctionSpace -----------------------
  // ( typedefs for the local grid and the corresponding local ('sub') )discrete space )

  //! type of grid
  typedef SubGridImp SubGridType;

  //! type of grid part
  typedef Fem::LeafGridPart< SubGridType > SubGridPartType;

    //! type of subgrid discrete function space
  typedef Fem::LagrangeDiscreteFunctionSpace< FunctionSpaceType, SubGridPartType, 1/*=POLORDER*/ > SubGridDiscreteFunctionSpace;

  //! type of subgrid discrete function
  typedef Fem::AdaptiveDiscreteFunction< SubGridDiscreteFunctionSpace > SubGridDiscreteFunction;

  SubGridList(MacroMicroGridSpecifierType& specifier, bool silent = true);
  ~SubGridList();
private:
  SubGridType& getSubGrid(int i);
  const SubGridType& getSubGrid(int i) const;
public:
  const SubGridType& getSubGrid(const CoarseEntityType& entity) const;
  SubGridType& getSubGrid(const CoarseEntityType& entity);

  int getNumberOfSubGrids() const;

  SubGridPartType gridPart(int i);

  // given the index of a (codim 0) host grid entity, return the indices of the subgrids that contain the entity
  const std::vector< int >& getSubgridIDs_that_contain_entity (int host_enitity_index) const;

  // only required for oversampling strategies with constraints (e.g strategy 2 or 3):
  const CoarseNodeVectorType& getCoarseNodeVector(int i) const;

  /** Get the index of the coarse cell enclosing the barycentre of a given fine cell.
*
* Given a fine cell, this method computes its barycentre. Using a grid run on the coarse
* grid, it checks which (if any) coarse cell contains the barycentre.
*
* @param[in] hostEntity The host entity.
* @param[in,out] lastIterator The macro cell that was found in the last run. This should be set to
*                             coarseGrid.begin<0>() in the first run. This iterator will then be
*                             updated and set to the macro element used in this run.
* @param[in] coarseGridLeafIndexSet The index set of the coarse grid.
*
*/
  int getEnclosingMacroCellIndex(const HostEntityPointerType& hostEntityPointer);

  int getEnclosingMacroCellId(const HostEntityPointerType& hostEntityPointer);

  /** Get the mapping from node number to codim 0 host entity.
  * @return Returns the map.
  * */
  const EntityPointerCollectionType& getNodeEntityMap();

private:
  typedef std::map<int, std::shared_ptr<SubGridType> > SubGridStorageType;
  /**
   * \note called in SubGridList constructor only
   */
  void enrichment(const HostEntityPointerType& hit,
//          const HostEntityPointerType& level_father_it,
          const int& father_index, // father_index = index/number of current subgrid
          shared_ptr<SubGridType> subGrid,
          int& layer);
  bool entityPatchInSubgrid(const HostEntityPointerType& hit,
          const HostGridPartType& hostGridPart,
          shared_ptr<const SubGridType> subGrid,
          const EntityPointerCollectionType& entities_sharing_same_node) const;

  void identifySubGrids();
  void createSubGrids();
  void finalizeSubGrids();

  const HostDiscreteFunctionSpaceType& hostSpace_;
  const HostDiscreteFunctionSpaceType& coarseSpace_;
  MacroMicroGridSpecifierType& specifier_;
  bool silent_;
  SubGridStorageType subGridList_;
  CoarseGridNodeStorageType coarse_node_store_;
  const HostGridLeafIndexSet& coarseGridLeafIndexSet_;
  const HostGridLeafIndexSet& hostGridLeafIndexSet_;
  const HostGridPartType& hostGridPart_;
  EntityPointerCollectionType entities_sharing_same_node_;
  EnrichmentMatrixType enriched_;
  std::vector<std::map<int, int> > fineToCoarseMap_;
  std::map<int, int> fineToCoarseMapID_;
  // given the id of a fine grid element, the vector returns the ids of all subgrids that share that element
  std::vector < std::vector< int > > fine_id_to_subgrid_ids_;
};

} //namespace MsFEM {
} //namespace Multiscale {
} //namespace Dune {

#endif // #ifndef SUBGRIDLIST_HH

<commit_msg>Fixed deprecation warning<commit_after>// dune-multiscale
// Copyright Holders: Patrick Henning, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef SUBGRIDLIST_HH
#define SUBGRIDLIST_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <boost/noncopyable.hpp>
#include <boost/multi_array.hpp>

#include <dune/common/fmatrix.hh>
#include <dune/common/shared_ptr.hh>
#include <dune/common/exceptions.hh>
#include <dune/stuff/grid/entity.hh>

#include <dune/multiscale/tools/subgrid_io.hh>
#include <dune/subgrid/subgrid.hh>

#include <dune/fem/quadrature/cachingquadrature.hh>
#include <dune/fem/operator/common/operator.hh>
#include <dune/fem/gridpart/adaptiveleafgridpart.hh>
#include <dune/fem/space/lagrange.hh>
//#include <dune/fem/function/adaptivefunction.hh>
#include <dune/fem/operator/2order/lagrangematrixsetup.hh>

#include <dune/multiscale/msfem/msfem_traits.hh>
#include <dune/multiscale/msfem/msfem_grid_specifier.hh>

namespace Dune {
namespace Multiscale {
namespace MsFEM {

//! container for cell problem subgrids
class SubGridList : public boost::noncopyable
{
  typedef typename CommonTraits::DiscreteFunctionType HostDiscreteFunctionImp;
  typedef MsFEMTraits::SubGridType SubGridImp;
  typedef MsFEMTraits::MacroMicroGridSpecifierType MacroMicroGridSpecifierImp;

public:
  //! ---------------- typedefs for the HostDiscreteFunctionSpace -----------------------

  typedef MacroMicroGridSpecifierImp MacroMicroGridSpecifierType;
  typedef HostDiscreteFunctionImp HostDiscreteFunctionType;
  //! type of discrete function space
  typedef typename HostDiscreteFunctionType::DiscreteFunctionSpaceType HostDiscreteFunctionSpaceType;
  //! type of grid partition
  typedef typename HostDiscreteFunctionSpaceType::GridPartType HostGridPartType;

  //! type of grid
private:
  typedef typename HostDiscreteFunctionSpaceType::GridType HostGridType;
  typedef typename HostGridType::Traits::LeafIndexSet HostGridLeafIndexSet;
  typedef typename HostDiscreteFunctionSpaceType::IteratorType HostGridEntityIteratorType;
  typedef typename HostGridEntityIteratorType::Entity HostEntityType;
  typedef typename HostEntityType::EntityPointer HostEntityPointerType;
  typedef typename HostEntityType::Codim< HostGridType::dimension >::EntityPointer HostNodePointer;
  typedef typename HostGridPartType::IntersectionIteratorType HostIntersectionIterator;

  typedef typename MsFEMTraits::CoarseEntityType CoarseEntityType;

  //! type of (non-discrete )function space
  typedef typename HostDiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;

  //! type of domain
  typedef typename FunctionSpaceType::DomainType DomainType;

public:
  typedef std::vector< DomainType > CoarseNodeVectorType;

private:
  typedef std::vector< CoarseNodeVectorType > CoarseGridNodeStorageType;
  typedef boost::multi_array<bool, 3> EnrichmentMatrixType;
  //! @todo this should eventually be changed to the type of the coarse space
  typedef typename HostGridPartType::Codim<0>::EntityType::Geometry::LocalCoordinate LocalCoordinateType;
  typedef ReferenceElements< typename  LocalCoordinateType::value_type,  LocalCoordinateType::dimension >
          CoarseRefElementType;
  typedef std::vector<std::vector<HostEntityPointerType>> EntityPointerCollectionType;

public:
  //! ---------------- typedefs for the SubgridDiscreteFunctionSpace -----------------------
  // ( typedefs for the local grid and the corresponding local ('sub') )discrete space )

  //! type of grid
  typedef SubGridImp SubGridType;

  //! type of grid part
  typedef Fem::LeafGridPart< SubGridType > SubGridPartType;

    //! type of subgrid discrete function space
  typedef Fem::LagrangeDiscreteFunctionSpace< FunctionSpaceType, SubGridPartType, 1/*=POLORDER*/ > SubGridDiscreteFunctionSpace;

  //! type of subgrid discrete function
  typedef Fem::AdaptiveDiscreteFunction< SubGridDiscreteFunctionSpace > SubGridDiscreteFunction;

  SubGridList(MacroMicroGridSpecifierType& specifier, bool silent = true);
  ~SubGridList();
private:
  SubGridType& getSubGrid(int i);
  const SubGridType& getSubGrid(int i) const;
public:
  const SubGridType& getSubGrid(const CoarseEntityType& entity) const;
  SubGridType& getSubGrid(const CoarseEntityType& entity);

  int getNumberOfSubGrids() const;

  SubGridPartType gridPart(int i);

  // given the index of a (codim 0) host grid entity, return the indices of the subgrids that contain the entity
  const std::vector< int >& getSubgridIDs_that_contain_entity (int host_enitity_index) const;

  // only required for oversampling strategies with constraints (e.g strategy 2 or 3):
  const CoarseNodeVectorType& getCoarseNodeVector(int i) const;

  /** Get the index of the coarse cell enclosing the barycentre of a given fine cell.
*
* Given a fine cell, this method computes its barycentre. Using a grid run on the coarse
* grid, it checks which (if any) coarse cell contains the barycentre.
*
* @param[in] hostEntity The host entity.
* @param[in,out] lastIterator The macro cell that was found in the last run. This should be set to
*                             coarseGrid.begin<0>() in the first run. This iterator will then be
*                             updated and set to the macro element used in this run.
* @param[in] coarseGridLeafIndexSet The index set of the coarse grid.
*
*/
  int getEnclosingMacroCellIndex(const HostEntityPointerType& hostEntityPointer);

  int getEnclosingMacroCellId(const HostEntityPointerType& hostEntityPointer);

  /** Get the mapping from node number to codim 0 host entity.
  * @return Returns the map.
  * */
  const EntityPointerCollectionType& getNodeEntityMap();

private:
  typedef std::map<int, std::shared_ptr<SubGridType> > SubGridStorageType;
  /**
   * \note called in SubGridList constructor only
   */
  void enrichment(const HostEntityPointerType& hit,
//          const HostEntityPointerType& level_father_it,
          const int& father_index, // father_index = index/number of current subgrid
          shared_ptr<SubGridType> subGrid,
          int& layer);
  bool entityPatchInSubgrid(const HostEntityPointerType& hit,
          const HostGridPartType& hostGridPart,
          shared_ptr<const SubGridType> subGrid,
          const EntityPointerCollectionType& entities_sharing_same_node) const;

  void identifySubGrids();
  void createSubGrids();
  void finalizeSubGrids();

  const HostDiscreteFunctionSpaceType& hostSpace_;
  const HostDiscreteFunctionSpaceType& coarseSpace_;
  MacroMicroGridSpecifierType& specifier_;
  bool silent_;
  SubGridStorageType subGridList_;
  CoarseGridNodeStorageType coarse_node_store_;
  const HostGridLeafIndexSet& coarseGridLeafIndexSet_;
  const HostGridLeafIndexSet& hostGridLeafIndexSet_;
  const HostGridPartType& hostGridPart_;
  EntityPointerCollectionType entities_sharing_same_node_;
  EnrichmentMatrixType enriched_;
  std::vector<std::map<int, int> > fineToCoarseMap_;
  std::map<int, int> fineToCoarseMapID_;
  // given the id of a fine grid element, the vector returns the ids of all subgrids that share that element
  std::vector < std::vector< int > > fine_id_to_subgrid_ids_;
};

} //namespace MsFEM {
} //namespace Multiscale {
} //namespace Dune {

#endif // #ifndef SUBGRIDLIST_HH

<|endoftext|>


<commit_before>/**
 * PcapSearch application
 * ======================
 * This application searches all pcap files in a given directory and all its sub-directories (unless stated otherwise) and outputs how many and which
 * packets in those files match a certain pattern given by the user. The pattern is given in Berkeley Packet Filter (BPF) syntax
 * (http://biot.com/capstats/bpf.html). For example: if running the application with the following parameters:
 * PcapSearch.exe -d C:\ -s "ip net 1.1.1.1" -r C:\report.txt
 * The application will search all '.pcap' files in all directories under C drive and try to match packets that matches IP 1.1.1.1. The result will be
 * printed to stdout and a more detailed report will be printed to c:\report.txt
 * Output example:
 *    1 packets found in 'C:\\path\example\Dns.pcap'
 *    5 packets found in 'C:\\path\example\bla1\my_pcap2.pcap'
 *    7299 packets found in 'C:\\path2\example\example2\big_pcap.pcap'
 *    7435 packets found in 'C:\\path3\dir1\dir2\dir3\dir4\another.pcap'
 *    435 packets found in 'C:\\path3\dirx\diry\dirz\ok.pcap'
 *    4662 packets found in 'C:\\path4\gotit.pcap'
 *    7299 packets found in 'C:\\enough.pcap'
 *
 * There are switches that allows the user to search only in the provided folder (without sub-directories), search user-defined file extensions (sometimes
 * pcap files have an extension which is not '.pcap'), and output or not output the detailed report
 *
 * For more details about modes of operation and parameters please run PcapSearch -h
 */

#include <stdlib.h>
#include <getopt.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <sys/stat.h>
#include <dirent.h>
#include <vector>
#include <map>
#include <Logger.h>
#include <RawPacket.h>
#include <Packet.h>
#include <PcapFileDevice.h>

using namespace pcpp;

static struct option PcapSearchOptions[] =
{
	{"input-dir",  required_argument, 0, 'd'},
	{"not-include-sub-dir", no_argument, 0, 'n'},
	{"search", required_argument, 0, 's'},
	{"detailed-report", required_argument, 0, 'r'},
	{"set-extensions", required_argument, 0, 'e'},
	{"help", no_argument, 0, 'h'},
    {0, 0, 0, 0}
};

#define EXIT_WITH_ERROR(reason, ...) do { \
	printf("\nError: " reason "\n\n", ## __VA_ARGS__); \
	printUsage(); \
	exit(1); \
	} while(0)

#ifdef WIN32
#define DIR_SEPARATOR "\\"
#else
#define DIR_SEPARATOR "/"
#endif

#define ERROR_STRING_LEN 500

char errorString[ERROR_STRING_LEN];

/**
 * Print application usage
 */
void printUsage()
{
	printf("\nUsage:\n"
			"-------\n"
			"PcapPrinter [-h] [-n] [-r file_name] [-e extension_list] -d directory -s search_criteria\n"
			"\nOptions:\n\n"
			"    -d directory        : Input directory\n"
			"    -n                  : Don't include sub-directories (default is include them)\n"
			"    -s search_criteria  : Criteria to search in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'\n"
			"    -r file_name        : Write a detailed search report to a file\n"
			"    -e extension_list   : Set file extensions to search. The default is searching '.pcap' files only.\n"
			"                          extnesions_list should be a comma-separated list of extensions, for example: pcap,net,dmp\n"
			"    -h                  : Displays this help message and exits\n");
	exit(0);
}

/*
 * Returns the extension of a given file name
 */
std::string getExtension(std::string fileName)
{
	return fileName.substr(fileName.find_last_of(".") + 1);
}

/**
 * Searches all packet in a given pcap file for a certain search criteria. Returns how many packets matched the seatch criteria
 */
int searchPcap(std::string pcapFilePath, std::string searchCriteria, std::ofstream* detailedReportFile)
{
	// create the pcap reader
	PcapFileReaderDevice reader(pcapFilePath.c_str());

	// if the reader fails to open
	if (!reader.open())
	{
		if (detailedReportFile != NULL)
		{
			// PcapPlusPlus writes the error to the error string variable we set it to write to
			// write this error to the report file
			(*detailedReportFile) << "File '" << pcapFilePath << "':" << std::endl;
			(*detailedReportFile) << "    ";
			std::string errorStr = errorString;
			(*detailedReportFile) << errorStr << std::endl;
		}

		return 0;
	}

	// set the filter for the file so only packets that match the search criteria will be read
	if (!reader.setFilter(searchCriteria))
	{
		return 0;
	}

	if (detailedReportFile != NULL)
	{
		(*detailedReportFile) << "File '" << pcapFilePath << "':" << std::endl;
	}

	int packetCount = 0;
	RawPacket rawPacket;

	// read packets from the file. Since we already set the filter, only packets that matches the filter will be read
	while (reader.getNextPacket(rawPacket))
	{
		// if a detailed report is required, parse the packet and print it to the report file
		if (detailedReportFile != NULL)
		{
			// parse the packet
			Packet parsedPacket(&rawPacket);

			// print layer by layer by layer as we want to add a few spaces before each layer
			std::vector<std::string> packetLayers;
			parsedPacket.printToStringList(packetLayers);
			for (std::vector<std::string>::iterator iter = packetLayers.begin(); iter != packetLayers.end(); iter++)
				(*detailedReportFile) << "\n    " << (*iter);
			(*detailedReportFile) << std::endl;
		}

		// count the packet read
		packetCount++;
	}

	// close the reader file
	reader.close();

	// finalize the report
	if (detailedReportFile != NULL)
	{
		if (packetCount > 0)
			(*detailedReportFile) << "\n";

		(*detailedReportFile) << "    ----> Found " << packetCount << " packets" << std::endl << std::endl;

	}

	// return how many packets matched the search criteria
	return packetCount;
}

/**
 * Searches all pcap files in given directory (and sub-directories if directed by the user) and output how many packets in each file matches a given
 * search criteria. This method outputs how many directories were searched, how many files were searched and how many packets were matched
 */
void searchtDirectories(std::string directory, bool includeSubDirectories, std::string searchCriteria, std::ofstream* detailedReportFile,
		std::map<std::string, bool> extensionsToSearch,
		int& totalDirSearched, int& totalFilesSearched, int& totalPacketsFound)
{
    // open the directory
    DIR *dir = opendir(directory.c_str());

    // dir is null usually when user has no access permissions
    if (dir == NULL)
        return;

    struct dirent *entry = readdir(dir);

    std::vector<std::string> pcapList;

    // go over all files in this directory
    while (entry != NULL)
    {
    	std::string name(entry->d_name);
    	std::string dirPath = directory + DIR_SEPARATOR + name;
    	struct stat info;

    	// get file attributes
    	if (stat(dirPath.c_str(), &info) != 0)
    	{
    		entry = readdir(dir);
    		continue;
    	}

    	// if the file is not a directory
    	if (!(info.st_mode & S_IFDIR))
    	{
    		// check if the file extension matches the requested extensions to search. If it does, put the file name in a list of files
    		// that should be searched (don't do the search just yet)
    		if (extensionsToSearch.find(getExtension(name)) != extensionsToSearch.end())
    			pcapList.push_back(dirPath);
    		entry = readdir(dir);
    		continue;
    	}

    	// if the file is a '.' or '..' skip it
    	if (name == "." || name == "..")
    	{
    		entry = readdir(dir);
    		continue;
    	}

    	// if we got to here it means the file is actually a directory. If required to search sub-directories, call this method recursively to search
    	// inside this sub-directory
        if (includeSubDirectories)
        	searchtDirectories(dirPath, true, searchCriteria, detailedReportFile, extensionsToSearch, totalDirSearched, totalFilesSearched, totalPacketsFound);

        // move to the next file
        entry = readdir(dir);
    }

    // close dir
    closedir(dir);

    totalDirSearched++;

    // when we get to here we already covered all sub-directories and collected all the files in this directory that are required for search
    // go over each such file and search its packets to find the search criteria
    for (std::vector<std::string>::iterator iter = pcapList.begin(); iter != pcapList.end(); iter++)
    {
    	// do the actual search
    	int packetsFound = searchPcap(*iter, searchCriteria, detailedReportFile);

    	// add to total matched packets
    	totalFilesSearched++;
    	if (packetsFound > 0)
    	{
    		printf("%d packets found in '%s'\n", packetsFound, iter->c_str());
    		totalPacketsFound += packetsFound;
    	}
    }

}

/**
 * main method of this utility
 */
int main(int argc, char* argv[])
{
	std::string inputDirectory = "";

	std::string searchCriteria = "";

	bool includeSubDirectories = true;

	std::string detailedReportFileName = "";

	std::map<std::string, bool> extensionsToSearch;

	// the default (unless set otherwise) is to search in '.pcap' extension only
	extensionsToSearch["pcap"] = true;

	int optionIndex = 0;
	char opt = 0;

	while((opt = getopt_long (argc, argv, "d:s:r:e:hn", PcapSearchOptions, &optionIndex)) != -1)
	{
		switch (opt)
		{
			case 0:
				break;
			case 'd':
				inputDirectory = optarg;
				break;
			case 'n':
				includeSubDirectories = false;
				break;
			case 's':
				searchCriteria = optarg;
				break;
			case 'r':
				detailedReportFileName = optarg;
				break;
			case 'e':
			{
				// read the extension list into the map
				extensionsToSearch.clear();
				std::string extensionsListAsString = std::string(optarg);
				std::stringstream stream(extensionsListAsString);
				std::string extension;
				// break comma-separated string into string list
				while(std::getline(stream, extension, ','))
				{
					// add the extension into the map if it doesn't already exist
					if (extensionsToSearch.find(extension) == extensionsToSearch.end())
						extensionsToSearch[extension] = true;
				}

				// verify list is not empty
				if (extensionsToSearch.empty())
				{
					EXIT_WITH_ERROR("Couldn't parse extensions list");
				}
				break;
			}
			case 'h':
				printUsage();
				break;
			default:
				printUsage();
				exit(-1);
		}
	}

	if (inputDirectory == "")
	{
		EXIT_WITH_ERROR("Input directory was not given");
	}

	if (searchCriteria == "")
	{
		EXIT_WITH_ERROR("Search criteria was not given");
	}

	DIR *dir = opendir(inputDirectory.c_str());
	if (dir == NULL)
	{
		EXIT_WITH_ERROR("Cannot find or open input directory");
	}

	// verify the search criteria is a valid BPF filter
	if (!pcpp::IPcapDevice::verifyFilter(searchCriteria))
	{
		EXIT_WITH_ERROR("Search criteria isn't valid");
	}

	// open the detailed report file if requested by the user
	std::ofstream* detailedReportFile = NULL;
	if (detailedReportFileName != "")
	{
		detailedReportFile = new std::ofstream();
		detailedReportFile->open(detailedReportFileName.c_str());
		if (detailedReportFile->fail())
		{
			EXIT_WITH_ERROR("Couldn't open detailed report file '%s' for writing", detailedReportFileName.c_str());
		}

		// in cases where the user requests a detailed report, all errors will be written to the report also. That's why we need to save the error messages
		// to a variable and write them to the report file later
		pcpp::LoggerPP::getInstance().setErrorString(errorString, ERROR_STRING_LEN);
	}

	printf("Searching...\n");
	int totalDirSearched = 0;
	int totalFilesSearched = 0;
	int totalPacketsFound = 0;

	// if input dir contains a directory separator at the end, remove it
	std::string dirSep = DIR_SEPARATOR;
	if (0 == inputDirectory.compare(inputDirectory.length() - dirSep.length(), dirSep.length(), dirSep))
	{
		inputDirectory = inputDirectory.substr(0, inputDirectory.size()-1);
	}

	// the main call - start searching!
	searchtDirectories(inputDirectory, includeSubDirectories, searchCriteria, detailedReportFile, extensionsToSearch, totalDirSearched, totalFilesSearched, totalPacketsFound);

	// after search is done, close the report file and delete its instance
	printf("\n\nDone! Searched %d files in %d directories, %d packets were matched to search criteria\n", totalFilesSearched, totalDirSearched, totalPacketsFound);
	if (detailedReportFile != NULL)
	{
		if (detailedReportFile->is_open())
			detailedReportFile->close();

		delete detailedReportFile;
		printf("Detailed report written to '%s'\n", detailedReportFileName.c_str());
	}

	return 0;
}
<commit_msg>Another bugfix in PcapSearch<commit_after>/**
 * PcapSearch application
 * ======================
 * This application searches all pcap files in a given directory and all its sub-directories (unless stated otherwise) and outputs how many and which
 * packets in those files match a certain pattern given by the user. The pattern is given in Berkeley Packet Filter (BPF) syntax
 * (http://biot.com/capstats/bpf.html). For example: if running the application with the following parameters:
 * PcapSearch.exe -d C:\ -s "ip net 1.1.1.1" -r C:\report.txt
 * The application will search all '.pcap' files in all directories under C drive and try to match packets that matches IP 1.1.1.1. The result will be
 * printed to stdout and a more detailed report will be printed to c:\report.txt
 * Output example:
 *    1 packets found in 'C:\\path\example\Dns.pcap'
 *    5 packets found in 'C:\\path\example\bla1\my_pcap2.pcap'
 *    7299 packets found in 'C:\\path2\example\example2\big_pcap.pcap'
 *    7435 packets found in 'C:\\path3\dir1\dir2\dir3\dir4\another.pcap'
 *    435 packets found in 'C:\\path3\dirx\diry\dirz\ok.pcap'
 *    4662 packets found in 'C:\\path4\gotit.pcap'
 *    7299 packets found in 'C:\\enough.pcap'
 *
 * There are switches that allows the user to search only in the provided folder (without sub-directories), search user-defined file extensions (sometimes
 * pcap files have an extension which is not '.pcap'), and output or not output the detailed report
 *
 * For more details about modes of operation and parameters please run PcapSearch -h
 */

#include <stdlib.h>
#include <getopt.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <sys/stat.h>
#include <dirent.h>
#include <vector>
#include <map>
#include <Logger.h>
#include <RawPacket.h>
#include <Packet.h>
#include <PcapFileDevice.h>

using namespace pcpp;

static struct option PcapSearchOptions[] =
{
	{"input-dir",  required_argument, 0, 'd'},
	{"not-include-sub-dir", no_argument, 0, 'n'},
	{"search", required_argument, 0, 's'},
	{"detailed-report", required_argument, 0, 'r'},
	{"set-extensions", required_argument, 0, 'e'},
	{"help", no_argument, 0, 'h'},
    {0, 0, 0, 0}
};

#define EXIT_WITH_ERROR(reason, ...) do { \
	printf("\nError: " reason "\n\n", ## __VA_ARGS__); \
	printUsage(); \
	exit(1); \
	} while(0)

#ifdef WIN32
#define DIR_SEPARATOR "\\"
#else
#define DIR_SEPARATOR "/"
#endif

#define ERROR_STRING_LEN 500

char errorString[ERROR_STRING_LEN];

/**
 * Print application usage
 */
void printUsage()
{
	printf("\nUsage:\n"
			"-------\n"
			"PcapPrinter [-h] [-n] [-r file_name] [-e extension_list] -d directory -s search_criteria\n"
			"\nOptions:\n\n"
			"    -d directory        : Input directory\n"
			"    -n                  : Don't include sub-directories (default is include them)\n"
			"    -s search_criteria  : Criteria to search in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'\n"
			"    -r file_name        : Write a detailed search report to a file\n"
			"    -e extension_list   : Set file extensions to search. The default is searching '.pcap' files only.\n"
			"                          extnesions_list should be a comma-separated list of extensions, for example: pcap,net,dmp\n"
			"    -h                  : Displays this help message and exits\n");
	exit(0);
}

/*
 * Returns the extension of a given file name
 */
std::string getExtension(std::string fileName)
{
	return fileName.substr(fileName.find_last_of(".") + 1);
}

/**
 * Searches all packet in a given pcap file for a certain search criteria. Returns how many packets matched the seatch criteria
 */
int searchPcap(std::string pcapFilePath, std::string searchCriteria, std::ofstream* detailedReportFile)
{
	// create the pcap reader
	PcapFileReaderDevice reader(pcapFilePath.c_str());

	// if the reader fails to open
	if (!reader.open())
	{
		if (detailedReportFile != NULL)
		{
			// PcapPlusPlus writes the error to the error string variable we set it to write to
			// write this error to the report file
			(*detailedReportFile) << "File '" << pcapFilePath << "':" << std::endl;
			(*detailedReportFile) << "    ";
			std::string errorStr = errorString;
			(*detailedReportFile) << errorStr << std::endl;
		}

		return 0;
	}

	// set the filter for the file so only packets that match the search criteria will be read
	if (!reader.setFilter(searchCriteria))
	{
		return 0;
	}

	if (detailedReportFile != NULL)
	{
		(*detailedReportFile) << "File '" << pcapFilePath << "':" << std::endl;
	}

	int packetCount = 0;
	RawPacket rawPacket;

	// read packets from the file. Since we already set the filter, only packets that matches the filter will be read
	while (reader.getNextPacket(rawPacket))
	{
		// if a detailed report is required, parse the packet and print it to the report file
		if (detailedReportFile != NULL)
		{
			// parse the packet
			Packet parsedPacket(&rawPacket);

			// print layer by layer by layer as we want to add a few spaces before each layer
			std::vector<std::string> packetLayers;
			parsedPacket.printToStringList(packetLayers);
			for (std::vector<std::string>::iterator iter = packetLayers.begin(); iter != packetLayers.end(); iter++)
				(*detailedReportFile) << "\n    " << (*iter);
			(*detailedReportFile) << std::endl;
		}

		// count the packet read
		packetCount++;
	}

	// close the reader file
	reader.close();

	// finalize the report
	if (detailedReportFile != NULL)
	{
		if (packetCount > 0)
			(*detailedReportFile) << "\n";

		(*detailedReportFile) << "    ----> Found " << packetCount << " packets" << std::endl << std::endl;

	}

	// return how many packets matched the search criteria
	return packetCount;
}

/**
 * Searches all pcap files in given directory (and sub-directories if directed by the user) and output how many packets in each file matches a given
 * search criteria. This method outputs how many directories were searched, how many files were searched and how many packets were matched
 */
void searchtDirectories(std::string directory, bool includeSubDirectories, std::string searchCriteria, std::ofstream* detailedReportFile,
		std::map<std::string, bool> extensionsToSearch,
		int& totalDirSearched, int& totalFilesSearched, int& totalPacketsFound)
{
    // open the directory
    DIR *dir = opendir(directory.c_str());

    // dir is null usually when user has no access permissions
    if (dir == NULL)
        return;

    struct dirent *entry = readdir(dir);

    std::vector<std::string> pcapList;

    // go over all files in this directory
    while (entry != NULL)
    {
    	std::string name(entry->d_name);

    	// construct directory full path
    	std::string dirPath = directory;
    	std::string dirSep = DIR_SEPARATOR;
    	if (0 != directory.compare(directory.length() - dirSep.length(), dirSep.length(), dirSep)) // directory doesn't contain separator in the end
    	    dirPath += DIR_SEPARATOR;
    	dirPath += name;

	struct stat info;

    	// get file attributes
    	if (stat(dirPath.c_str(), &info) != 0)
    	{
    		entry = readdir(dir);
    		continue;
    	}

    	// if the file is not a directory
    	if (!(info.st_mode & S_IFDIR))
    	{
    		// check if the file extension matches the requested extensions to search. If it does, put the file name in a list of files
    		// that should be searched (don't do the search just yet)
    		if (extensionsToSearch.find(getExtension(name)) != extensionsToSearch.end())
    			pcapList.push_back(dirPath);
    		entry = readdir(dir);
    		continue;
    	}

    	// if the file is a '.' or '..' skip it
    	if (name == "." || name == "..")
    	{
    		entry = readdir(dir);
    		continue;
    	}

    	// if we got to here it means the file is actually a directory. If required to search sub-directories, call this method recursively to search
    	// inside this sub-directory
        if (includeSubDirectories)
        	searchtDirectories(dirPath, true, searchCriteria, detailedReportFile, extensionsToSearch, totalDirSearched, totalFilesSearched, totalPacketsFound);

        // move to the next file
        entry = readdir(dir);
    }

    // close dir
    closedir(dir);

    totalDirSearched++;

    // when we get to here we already covered all sub-directories and collected all the files in this directory that are required for search
    // go over each such file and search its packets to find the search criteria
    for (std::vector<std::string>::iterator iter = pcapList.begin(); iter != pcapList.end(); iter++)
    {
    	// do the actual search
    	int packetsFound = searchPcap(*iter, searchCriteria, detailedReportFile);

    	// add to total matched packets
    	totalFilesSearched++;
    	if (packetsFound > 0)
    	{
    		printf("%d packets found in '%s'\n", packetsFound, iter->c_str());
    		totalPacketsFound += packetsFound;
    	}
    }

}

/**
 * main method of this utility
 */
int main(int argc, char* argv[])
{
	std::string inputDirectory = "";

	std::string searchCriteria = "";

	bool includeSubDirectories = true;

	std::string detailedReportFileName = "";

	std::map<std::string, bool> extensionsToSearch;

	// the default (unless set otherwise) is to search in '.pcap' extension only
	extensionsToSearch["pcap"] = true;

	int optionIndex = 0;
	char opt = 0;

	while((opt = getopt_long (argc, argv, "d:s:r:e:hn", PcapSearchOptions, &optionIndex)) != -1)
	{
		switch (opt)
		{
			case 0:
				break;
			case 'd':
				inputDirectory = optarg;
				break;
			case 'n':
				includeSubDirectories = false;
				break;
			case 's':
				searchCriteria = optarg;
				break;
			case 'r':
				detailedReportFileName = optarg;
				break;
			case 'e':
			{
				// read the extension list into the map
				extensionsToSearch.clear();
				std::string extensionsListAsString = std::string(optarg);
				std::stringstream stream(extensionsListAsString);
				std::string extension;
				// break comma-separated string into string list
				while(std::getline(stream, extension, ','))
				{
					// add the extension into the map if it doesn't already exist
					if (extensionsToSearch.find(extension) == extensionsToSearch.end())
						extensionsToSearch[extension] = true;
				}

				// verify list is not empty
				if (extensionsToSearch.empty())
				{
					EXIT_WITH_ERROR("Couldn't parse extensions list");
				}
				break;
			}
			case 'h':
				printUsage();
				break;
			default:
				printUsage();
				exit(-1);
		}
	}

	if (inputDirectory == "")
	{
		EXIT_WITH_ERROR("Input directory was not given");
	}

	if (searchCriteria == "")
	{
		EXIT_WITH_ERROR("Search criteria was not given");
	}

	DIR *dir = opendir(inputDirectory.c_str());
	if (dir == NULL)
	{
		EXIT_WITH_ERROR("Cannot find or open input directory");
	}

	// verify the search criteria is a valid BPF filter
	if (!pcpp::IPcapDevice::verifyFilter(searchCriteria))
	{
		EXIT_WITH_ERROR("Search criteria isn't valid");
	}

	// open the detailed report file if requested by the user
	std::ofstream* detailedReportFile = NULL;
	if (detailedReportFileName != "")
	{
		detailedReportFile = new std::ofstream();
		detailedReportFile->open(detailedReportFileName.c_str());
		if (detailedReportFile->fail())
		{
			EXIT_WITH_ERROR("Couldn't open detailed report file '%s' for writing", detailedReportFileName.c_str());
		}

		// in cases where the user requests a detailed report, all errors will be written to the report also. That's why we need to save the error messages
		// to a variable and write them to the report file later
		pcpp::LoggerPP::getInstance().setErrorString(errorString, ERROR_STRING_LEN);
	}

	printf("Searching...\n");
	int totalDirSearched = 0;
	int totalFilesSearched = 0;
	int totalPacketsFound = 0;

	// the main call - start searching!
	searchtDirectories(inputDirectory, includeSubDirectories, searchCriteria, detailedReportFile, extensionsToSearch, totalDirSearched, totalFilesSearched, totalPacketsFound);

	// after search is done, close the report file and delete its instance
	printf("\n\nDone! Searched %d files in %d directories, %d packets were matched to search criteria\n", totalFilesSearched, totalDirSearched, totalPacketsFound);
	if (detailedReportFile != NULL)
	{
		if (detailedReportFile->is_open())
			detailedReportFile->close();

		delete detailedReportFile;
		printf("Detailed report written to '%s'\n", detailedReportFileName.c_str());
	}

	return 0;
}
<|endoftext|>


<commit_before>//=====================================================================//
/*!	@file
	@brief	DS3231 RTC のテスト
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include<cstring>
#include "G13/system.hpp"
#include "G13/port.hpp"
#include "common/uart_io.hpp"
#include "common/fifo.hpp"
#include "common/format.hpp"
#include "common/iica_io.hpp"
#include "common/delay.hpp"
#include "common/itimer.hpp"
#include "common/command.hpp"
#include "common/time.h"
#include "chip/DS3231.hpp"

namespace {

	typedef device::iica_io<device::IICA0> IICA;
	IICA iica0_;

	chip::DS3231<IICA> rtc_(iica0_);

	typedef utils::fifo<128> buffer;

	device::uart_io<device::SAU00, device::SAU01, buffer, buffer> uart0_;

	device::itimer<uint8_t> itm_;

	utils::command<64> command_;
}

const void* ivec_[] __attribute__ ((section (".ivec"))) = {
	/*  0 */  nullptr,
	/*  1 */  nullptr,
	/*  2 */  nullptr,
	/*  3 */  nullptr,
	/*  4 */  nullptr,
	/*  5 */  nullptr,
	/*  6 */  nullptr,
	/*  7 */  nullptr,
	/*  8 */  nullptr,
	/*  9 */  nullptr,
	/* 10 */  nullptr,
	/* 11 */  nullptr,
	/* 12 */  nullptr,
	/* 13 */  reinterpret_cast<void*>(uart0_.send_task),
	/* 14 */  reinterpret_cast<void*>(uart0_.recv_task),
	/* 15 */  reinterpret_cast<void*>(uart0_.error_task),
	/* 16 */  nullptr,
	/* 17 */  nullptr,
	/* 18 */  nullptr,
	/* 19 */  nullptr,
	/* 20 */  nullptr,
	/* 21 */  nullptr,
	/* 22 */  nullptr,
	/* 23 */  nullptr,
	/* 24 */  nullptr,
	/* 25 */  nullptr,
	/* 26 */  reinterpret_cast<void*>(itm_.task),
};

extern "C" {
	void sci_putch(char ch)
	{
		uart0_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		uart0_.puts(str);
	}

	char sci_getch(void)
	{
		return uart0_.getch();
	}

	uint16_t sci_length()
	{
		return uart0_.recv_length();
	}
};

static const char* wday_[] = {
	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

static const char* mon_[] = {
	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

namespace {

	time_t get_time_()
	{
		time_t t = 0;
		if(!rtc_.get_time(t)) {
			utils::format("Stall RTC read (%d)\n") % static_cast<uint32_t>(iica0_.get_last_error());
		}
		return t;
	}

	void disp_time_(time_t t) {
		struct tm *m = gmtime(&t);
		utils::format("%s %s %d %02d:%02d:%02d  %4d\n")
			% wday_[m->tm_wday]
			% mon_[m->tm_mon]
			% static_cast<uint32_t>(m->tm_mday)
			% static_cast<uint32_t>(m->tm_hour)
			% static_cast<uint32_t>(m->tm_min)
			% static_cast<uint32_t>(m->tm_sec)
			% static_cast<uint32_t>(m->tm_year + 1900);
	}

	bool check_key_word_(uint8_t idx, const char* key)
	{
		char buff[12];
		if(command_.get_word(idx, sizeof(buff), buff)) {
			if(std::strcmp(buff, key) == 0) {
				return true;
			}
		}
		return false;
	}

	const char* get_dec_(const char* p, char tmch, int& value) {
		int v = 0;
		char ch;
		while((ch = *p) != 0) {
			++p;
			if(ch == tmch) {
				break;
			} else if(ch >= '0' && ch <= '9') {
				v *= 10;
				v += ch - '0';
			} else {
				return nullptr;
			}
		}
		value = v;
		return p;
	}

	void set_time_date_()
	{
		time_t t = get_time_();
		if(t == 0) return;

		struct tm *m = gmtime(&t);
		bool err = false;
		if(command_.get_words() == 3) {
			char buff[12];
			if(command_.get_word(1, sizeof(buff), buff)) {
				const char* p = buff;
				int vs[3];
				uint8_t i;
				for(i = 0; i < 3; ++i) {
					p = get_dec_(p, '/', vs[i]);
					if(p == nullptr) {
						break;
					}
				}
				if(p != nullptr && p[0] == 0 && i == 3) {
					if(vs[0] >= 1900 && vs[0] < 2100) m->tm_year = vs[0] - 1900;
					if(vs[1] >= 1 && vs[1] <= 12) m->tm_mon = vs[1] - 1;
					if(vs[2] >= 1 && vs[2] <= 31) m->tm_mday = vs[2];
				} else {
					err = true;
				}
			}

			if(command_.get_word(2, sizeof(buff), buff)) {
				const char* p = buff;
				int vs[3];
				uint8_t i;
				for(i = 0; i < 3; ++i) {
					p = get_dec_(p, ':', vs[i]);
					if(p == nullptr) {
						break;
					}
				}
				if(p != nullptr && p[0] == 0 && (i == 2 || i == 3)) {
					if(vs[0] >= 0 && vs[0] < 24) m->tm_hour = vs[0];
					if(vs[1] >= 0 && vs[1] < 60) m->tm_min = vs[1];
					if(i == 3 && vs[2] >= 0 && vs[2] < 60) m->tm_sec = vs[2];
					else m->tm_sec = 0;
				} else {
					err = true;
				}
			}
		}

		if(err) {
			sci_puts("Can't analize Time/Date input.\n");
			return;
		}

		time_t tt = mktime(m);
		if(!rtc_.set_time(tt)) {
			sci_puts("Stall RTC write...\n");
		}
	}
}

int main(int argc, char* argv[])
{
	using namespace device;

	PM4.B3 = 0;  // output

	// itimer の開始
	{
		uint8_t intr_level = 1;
		itm_.start(60, intr_level);
	}

	// UART0 の開始
	{
		uint8_t intr_level = 1;
		uart0_.start(115200, intr_level);
	}

	// IICA(I2C) の開始
	{
		uint8_t intr_level = 0;
		if(!iica0_.start(IICA::speed::fast, intr_level)) {
//		if(!iica0_.start(IICA::speed::standard, intr_level)) {
			utils::format("IICA start error (%d)\n") % static_cast<uint32_t>(iica0_.get_last_error());
		}
	}

	sci_puts("Start RL78/G13 DS3231(I2C-RTC) sample\n");

	// DS3231(RTC) の開始
	if(!rtc_.start()) {
		utils::format("Stall RTC start (%d)\n") % static_cast<uint32_t>(iica0_.get_last_error());
	}

	command_.set_prompt("# ");

	uint8_t cnt = 0;
	while(1) {
		itm_.sync();

		if(cnt >= 20) {
			cnt = 0;
		}
		if(cnt < 10) P4.B3 = 1;
		else P4.B3 = 0;
		++cnt;

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			uint8_t cmdn = command_.get_words();
			if(cmdn >= 1) {
				if(check_key_word_(0, "date")) {
					if(cmdn == 1) {
						time_t t = get_time_();
						if(t != 0) {
							disp_time_(t);
						}
					} else {
						set_time_date_();
					}
				} else if(check_key_word_(0, "help")) {
					sci_puts("date\n");
					sci_puts("date yyyy/mm/dd hh:mm[:ss]\n");
				} else {
					char buff[12];
					if(command_.get_word(0, sizeof(buff), buff)) {
						sci_puts("Command error: ");
						sci_puts(buff);
						sci_putch('\n');
					}
				}
			}
		}
	}
}
<commit_msg>change UART1<commit_after>//=====================================================================//
/*!	@file
	@brief	DS3231 RTC のテスト
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include<cstring>
#include "G13/system.hpp"
#include "G13/port.hpp"
#include "common/uart_io.hpp"
#include "common/fifo.hpp"
#include "common/format.hpp"
#include "common/iica_io.hpp"
#include "common/delay.hpp"
#include "common/itimer.hpp"
#include "common/command.hpp"
#include "common/time.h"
#include "chip/DS3231.hpp"

// どれか一つだけ有効にする。
// #define UART0
#define UART1

namespace {

	typedef device::iica_io<device::IICA0> IICA;
	IICA iica0_;

	chip::DS3231<IICA> rtc_(iica0_);

	typedef utils::fifo<128> buffer;

#ifdef UART0
	// UART0 の定義（SAU0、SAU1）
	device::uart_io<device::SAU00, device::SAU01, buffer, buffer> uart_;
#endif
#ifdef UART1
	// UART1 の定義（SAU2、SAU3）
	device::uart_io<device::SAU02, device::SAU03, buffer, buffer> uart_;
#endif

	device::itimer<uint8_t> itm_;

	utils::command<64> command_;
}

const void* ivec_[] __attribute__ ((section (".ivec"))) = {
	/*  0 */  nullptr,
	/*  1 */  nullptr,
	/*  2 */  nullptr,
	/*  3 */  nullptr,
	/*  4 */  nullptr,
	/*  5 */  nullptr,
	/*  6 */  nullptr,
	/*  7 */  nullptr,
	/*  8 */  nullptr,
	/*  9 */  nullptr,
	/* 10 */  nullptr,
	/* 11 */  nullptr,
	/* 12 */  nullptr,
	/* 13 */  reinterpret_cast<void*>(uart_.send_task),  // UART0-TX
	/* 14 */  reinterpret_cast<void*>(uart_.recv_task),  // UART0-RX
	/* 15 */  reinterpret_cast<void*>(uart_.error_task), // UART0-ER
	/* 16 */  reinterpret_cast<void*>(uart_.send_task),  // UART1-TX
	/* 17 */  reinterpret_cast<void*>(uart_.recv_task),  // UART1-RX
	/* 18 */  reinterpret_cast<void*>(uart_.error_task), // UART1-ER
	/* 19 */  nullptr,
	/* 20 */  nullptr,
	/* 21 */  nullptr,
	/* 22 */  nullptr,
	/* 23 */  nullptr,
	/* 24 */  nullptr,
	/* 25 */  nullptr,
	/* 26 */  reinterpret_cast<void*>(itm_.task),
};

extern "C" {
	void sci_putch(char ch)
	{
		uart_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		uart_.puts(str);
	}

	char sci_getch(void)
	{
		return uart_.getch();
	}

	uint16_t sci_length()
	{
		return uart_.recv_length();
	}
};

static const char* wday_[] = {
	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

static const char* mon_[] = {
	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

namespace {

	time_t get_time_()
	{
		time_t t = 0;
		if(!rtc_.get_time(t)) {
			utils::format("Stall RTC read (%d)\n") % static_cast<uint32_t>(iica0_.get_last_error());
		}
		return t;
	}

	void disp_time_(time_t t) {
		struct tm *m = gmtime(&t);
		utils::format("%s %s %d %02d:%02d:%02d  %4d\n")
			% wday_[m->tm_wday]
			% mon_[m->tm_mon]
			% static_cast<uint32_t>(m->tm_mday)
			% static_cast<uint32_t>(m->tm_hour)
			% static_cast<uint32_t>(m->tm_min)
			% static_cast<uint32_t>(m->tm_sec)
			% static_cast<uint32_t>(m->tm_year + 1900);
	}

	bool check_key_word_(uint8_t idx, const char* key)
	{
		char buff[12];
		if(command_.get_word(idx, sizeof(buff), buff)) {
			if(std::strcmp(buff, key) == 0) {
				return true;
			}
		}
		return false;
	}

	const char* get_dec_(const char* p, char tmch, int& value) {
		int v = 0;
		char ch;
		while((ch = *p) != 0) {
			++p;
			if(ch == tmch) {
				break;
			} else if(ch >= '0' && ch <= '9') {
				v *= 10;
				v += ch - '0';
			} else {
				return nullptr;
			}
		}
		value = v;
		return p;
	}

	void set_time_date_()
	{
		time_t t = get_time_();
		if(t == 0) return;

		struct tm *m = gmtime(&t);
		bool err = false;
		if(command_.get_words() == 3) {
			char buff[12];
			if(command_.get_word(1, sizeof(buff), buff)) {
				const char* p = buff;
				int vs[3];
				uint8_t i;
				for(i = 0; i < 3; ++i) {
					p = get_dec_(p, '/', vs[i]);
					if(p == nullptr) {
						break;
					}
				}
				if(p != nullptr && p[0] == 0 && i == 3) {
					if(vs[0] >= 1900 && vs[0] < 2100) m->tm_year = vs[0] - 1900;
					if(vs[1] >= 1 && vs[1] <= 12) m->tm_mon = vs[1] - 1;
					if(vs[2] >= 1 && vs[2] <= 31) m->tm_mday = vs[2];
				} else {
					err = true;
				}
			}

			if(command_.get_word(2, sizeof(buff), buff)) {
				const char* p = buff;
				int vs[3];
				uint8_t i;
				for(i = 0; i < 3; ++i) {
					p = get_dec_(p, ':', vs[i]);
					if(p == nullptr) {
						break;
					}
				}
				if(p != nullptr && p[0] == 0 && (i == 2 || i == 3)) {
					if(vs[0] >= 0 && vs[0] < 24) m->tm_hour = vs[0];
					if(vs[1] >= 0 && vs[1] < 60) m->tm_min = vs[1];
					if(i == 3 && vs[2] >= 0 && vs[2] < 60) m->tm_sec = vs[2];
					else m->tm_sec = 0;
				} else {
					err = true;
				}
			}
		}

		if(err) {
			sci_puts("Can't analize Time/Date input.\n");
			return;
		}

		time_t tt = mktime(m);
		if(!rtc_.set_time(tt)) {
			sci_puts("Stall RTC write...\n");
		}
	}
}

int main(int argc, char* argv[])
{
	using namespace device;

	PM4.B3 = 0;  // output

	// itimer の開始
	{
		uint8_t intr_level = 1;
		itm_.start(60, intr_level);
	}

	// UART の開始
	{
		uint8_t intr_level = 1;
		uart_.start(115200, intr_level);
	}

	// IICA(I2C) の開始
	{
		uint8_t intr_level = 0;
		if(!iica0_.start(IICA::speed::fast, intr_level)) {
//		if(!iica0_.start(IICA::speed::standard, intr_level)) {
			utils::format("IICA start error (%d)\n") % static_cast<uint32_t>(iica0_.get_last_error());
		}
	}

	sci_puts("Start RL78/G13 DS3231(I2C-RTC) sample\n");

	// DS3231(RTC) の開始
	if(!rtc_.start()) {
		utils::format("Stall RTC start (%d)\n") % static_cast<uint32_t>(iica0_.get_last_error());
	}

	command_.set_prompt("# ");

	uint8_t cnt = 0;
	while(1) {
		itm_.sync();

		if(cnt >= 20) {
			cnt = 0;
		}
		if(cnt < 10) P4.B3 = 1;
		else P4.B3 = 0;
		++cnt;

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			uint8_t cmdn = command_.get_words();
			if(cmdn >= 1) {
				if(check_key_word_(0, "date")) {
					if(cmdn == 1) {
						time_t t = get_time_();
						if(t != 0) {
							disp_time_(t);
						}
					} else {
						set_time_date_();
					}
				} else if(check_key_word_(0, "help")) {
					sci_puts("date\n");
					sci_puts("date yyyy/mm/dd hh:mm[:ss]\n");
				} else {
					char buff[12];
					if(command_.get_word(0, sizeof(buff), buff)) {
						sci_puts("Command error: ");
						sci_puts(buff);
						sci_putch('\n');
					}
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
   线段树
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define lson root<<1
#define rson root<<1|1

const int maxn = (65535<<1) + 3;

static struct {
    int left;
    int right;
    int lbd;
    int rbd;
    int cover;
    int mask;
    int flag;
} tree[maxn*4+11];

void build(int root, int left, int right) {
    tree[root].left = left;
    tree[root].right = right;
    tree[root].cover = 0;
    tree[root].mask = 0;
    tree[root].flag = 1;
    tree[root].lbd = left-1;
    tree[root].rbd = right+1;
    if (left >= right) {
      return;
    }
    int mid = (left + right) >> 1;
    build(lson, left, mid);
    build(rson, mid+1, right);
}

#define line(x)\
  if (c == 1) {\
    x = 1;\
  } else if (c == -1) {\
    x = 0;\
  } else if (c == 2) {\
    x = not x;\
  }\

void push_down(int root) {
  int c = tree[root].mask;
  if (c) {
    tree[lson].cover = tree[root].cover;
    tree[rson].cover = tree[root].cover;
    tree[lson].mask = c;
    tree[rson].mask = c;
    if (tree[root].cover) {
      tree[lson].lbd = tree[lson].right;
      tree[lson].rbd = tree[lson].left;
      tree[rson].lbd = tree[rson].right;
      tree[rson].rbd = tree[rson].left;
    } else {
      tree[lson].lbd = -1;
      tree[lson].rbd = -1;
      tree[rson].lbd = -1;
      tree[rson].rbd = -1;
    }
    tree[lson].flag = 1;
    tree[rson].flag = 1;
    tree[root].mask = 0;
  }
}

void update(int root) {
  if (tree[lson].cover == tree[rson].cover and tree[lson].flag and tree[rson].flag) {
    tree[root].cover = tree[lson].cover;
    tree[root].flag = 1;
  } else {
    tree[root].flag = 0;
  }

  tree[root].lbd = tree[lson].lbd;
  if (tree[rson].lbd != -1 and tree[lson].lbd == tree[lson].right) {
    tree[root].lbd = tree[rson].lbd;
  }
  tree[root].rbd = tree[rson].rbd;
  if (tree[lson].rbd != -1 and tree[rson].rbd == tree[rson].left) {
    tree[root].rbd = tree[lson].rbd;
  }
}

void insert(int root, int left, int right, int c) {
  tree[root].flag = 0;
  if (left <= tree[root].left and tree[root].right <= right) {
    line(tree[root].cover);
    tree[root].mask = c;
    tree[root].flag = 1;
    if (tree[root].cover) {
      tree[root].lbd = tree[root].right;
      tree[root].rbd = tree[root].left;
    } else {
      tree[root].lbd = -1;
      tree[root].rbd = -1;
    }
    return;
  } else if (left > tree[root].right or right < tree[root].left) {
    return;
  }
  push_down(root);
  insert(lson, left, right, c);
  insert(rson, left, right, c);
  update(root);
}

void (*f[256]) (int root, int left, int right);
void U(int root, int left, int right) {
  insert(root, left, right, 1);
}
void I(int root, int left, int right) {
  insert(root, -1, left-1, -1);
  insert(root, right+1, maxn+1, -1);
}
void D(int root, int left, int right) {
  insert(root, left, right, -1);
}
void C(int root, int left, int right) {
  insert(root, -1, left-1, -1);
  insert(root, right+1, maxn+1, -1);
  insert(root, left, right, 2);
}
void S(int root, int left, int right) {
  insert(root, left, right, 2);
}

void query(int root) {
  if (tree[root].left == tree[root].right) {
    return;
  }
  query(lson);

  l = tree[lson].rbd;

  query(rson);
}

void solve() {
    f['U'] = U, f['I'] = I, f['D'] = D, f['C'] = C, f['S'] = S;
    char order, l, r;
    int a, b;
    build(1, -1, maxn+1);
    while (scanf("%c %c%d,%d%c\n", &order, &l, &a, &b, &r) != EOF) {
        //printf("%c %c%d,%d%c\n", order, l, a,b,r);
        f[(int)order](1, (a<<1)+(l=='('), (b<<1)-(r==')'));
    }
    query(1);
}

int main() {
    solve();
    return 0;
}
<commit_msg> update<commit_after>/*
   线段树
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define lson root<<1
#define rson root<<1|1

const int maxn = (65535<<1) + 3;

static struct {
    int left;
    int right;
    int lbd;
    int rbd;
    int cover;
    int mask;
} tree[maxn*4+11];

void build(int root, int left, int right) {
    tree[root].left = left;
    tree[root].right = right;
    tree[root].cover = 0;
    tree[root].mask = 0;
    tree[root].lbd = left-1;
    tree[root].rbd = right+1;
    if (left >= right) {
      return;
    }
    int mid = (left + right) >> 1;
    build(lson, left, mid);
    build(rson, mid+1, right);
}

#define line(x)\
  if (c == 1) {\
    x = 1;\
  } else if (c == -1) {\
    x = 0;\
  } else if (c == 2) {\
    x = not x;\
  }\

void push_down(int root) {
  int c = tree[root].mask;
  if (c) {
    tree[lson].cover = tree[root].cover;
    tree[rson].cover = tree[root].cover;
    tree[lson].mask = c;
    tree[rson].mask = c;
    if (tree[root].cover) {
      tree[lson].lbd = tree[lson].right;
      tree[lson].rbd = tree[lson].left;
      tree[rson].lbd = tree[rson].right;
      tree[rson].rbd = tree[rson].left;
    } else {
      tree[lson].lbd = tree[lson].left - 1;
      tree[lson].rbd = tree[lson].right + 1;
      tree[rson].lbd = tree[rson].left - 1;
      tree[rson].rbd = tree[rson].right + 1;
    }
    tree[root].mask = 0;
  }
}

void update(int root) {
  tree[root].lbd = tree[lson].lbd;
  if (tree[lson].lbd == tree[lson].right) {
    tree[root].lbd = tree[rson].lbd;
  }
  tree[root].rbd = tree[rson].rbd;
  if (tree[rson].rbd == tree[rson].left) {
    tree[root].rbd = tree[lson].rbd;
  }
}

void insert(int root, int left, int right, int c) {
  if (left <= tree[root].left and tree[root].right <= right) {
    line(tree[root].cover);
    tree[root].mask = c;
    if (tree[root].cover) {
      tree[root].lbd = tree[root].right;
      tree[root].rbd = tree[root].left;
    } else {
      tree[root].lbd = tree[root].left - 1;
      tree[root].rbd = tree[root].right + 1;
    }
    return;
  } else if (left > tree[root].right or right < tree[root].left) {
    return;
  }
  push_down(root);
  insert(lson, left, right, c);
  insert(rson, left, right, c);
  update(root);
}

void (*f[256]) (int root, int left, int right);
void U(int root, int left, int right) {
  insert(root, left, right, 1);
}
void I(int root, int left, int right) {
  insert(root, -1, left-1, -1);
  insert(root, right+1, maxn+1, -1);
}
void D(int root, int left, int right) {
  insert(root, left, right, -1);
}
void C(int root, int left, int right) {
  insert(root, -1, left-1, -1);
  insert(root, right+1, maxn+1, -1);
  insert(root, left, right, 2);
}
void S(int root, int left, int right) {
  insert(root, left, right, 2);
}

void query(int root, int left, int right) {
  if (tree[root].left == tree[root].right) {
    return;
  }
  if (tree[root].)
  query(lson);
  if (tree[lson].rbd <= tree[rson].lbd) {
    printf("(%d, %d) ", tree[lson].rbd, tree[rson].lbd);
  }
  query(rson);
}

void solve() {
    f['U'] = U, f['I'] = I, f['D'] = D, f['C'] = C, f['S'] = S;
    char order, l, r;
    int a, b;
    build(1, -1, maxn+1);
    while (scanf("%c %c%d,%d%c\n", &order, &l, &a, &b, &r) != EOF) {
        //printf("%c %c%d,%d%c\n", order, l, a,b,r);
        f[(int)order](1, (a<<1)+(l=='('), (b<<1)-(r==')'));
    }
    query(1, -1, maxn+1);
}

int main() {
    solve();
    return 0;
}
<|endoftext|>


<commit_before>/*
 * File:   Signal.hpp
 * Author: Barath Kannan
 * Signal/Slots C++14 implementation
 * Created on May 10, 2016, 5:57 PM
 */

#ifndef SIGNAL_HPP
#define SIGNAL_HPP

#include <functional>
#include <map>
#include <unordered_map>
#include <atomic>
#include <mutex>
#include <shared_mutex>
#include <condition_variable>
#include <thread>
#include <utility>
#include <type_traits>

#include "BSignals/details/SafeQueue.hpp"
#include "BSignals/details/WheeledThreadPool.h"
#include "BSignals/details/Semaphore.h"

//These connection schemes determine how message emission to a connection occurs
    // SYNCHRONOUS CONNECTION:
    // Emission occurs synchronously.
    // When emit returns, all connected signals have returned.
    // This method is preferred when connected functions have short execution
    // time, quick emission is required, and/or when it is necessary to know
    // that the function has returned before proceeding.

    // ASYNCHRONOUS CONNECTION:
    // Emission occurs asynchronously. A detached thread is spawned on emission.
    // When emit returns, the thread has been spawned. The thread automatically
    // destructs when the connected function returns.
    // This method is recommended when connected functions have long execution
    // time and are independent.

    // ASYNCHRONOUS ENQUEUED CONNECTION:
    // Emission occurs asynchronously.
    // On connection a dedicated thread is spawned to wait for new messages.
    // Emitted parameters are bound to the mapped function and enqueued on the
    // waiting thread. These messages are then processed synchronously in the
    // spawned thread.
    // This method is recommended when quick emission is required, connected
    // functions have longer execution time, and/or connected functions need to
    // be processed in order of arrival (FIFO).

    // THREAD POOLED:
    // Emission occurs asynchronously.
    // On connection, if it is the first thread pooled function by any signal,
    // the thread pool is initialized with 8 threads, all listening for queued
    // emissions. The number of threads in the pool is not currently run-time
    // configurable but may be in the future.
    // Emitted parameters are bound to the mapped function and enqueued on the
    // one of the waiting threads - acquisition of a thread is wait-free and
    // lock free. These messages are then processed when the relevant queue
    // is consumed by the mapped thread pool.
    // This method is recommended when quick emission is required, connected
    // functions have longer execution time, and order is irrelevant. This method
//

namespace BSignals{

enum class SignalConnectionScheme{
    SYNCHRONOUS,
    ASYNCHRONOUS,
    ASYNCHRONOUS_ENQUEUE,
    THREAD_POOLED
};

template <typename... Args>
class Signal {
public:
    Signal() = default;

    Signal(bool enforceThreadSafety)
        : enableEmissionGuard{enforceThreadSafety} {}

    Signal(uint32_t maxAsyncThreads)
        : sem{maxAsyncThreads} {}

    Signal(bool enforceThreadSafety, uint32_t maxAsyncThreads)
        : enableEmissionGuard{enforceThreadSafety}, sem{maxAsyncThreads} {}

    ~Signal(){
        disconnectAllSlots();
    }

    template<typename F, typename C>
    int connectMemberSlot(const SignalConnectionScheme &scheme, F&& function, C&& instance) const {
        //type check assertions
        static_assert(std::is_member_function_pointer<F>::value, "function is not a member function");
        static_assert(std::is_object<std::remove_reference<C>>::value, "instance is not a class object");

        //Construct a bound function from the function pointer and object
        auto boundFunc = objectBind(function, instance);
        return connectSlot(scheme, boundFunc);
    }

    int connectSlot(const SignalConnectionScheme &scheme, std::function<void(Args...)> slot) const {
        std::unique_lock<std::shared_timed_mutex> lock(signalLock);
        uint32_t id = currentId.fetch_add(1);
        auto *slotMap = getSlotMap(scheme);
        slotMap->emplace(id, slot);
        if (scheme == SignalConnectionScheme::ASYNCHRONOUS_ENQUEUE){
            asyncQueues[id];
            asyncQueueThreads.emplace(id, std::thread(&Signal::queueListener, this, id));
        }
        else if (scheme == SignalConnectionScheme::THREAD_POOLED){
            BSignals::details::WheeledThreadPool::startup();
        }
        return (int)id;
    }

    void disconnectSlot(const uint32_t &id) const {
        std::unique_lock<std::shared_timed_mutex> lock(signalLock);
        std::map<uint32_t, std::function<void(Args...)>> *slotMap = findSlotMapWithId(id);
        if (slotMap == nullptr) return;
        if (slotMap == &asynchronousEnqueueSlots){
            asyncQueues[id].stop();
            asyncQueueThreads[id].join();
            asyncQueueThreads.erase(id);
            asyncQueues.erase(id);
        }
        slotMap->erase(id);
    }

    void disconnectAllSlots() const {
        std::unique_lock<std::shared_timed_mutex> lock(signalLock);
        for (auto &q : asyncQueues){
            q.second.stop();
        }
        for (auto &t : asyncQueueThreads){
            t.second.join();
        }
        asyncQueueThreads.clear();
        asyncQueues.clear();

        synchronousSlots.clear();
        asynchronousSlots.clear();
        asynchronousEnqueueSlots.clear();
        threadPooledSlots.clear();
    }

    void emitSignal(const Args &... p) const {
        return enableEmissionGuard ? emitSignalThreadSafe(p...) : emitSignalUnsafe(p...);
    }

private:
    inline void emitSignalUnsafe(const Args &... p) const {
        for (auto const &slot : synchronousSlots){
            runSynchronous(slot.second, p...);
        }

        for (auto const &slot : asynchronousSlots){
            runAsynchronous(slot.second, p...);
        }

        for (auto const &slot : asynchronousEnqueueSlots){
            runAsynchronousEnqueued(slot.first, slot.second, p...);
        }

        for (auto const &slot : threadPooledSlots){
            runThreadPooled(slot.second, p...);
        }
    }

    inline void emitSignalThreadSafe(const Args &... p) const {
        std::shared_lock<std::shared_timed_mutex> lock(signalLock);
        emitSignalUnsafe(p...);
    }

    inline void runThreadPooled(const std::function<void(Args...)> &function, const Args &... p) const {
        BSignals::details::WheeledThreadPool::run([&function, p...](){function(p...);});
    }

    inline void runAsynchronous(const std::function<void(Args...)> &function, const Args &... p) const {
        sem.acquire();
        std::thread slotThread([this, function, p...](){
            function(p...);
            sem.release();
        });
        slotThread.detach();
    }

    inline void runAsynchronousEnqueued(uint32_t asyncQueueId, const std::function<void(Args...)> &function, const Args &... p) const{
        //bind the function arguments to the function using a lambda and store
        //the newly bound function. This changes the function signature in the
        //resultant map, there are no longer any parameters in the bound function
        asyncQueues[asyncQueueId].enqueue([&function, p...](){function(p...);});
    }

    inline void runSynchronous(const std::function<void(Args...)> &function, const Args &... p) const{
        function(p...);
    }

    //Reference to instance
    template<typename F, typename I>
    std::function<void(Args...)> objectBind(F&& function, I&& instance) const {
        return[=, &instance](Args... args){
            (instance.*function)(args...);
        };
    }

    //Pointer to instance
    template<typename F, typename I>
    std::function<void(Args...)> objectBind(F&& function, I* instance) const {
        return objectBind(function, *instance);
    }

    std::map<uint32_t, std::function<void(Args...)>> *getSlotMap(const SignalConnectionScheme &scheme) const{
        switch(scheme){
            case (SignalConnectionScheme::ASYNCHRONOUS):
                return &asynchronousSlots;
            case (SignalConnectionScheme::ASYNCHRONOUS_ENQUEUE):
                return &asynchronousEnqueueSlots;
            case (SignalConnectionScheme::THREAD_POOLED):
                return &threadPooledSlots;
            default:
            case (SignalConnectionScheme::SYNCHRONOUS):
                return &synchronousSlots;
        }
    }

    std::map<uint32_t, std::function<void(Args...)>> *findSlotMapWithId(const uint32_t &id) const{
        if (synchronousSlots.count(id))
            return &synchronousSlots;
        if (asynchronousSlots.count(id))
            return &asynchronousSlots;
        if (asynchronousEnqueueSlots.count(id))
            return &asynchronousEnqueueSlots;
        if (threadPooledSlots.count(id))
            return &threadPooledSlots;
        return nullptr;
    }

    void queueListener(const uint32_t &id) const{
        auto &q = asyncQueues[id];
        while (!q.isStopped()){
            auto func = q.dequeue();
            if (q.isStopped())
                break;
            func();
        }
    }

    //shared mutex for thread safety
    //emit acquires shared lock, connect/disconnect acquires unique lock
    mutable std::shared_timed_mutex signalLock;

    //atomically incremented slotId
    mutable std::atomic<uint32_t> currentId {0};

    //Async Emit Semaphore
    mutable BSignals::details::Semaphore sem {128};

    //emissionGuard determines if it is necessary to guard emission with a shared mutex
    //this is only required if connection/disconnection could be interleaved with emission
    const bool enableEmissionGuard {false};

    //Async Enqueue Queues and Threads
    mutable std::map<uint32_t, BSignals::details::SafeQueue<std::function<void()>>> asyncQueues;
    mutable std::map<uint32_t, std::thread> asyncQueueThreads;

    //Slot Maps
    mutable std::map<uint32_t, std::function<void(Args...)>> synchronousSlots;
    mutable std::map<uint32_t, std::function<void(Args...)>> asynchronousSlots;
    mutable std::map<uint32_t, std::function<void(Args...)>> asynchronousEnqueueSlots;
    mutable std::map<uint32_t, std::function<void(Args...)>> threadPooledSlots;

};

} /* namespace BSignals */

#endif /* SIGNAL_HPP */
<commit_msg>thread pooled documentation clean up<commit_after>/*
 * File:   Signal.hpp
 * Author: Barath Kannan
 * Signal/Slots C++14 implementation
 * Created on May 10, 2016, 5:57 PM
 */

#ifndef SIGNAL_HPP
#define SIGNAL_HPP

#include <functional>
#include <map>
#include <unordered_map>
#include <atomic>
#include <mutex>
#include <shared_mutex>
#include <condition_variable>
#include <thread>
#include <utility>
#include <type_traits>

#include "BSignals/details/SafeQueue.hpp"
#include "BSignals/details/WheeledThreadPool.h"
#include "BSignals/details/Semaphore.h"

//These connection schemes determine how message emission to a connection occurs
    // SYNCHRONOUS CONNECTION:
    // Emission occurs synchronously.
    // When emit returns, all connected signals have returned.
    // This method is preferred when connected functions have short execution
    // time, quick emission is required, and/or when it is necessary to know
    // that the function has returned before proceeding.

    // ASYNCHRONOUS CONNECTION:
    // Emission occurs asynchronously. A detached thread is spawned on emission.
    // When emit returns, the thread has been spawned. The thread automatically
    // destructs when the connected function returns.
    // This method is recommended when connected functions have long execution
    // time and are independent.

    // ASYNCHRONOUS ENQUEUED CONNECTION:
    // Emission occurs asynchronously.
    // On connection a dedicated thread is spawned to wait for new messages.
    // Emitted parameters are bound to the mapped function and enqueued on the
    // waiting thread. These messages are then processed synchronously in the
    // spawned thread.
    // This method is recommended when connected functions have longer execution
    // time, the overhead of creating/destroying a thread for each slot would be
    // unperformant, and/or connected functions need to be processed in order
    // of arrival (FIFO).

    // THREAD POOLED:
    // Emission occurs asynchronously.
    // On connection, if it is the first thread pooled function by any signal,
    // the thread pool is initialized with 8 threads, all listening for queued
    // emissions. The number of threads in the pool is not currently run-time
    // configurable but may be in the future.
    // Emitted parameters are bound to the mapped function and enqueued on the
    // one of the waiting threads - acquisition of a thread is wait-free and
    // lock free. These messages are then processed when the relevant queue
    // is consumed by the mapped thread pool.
    // This method is recommended when connected functions have longer execution
    // time, the overhead of creating/destroying a thread for each slot would be
    // unperformant, the overhead of a waiting thread for each slot is
    // unnecessary, and/or connected functions do NOT need to be processed in
    // order of arrival.
//

namespace BSignals{

enum class SignalConnectionScheme{
    SYNCHRONOUS,
    ASYNCHRONOUS,
    ASYNCHRONOUS_ENQUEUE,
    THREAD_POOLED
};

template <typename... Args>
class Signal {
public:
    Signal() = default;

    Signal(bool enforceThreadSafety)
        : enableEmissionGuard{enforceThreadSafety} {}

    Signal(uint32_t maxAsyncThreads)
        : sem{maxAsyncThreads} {}

    Signal(bool enforceThreadSafety, uint32_t maxAsyncThreads)
        : enableEmissionGuard{enforceThreadSafety}, sem{maxAsyncThreads} {}

    ~Signal(){
        disconnectAllSlots();
    }

    template<typename F, typename C>
    int connectMemberSlot(const SignalConnectionScheme &scheme, F&& function, C&& instance) const {
        //type check assertions
        static_assert(std::is_member_function_pointer<F>::value, "function is not a member function");
        static_assert(std::is_object<std::remove_reference<C>>::value, "instance is not a class object");

        //Construct a bound function from the function pointer and object
        auto boundFunc = objectBind(function, instance);
        return connectSlot(scheme, boundFunc);
    }

    int connectSlot(const SignalConnectionScheme &scheme, std::function<void(Args...)> slot) const {
        std::unique_lock<std::shared_timed_mutex> lock(signalLock);
        uint32_t id = currentId.fetch_add(1);
        auto *slotMap = getSlotMap(scheme);
        slotMap->emplace(id, slot);
        if (scheme == SignalConnectionScheme::ASYNCHRONOUS_ENQUEUE){
            asyncQueues[id];
            asyncQueueThreads.emplace(id, std::thread(&Signal::queueListener, this, id));
        }
        else if (scheme == SignalConnectionScheme::THREAD_POOLED){
            BSignals::details::WheeledThreadPool::startup();
        }
        return (int)id;
    }

    void disconnectSlot(const uint32_t &id) const {
        std::unique_lock<std::shared_timed_mutex> lock(signalLock);
        std::map<uint32_t, std::function<void(Args...)>> *slotMap = findSlotMapWithId(id);
        if (slotMap == nullptr) return;
        if (slotMap == &asynchronousEnqueueSlots){
            asyncQueues[id].stop();
            asyncQueueThreads[id].join();
            asyncQueueThreads.erase(id);
            asyncQueues.erase(id);
        }
        slotMap->erase(id);
    }

    void disconnectAllSlots() const {
        std::unique_lock<std::shared_timed_mutex> lock(signalLock);
        for (auto &q : asyncQueues){
            q.second.stop();
        }
        for (auto &t : asyncQueueThreads){
            t.second.join();
        }
        asyncQueueThreads.clear();
        asyncQueues.clear();

        synchronousSlots.clear();
        asynchronousSlots.clear();
        asynchronousEnqueueSlots.clear();
        threadPooledSlots.clear();
    }

    void emitSignal(const Args &... p) const {
        return enableEmissionGuard ? emitSignalThreadSafe(p...) : emitSignalUnsafe(p...);
    }

private:
    inline void emitSignalUnsafe(const Args &... p) const {
        for (auto const &slot : synchronousSlots){
            runSynchronous(slot.second, p...);
        }

        for (auto const &slot : asynchronousSlots){
            runAsynchronous(slot.second, p...);
        }

        for (auto const &slot : asynchronousEnqueueSlots){
            runAsynchronousEnqueued(slot.first, slot.second, p...);
        }

        for (auto const &slot : threadPooledSlots){
            runThreadPooled(slot.second, p...);
        }
    }

    inline void emitSignalThreadSafe(const Args &... p) const {
        std::shared_lock<std::shared_timed_mutex> lock(signalLock);
        emitSignalUnsafe(p...);
    }

    inline void runThreadPooled(const std::function<void(Args...)> &function, const Args &... p) const {
        BSignals::details::WheeledThreadPool::run([&function, p...](){function(p...);});
    }

    inline void runAsynchronous(const std::function<void(Args...)> &function, const Args &... p) const {
        sem.acquire();
        std::thread slotThread([this, function, p...](){
            function(p...);
            sem.release();
        });
        slotThread.detach();
    }

    inline void runAsynchronousEnqueued(uint32_t asyncQueueId, const std::function<void(Args...)> &function, const Args &... p) const{
        //bind the function arguments to the function using a lambda and store
        //the newly bound function. This changes the function signature in the
        //resultant map, there are no longer any parameters in the bound function
        asyncQueues[asyncQueueId].enqueue([&function, p...](){function(p...);});
    }

    inline void runSynchronous(const std::function<void(Args...)> &function, const Args &... p) const{
        function(p...);
    }

    //Reference to instance
    template<typename F, typename I>
    std::function<void(Args...)> objectBind(F&& function, I&& instance) const {
        return[=, &instance](Args... args){
            (instance.*function)(args...);
        };
    }

    //Pointer to instance
    template<typename F, typename I>
    std::function<void(Args...)> objectBind(F&& function, I* instance) const {
        return objectBind(function, *instance);
    }

    std::map<uint32_t, std::function<void(Args...)>> *getSlotMap(const SignalConnectionScheme &scheme) const{
        switch(scheme){
            case (SignalConnectionScheme::ASYNCHRONOUS):
                return &asynchronousSlots;
            case (SignalConnectionScheme::ASYNCHRONOUS_ENQUEUE):
                return &asynchronousEnqueueSlots;
            case (SignalConnectionScheme::THREAD_POOLED):
                return &threadPooledSlots;
            default:
            case (SignalConnectionScheme::SYNCHRONOUS):
                return &synchronousSlots;
        }
    }

    std::map<uint32_t, std::function<void(Args...)>> *findSlotMapWithId(const uint32_t &id) const{
        if (synchronousSlots.count(id))
            return &synchronousSlots;
        if (asynchronousSlots.count(id))
            return &asynchronousSlots;
        if (asynchronousEnqueueSlots.count(id))
            return &asynchronousEnqueueSlots;
        if (threadPooledSlots.count(id))
            return &threadPooledSlots;
        return nullptr;
    }

    void queueListener(const uint32_t &id) const{
        auto &q = asyncQueues[id];
        while (!q.isStopped()){
            auto func = q.dequeue();
            if (q.isStopped())
                break;
            func();
        }
    }

    //shared mutex for thread safety
    //emit acquires shared lock, connect/disconnect acquires unique lock
    mutable std::shared_timed_mutex signalLock;

    //atomically incremented slotId
    mutable std::atomic<uint32_t> currentId {0};

    //Async Emit Semaphore
    mutable BSignals::details::Semaphore sem {128};

    //emissionGuard determines if it is necessary to guard emission with a shared mutex
    //this is only required if connection/disconnection could be interleaved with emission
    const bool enableEmissionGuard {false};

    //Async Enqueue Queues and Threads
    mutable std::map<uint32_t, BSignals::details::SafeQueue<std::function<void()>>> asyncQueues;
    mutable std::map<uint32_t, std::thread> asyncQueueThreads;

    //Slot Maps
    mutable std::map<uint32_t, std::function<void(Args...)>> synchronousSlots;
    mutable std::map<uint32_t, std::function<void(Args...)>> asynchronousSlots;
    mutable std::map<uint32_t, std::function<void(Args...)>> asynchronousEnqueueSlots;
    mutable std::map<uint32_t, std::function<void(Args...)>> threadPooledSlots;

};

} /* namespace BSignals */

#endif /* SIGNAL_HPP */
<|endoftext|>