Skip to content
Snippets Groups Projects
MultiArrayIO.impl.h 6.03 KiB
Newer Older
//======================================================================================================================
//
//  This file is part of waLBerla. waLBerla is free software: you can
//  redistribute it and/or modify it under the terms of the GNU General Public
//  License as published by the Free Software Foundation, either version 3 of
//  the License, or (at your option) any later version.
//
//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
//  for more details.
//
//  You should have received a copy of the GNU General Public License along
//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file MultiArrayIO.h
//! \ingroup config
//! \author Martin Bauer <martin.bauer@fau.de>
//
//======================================================================================================================

#pragma once

#include "core/DataTypes.h"

#include <sstream>
#include <boost/algorithm/string.hpp>

namespace boost {

//===================================================================================================================
//
//  Helper Functions
//
//===================================================================================================================


template<typename T>
bool parseArray1D( std::vector<T> & arr, std::istream & is,
                   const char openingBracket='[',
                   const char closingBracket=']',
                   const std::string & delimiter = ", \t\n" )
{

   is >> std::skipws;

   char bracket1;
   if( !(is >> bracket1 ) || bracket1 != openingBracket )
      return false;

   std::string line;
   if ( ! std::getline( is, line, closingBracket ) )
      return false;


   std::vector<std::string> stringArr;
   boost::split( stringArr,line, boost::is_any_of( delimiter ), boost::token_compress_on );

   arr.clear();
   arr.reserve( stringArr.size() );
   for( auto sArrIt =stringArr.begin(); sArrIt != stringArr.end(); ++sArrIt )
   {
      if ( *sArrIt == "") continue;

      std::stringstream ss ( *sArrIt );
      T value;
      ss >> value;
      arr.push_back( value );
   }
   return true;
}



template<typename T >
bool parseArray2D( std::vector< std::vector<T> > & arr, std::istream & is,
                   const char openingBracket='[',
                   const char closingBracket=']',
                   const std::string & delimiter = ", \t\n"  )
{
   is >> std::skipws;
   char bracket1;
   if( !(is >> bracket1 ) || bracket1 != openingBracket )
      return false;

   do
   {
      arr.push_back( std::vector<T>() );
      if ( ! parseArray1D( arr.back(), is, openingBracket, closingBracket, delimiter ) )
         return false;

      while( delimiter.find( (char)( is.peek()) ) != std::string::npos )
         is.get();

      if ( is.peek() == closingBracket ) {
         is.get();
         return true;
      }

   } while ( true );

}


//===================================================================================================================
//
//  IO Operators
//
//===================================================================================================================


template<typename T>
std::istream & operator>> ( std::istream & is, boost::multi_array<T,1> & arr )
{
   if ( !is ) return is;

   const std::istream::pos_type pos( is.tellg() );
   const std::istream::fmtflags oldFlags( is.flags() );


   std::vector< T > vec;
   if ( ! parseArray1D( vec, is ) ) {
      is.clear();
      is.seekg( pos );
      is.setstate( std::istream::failbit );
      is.flags( oldFlags );
      return is;
   }

   auto rows = vec.size();
   if ( rows == 0 )
      return is;

   arr.resize( boost::extents[walberla::numeric_cast< boost::multi_array_types::index >(rows)] );

   for( size_t r = 0; r < rows; ++r )
      arr[walberla::numeric_cast< boost::multi_array_types::index >(r)] = vec[r];

   return is;
}

template<typename T>
std::ostream & operator<< ( std::ostream & os, const boost::multi_array<T,1> & arr )
{
   os << "[ ";
   for( size_t c = 0; c < arr.size(); ++c )
      os << arr[walberla::numeric_cast< boost::multi_array_types::index >(c)] << ",";
   os << "]";

   return os;
}






template<typename T>
std::istream & operator>> ( std::istream & is, boost::multi_array<T,2> & arr )
{
   if ( !is ) return is;

   const std::istream::pos_type pos( is.tellg() );
   const std::istream::fmtflags oldFlags( is.flags() );


   std::vector< std::vector<T> > vec2D;
   if ( ! parseArray2D( vec2D, is ) ) {
      is.clear();
      is.seekg( pos );
      is.setstate( std::istream::failbit );
      is.flags( oldFlags );
      return is;
   }

   size_t rows = vec2D.size();
   if ( rows == 0 )
      return is;

   size_t cols = vec2D[0].size();
   for( size_t r = 0; r < rows; ++r )
   {
      if ( vec2D[r].size() != cols  )
      {
         // non square vector
         is.clear();
         is.seekg( pos );
         is.setstate( std::istream::failbit );
         is.flags( oldFlags );
         return is;
      }
   }

   arr.resize( boost::extents[ walberla::numeric_cast< boost::multi_array_types::index >(rows) ][ walberla::numeric_cast< boost::multi_array_types::index >(cols) ] );

   for( size_t r = 0; r < rows; ++r )
      for( size_t c = 0; c < cols; ++c )
         arr[walberla::numeric_cast< boost::multi_array_types::index >(r)][walberla::numeric_cast< boost::multi_array_types::index >(c)] = vec2D[r][c];


   return is;
}

template<typename T>
std::ostream & operator<< ( std::ostream & os, const boost::multi_array<T,2> & arr )
{
   os << "[\n";

   for( size_t r = 0; r < arr.size(); ++r )
   {
      os << " [ ";
      for( size_t c = 0; c < arr[walberla::numeric_cast< boost::multi_array_types::index >(r)].size(); ++c ) {
         os << arr[walberla::numeric_cast< boost::multi_array_types::index >(r)][walberla::numeric_cast< boost::multi_array_types::index >(c)] << "\t";
      }
      os << "] \n";
   }
   os << "]";

   return os;
}








} // namespace walberla