<commit_before>//=======================================================================
// Copyright (c) 2013-2016 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file
 * \brief Contains an std::array-like implementation but with aligned data
 * access
 */

#ifndef CPP_ALIGNED_ARRAY_HPP
#define CPP_ALIGNED_ARRAY_HPP

namespace cpp {

/*!
 * \brief Aligned std::array implementation
 * \tparam T The value type
 * \tparam S The size of the collection
 * \tparam A The alignment in bytes
 */
template <typename T, std::size_t S, std::size_t A>
struct aligned_array {
    using value_type             = T;                                     ///< The type of value
    using size_type              = std::size_t;                           ///< The type of indices
    using difference_type        = std::ptrdiff_t;                        ///< The type of iterator difference
    using reference              = value_type&;                           ///< The type of a reference
    using const_reference        = value_type&;                           ///< The type of a const reference
    using pointer                = value_type*;                           ///< The type of a pointer
    using const_pointer          = const value_type*;                     ///< The type of a const pointer
    using iterator               = T*;                                    ///< The type of an iterator
    using const_iterator         = const T*;                              ///< The type of a const iterator
    using reverse_iterator       = std::reverse_iterator<iterator>;       ///< The type of a reverse iterator
    using const_reverse_iterator = std::reverse_iterator<const_iterator>; ///< The type of a const reverse iterator

    /*!
     * \brief Initialize the array
     */
    aligned_array() {
        auto raw = reinterpret_cast<std::size_t>(storage);

        if (raw % A) {
            aligned_data = reinterpret_cast<value_type*>(raw + (A - (raw % A)));
        } else {
            aligned_data = reinterpret_cast<value_type*>(raw);
        }

        new (aligned_data) value_type[size()];
    }

    reference at(std::size_t i) {
        if (i >= size()) {
            throw std::out_of_range("Out of bounds aligned_array");
        }

        return aligned_data[i];
    }

    const_reference at(std::size_t i) const {
        if (i >= size()) {
            throw std::out_of_range("Out of bounds aligned_array");
        }

        return aligned_data[i];
    }

    reference operator[](std::size_t i) noexcept {
        return aligned_data[i];
    }

    const_reference operator[](std::size_t i) const noexcept {
        return aligned_data[i];
    }

    reference front() noexcept {
        return aligned_data[0];
    }

    const_reference front() const noexcept {
        return aligned_data[0];
    }

    reference back() noexcept {
        return aligned_data[size() - 1];
    }

    const_reference back() const noexcept {
        return aligned_data[size() - 1];
    }

    T* data() noexcept {
        return aligned_data;
    }

    const T* data() const noexcept {
        return aligned_data;
    }

    iterator begin() {
        return &aligned_data[0];
    }

    const_iterator begin() const {
        return &aligned_data[0];
    }

    const_iterator cbegin() const {
        return &aligned_data[0];
    }

    iterator end() {
        return &aligned_data[size()];
    }

    const_iterator end() const {
        return &aligned_data[size()];
    }

    const_iterator cend() const {
        return &aligned_data[size()];
    }

    reverse_iterator rbegin() noexcept {
        return reverse_iterator(&aligned_data[size()]);
    }

    const_reverse_iterator rbegin() const noexcept {
        return const_reverse_iterator(&aligned_data[size()]);
    }

    const_reverse_iterator crbegin() const noexcept {
        return const_reverse_iterator(&aligned_data[size()]);
    }

    reverse_iterator rend() noexcept {
        return reverse_iterator(&aligned_data[0]);
    }

    const_reverse_iterator rend() const noexcept {
        return const_reverse_iterator(&aligned_data[0]);
    }

    const_reverse_iterator crend() const noexcept {
        return const_reverse_iterator(&aligned_data[0]);
    }

    constexpr bool empty() const noexcept {
        return !S;
    }

    constexpr std::size_t size() const noexcept {
        return S;
    }

    constexpr std::size_t max_size() const noexcept {
        return S;
    }

    void fill(const value_type& value) noexcept {
        for (std::size_t i = 0; i < size(); ++i) {
            aligned_data[i] = value;
        }
    }

    void swap(aligned_array& other){
        for(size_t i = 0; i < size(); ++i){
            using std::swap;
            swap((*this)[i], other[i]);
        }
    }

private:
    T* aligned_data;
    char storage[S * sizeof(T) + (A - 1)];
};

template <typename T, std::size_t N>
void swap(aligned_array<T, N>& lhs, aligned_array<T, N>& rhs){
    lhs.swap(rhs);
}

} //end of namespace cpp

#endif //CPP_ARRAY_WRAPPER_HPP
<commit_msg>God damn it...<commit_after>//=======================================================================
// Copyright (c) 2013-2016 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file
 * \brief Contains an std::array-like implementation but with aligned data
 * access
 */

#ifndef CPP_ALIGNED_ARRAY_HPP
#define CPP_ALIGNED_ARRAY_HPP

namespace cpp {

/*!
 * \brief Aligned std::array implementation
 * \tparam T The value type
 * \tparam S The size of the collection
 * \tparam A The alignment in bytes
 */
template <typename T, std::size_t S, std::size_t A>
struct aligned_array {
    using value_type             = T;                                     ///< The type of value
    using size_type              = std::size_t;                           ///< The type of indices
    using difference_type        = std::ptrdiff_t;                        ///< The type of iterator difference
    using reference              = value_type&;                           ///< The type of a reference
    using const_reference        = value_type&;                           ///< The type of a const reference
    using pointer                = value_type*;                           ///< The type of a pointer
    using const_pointer          = const value_type*;                     ///< The type of a const pointer
    using iterator               = T*;                                    ///< The type of an iterator
    using const_iterator         = const T*;                              ///< The type of a const iterator
    using reverse_iterator       = std::reverse_iterator<iterator>;       ///< The type of a reverse iterator
    using const_reverse_iterator = std::reverse_iterator<const_iterator>; ///< The type of a const reverse iterator

    /*!
     * \brief Initialize the array
     */
    aligned_array() {
        auto raw = reinterpret_cast<std::size_t>(storage);

        if (raw % A) {
            aligned_data = reinterpret_cast<value_type*>(raw + (A - (raw % A)));
        } else {
            aligned_data = reinterpret_cast<value_type*>(raw);
        }

        new (aligned_data) value_type[size()];
    }

    reference at(std::size_t i) {
        if (i >= size()) {
            throw std::out_of_range("Out of bounds aligned_array");
        }

        return aligned_data[i];
    }

    const_reference at(std::size_t i) const {
        if (i >= size()) {
            throw std::out_of_range("Out of bounds aligned_array");
        }

        return aligned_data[i];
    }

    reference operator[](std::size_t i) noexcept {
        return aligned_data[i];
    }

    const_reference operator[](std::size_t i) const noexcept {
        return aligned_data[i];
    }

    reference front() noexcept {
        return aligned_data[0];
    }

    const_reference front() const noexcept {
        return aligned_data[0];
    }

    reference back() noexcept {
        return aligned_data[size() - 1];
    }

    const_reference back() const noexcept {
        return aligned_data[size() - 1];
    }

    T* data() noexcept {
        return aligned_data;
    }

    const T* data() const noexcept {
        return aligned_data;
    }

    iterator begin() {
        return &aligned_data[0];
    }

    const_iterator begin() const {
        return &aligned_data[0];
    }

    const_iterator cbegin() const {
        return &aligned_data[0];
    }

    iterator end() {
        return &aligned_data[size()];
    }

    const_iterator end() const {
        return &aligned_data[size()];
    }

    const_iterator cend() const {
        return &aligned_data[size()];
    }

    reverse_iterator rbegin() noexcept {
        return reverse_iterator(&aligned_data[size()]);
    }

    const_reverse_iterator rbegin() const noexcept {
        return const_reverse_iterator(&aligned_data[size()]);
    }

    const_reverse_iterator crbegin() const noexcept {
        return const_reverse_iterator(&aligned_data[size()]);
    }

    reverse_iterator rend() noexcept {
        return reverse_iterator(&aligned_data[0]);
    }

    const_reverse_iterator rend() const noexcept {
        return const_reverse_iterator(&aligned_data[0]);
    }

    const_reverse_iterator crend() const noexcept {
        return const_reverse_iterator(&aligned_data[0]);
    }

    constexpr bool empty() const noexcept {
        return !S;
    }

    constexpr std::size_t size() const noexcept {
        return S;
    }

    constexpr std::size_t max_size() const noexcept {
        return S;
    }

    void fill(const value_type& value) noexcept {
        for (std::size_t i = 0; i < size(); ++i) {
            aligned_data[i] = value;
        }
    }

    void swap(aligned_array& other){
        for(size_t i = 0; i < size(); ++i){
            using std::swap;
            swap((*this)[i], other[i]);
        }
    }

private:
    T* aligned_data;
    char storage[S * sizeof(T) + (A - 1)];
};

template <typename T, std::size_t N, std::size_t A>
void swap(aligned_array<T, N, A>& lhs, aligned_array<T, N, A>& rhs){
    lhs.swap(rhs);
}

} //end of namespace cpp

#endif //CPP_ARRAY_WRAPPER_HPP
<|endoftext|>


<commit_before>#include "../bart_builder.h"
#include "../problem_definition.h"

#include "gtest/gtest.h"
#include "../../test_helpers/bart_test_helper.h"

class BARTBuilderTest : public ::testing::Test {
 protected:
  void SetUp ();

  // FE builder test
  void SetUpFEBuilderTest ();

  template <int dim>
  void FEBuilderTest ();

  // AQ builder test
  void SetUpAQBuilderTest ();

  template <int dim>
  void AQBuilderTest ();

  dealii::ParameterHandler prm;
};

void BARTBuilderTest::SetUp () {
  // Note that setup for different tests
  // had better be separated for clearness.
  SetUpAQBuilderTest();

  SetUpFEBuilderTest();
}

void BARTBuilderTest::SetUpAQBuilderTest () {
  prm.declare_entry("have reflective boundary", "false",
                    dealii::Patterns::Bool(), "");
  prm.declare_entry("angular quadrature order", "4",
                    dealii::Patterns::Integer(), "");
  prm.declare_entry("angular quadrature name", "gl",
                    dealii::Patterns::Selection("gl|lsgc"), "");
  prm.declare_entry("number of groups", "1", dealii::Patterns::Integer(), "");
  prm.declare_entry("transport model", "regular",
                    dealii::Patterns::Selection("regular|ep"), "");
}

void BARTBuilderTest::SetUpFEBuilderTest () {
  prm.declare_entry("finite element polynomial degree", "1",
                    dealii::Patterns::Integer(), "");
  prm.declare_entry("do nda", "true",
                    dealii::Patterns::Bool(), "");
  prm.declare_entry("transport model", "dummy",
                    dealii::Patterns::Anything(), "");
  prm.declare_entry("ho spatial discretization", "",
                    dealii::Patterns::Anything(), "");
  prm.declare_entry("nda spatial discretization", "",
                    dealii::Patterns::Anything(), "");
}

template <int dim>
void BARTBuilderTest::FEBuilderTest () {
  // set values to parameters
  prm.set ("ho spatial discretization", "cfem");
  prm.set ("nda spatial discretization", "cfem");
  std::unordered_map<std::string, dealii::FiniteElement<dim, dim>*> fe_ptrs;
  bbuilders::BuildFESpaces (prm, fe_ptrs);

  // testing for FE names
  EXPECT_EQ (fe_ptrs["dummy"]->get_name(),
      "FE_Q<"+dealii::Utilities::int_to_string(dim)+">(1)");
  EXPECT_EQ (fe_ptrs["nda"]->get_name(),
      "FE_Q<"+dealii::Utilities::int_to_string(dim)+">(1)");

  // changing FE types
  prm.set ("ho spatial discretization", "dfem");
  prm.set ("nda spatial discretization", "dfem");
  fe_ptrs.clear ();
  bbuilders::BuildFESpaces (prm, fe_ptrs);
  EXPECT_EQ (fe_ptrs["dummy"]->get_name(),
      "FE_DGQ<"+dealii::Utilities::int_to_string(dim)+">(1)");
  EXPECT_EQ (fe_ptrs["nda"]->get_name(),
      "FE_DGQ<"+dealii::Utilities::int_to_string(dim)+">(1)");

  // changing NDA FE type
  prm.set ("nda spatial discretization", "cmfd");
  fe_ptrs.clear ();
  bbuilders::BuildFESpaces (prm, fe_ptrs);
  EXPECT_EQ (fe_ptrs["nda"]->get_name(),
      "FE_DGQ<"+dealii::Utilities::int_to_string(dim)+">(0)");

  // changing NDA FE type
  prm.set ("nda spatial discretization", "rtk");
  fe_ptrs.clear ();
  bbuilders::BuildFESpaces (prm, fe_ptrs);
  EXPECT_EQ (fe_ptrs["nda"]->get_name(),
      "FE_RaviartThomas<"+dealii::Utilities::int_to_string(dim)+">(1)");
}

TEST_F (BARTBuilderTest, FEBuilder2DTest) {
  FEBuilderTest<2> ();
}

TEST_F (BARTBuilderTest, FEBuilder3DTest) {
  FEBuilderTest<3> ();
}

template <int dim>
void BARTBuilderTest::AQBuilderTest () {
  std::unique_ptr<AQBase<dim>> aq_ptr;
  std::string aq_name = (dim==1) ? "gl" : "lsgc";
  prm.set ("angular quadrature name", aq_name);
  prm.set ("angular quadrature order", "4");

  // call builder function to build aq
  bbuilders::BuildAQ (prm, aq_ptr);
  aq_ptr->MakeAQ();
  auto wi = aq_ptr->GetAQWeights();
  auto omega_i = aq_ptr->GetAQDirs();

  // check output
  std::string filename = "aq_builder_"+dealii::Utilities::int_to_string(dim)+"d";
  btest::GoldTestInit(filename);
  for (unsigned int i=0; i<wi.size(); ++i) {
    dealii::deallog << "Weight: " << wi[i] << "; Omega: ";
    for (int j=0; j<dim; ++j)
      dealii::deallog << omega_i[i][j] << " ";
    dealii::deallog << std::endl;
  }
  btest::GoldTestRun(filename);
}

TEST_F (BARTBuilderTest, AQBuilder1DTest) {
  AQBuilderTest<1> ();
}

TEST_F (BARTBuilderTest, AQBuilder2DTest) {
  AQBuilderTest<2> ();
}

TEST_F (BARTBuilderTest, AQBuilder3DTest) {
  AQBuilderTest<3> ();
}
<commit_msg>removed tests for depreciated BuildAQ factory function<commit_after>#include "../bart_builder.h"
#include "../problem_definition.h"

#include "gtest/gtest.h"
#include "../../test_helpers/bart_test_helper.h"

class BARTBuilderTest : public ::testing::Test {
 protected:
  void SetUp ();

  // FE builder test
  void SetUpFEBuilderTest ();

  template <int dim>
  void FEBuilderTest ();

  dealii::ParameterHandler prm;
};

void BARTBuilderTest::SetUp () {
  // Note that setup for different tests
  // had better be separated for clearness.

  SetUpFEBuilderTest();
}

void BARTBuilderTest::SetUpFEBuilderTest () {
  prm.declare_entry("finite element polynomial degree", "1",
                    dealii::Patterns::Integer(), "");
  prm.declare_entry("do nda", "true",
                    dealii::Patterns::Bool(), "");
  prm.declare_entry("transport model", "dummy",
                    dealii::Patterns::Anything(), "");
  prm.declare_entry("ho spatial discretization", "",
                    dealii::Patterns::Anything(), "");
  prm.declare_entry("nda spatial discretization", "",
                    dealii::Patterns::Anything(), "");
}

template <int dim>
void BARTBuilderTest::FEBuilderTest () {
  // set values to parameters
  prm.set ("ho spatial discretization", "cfem");
  prm.set ("nda spatial discretization", "cfem");
  std::unordered_map<std::string, dealii::FiniteElement<dim, dim>*> fe_ptrs;
  bbuilders::BuildFESpaces (prm, fe_ptrs);

  // testing for FE names
  EXPECT_EQ (fe_ptrs["dummy"]->get_name(),
      "FE_Q<"+dealii::Utilities::int_to_string(dim)+">(1)");
  EXPECT_EQ (fe_ptrs["nda"]->get_name(),
      "FE_Q<"+dealii::Utilities::int_to_string(dim)+">(1)");

  // changing FE types
  prm.set ("ho spatial discretization", "dfem");
  prm.set ("nda spatial discretization", "dfem");
  fe_ptrs.clear ();
  bbuilders::BuildFESpaces (prm, fe_ptrs);
  EXPECT_EQ (fe_ptrs["dummy"]->get_name(),
      "FE_DGQ<"+dealii::Utilities::int_to_string(dim)+">(1)");
  EXPECT_EQ (fe_ptrs["nda"]->get_name(),
      "FE_DGQ<"+dealii::Utilities::int_to_string(dim)+">(1)");

  // changing NDA FE type
  prm.set ("nda spatial discretization", "cmfd");
  fe_ptrs.clear ();
  bbuilders::BuildFESpaces (prm, fe_ptrs);
  EXPECT_EQ (fe_ptrs["nda"]->get_name(),
      "FE_DGQ<"+dealii::Utilities::int_to_string(dim)+">(0)");

  // changing NDA FE type
  prm.set ("nda spatial discretization", "rtk");
  fe_ptrs.clear ();
  bbuilders::BuildFESpaces (prm, fe_ptrs);
  EXPECT_EQ (fe_ptrs["nda"]->get_name(),
      "FE_RaviartThomas<"+dealii::Utilities::int_to_string(dim)+">(1)");
}

TEST_F (BARTBuilderTest, FEBuilder2DTest) {
  FEBuilderTest<2> ();
}

TEST_F (BARTBuilderTest, FEBuilder3DTest) {
  FEBuilderTest<3> ();
}
<|endoftext|>


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

using namespace com::sun::star::packages::zip::ZipConstants;
using namespace com::sun::star::io;
using namespace com::sun::star::uno;
using com::sun::star::lang::IllegalArgumentException;
using ::rtl::OUString;

XFileStream::XFileStream( ZipEntry & rEntry,
                           com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream,
                           com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewTempStream,
                           const vos::ORef < EncryptionData > &rData,
                           sal_Bool bNewRawStream )
: maEntry ( rEntry )
, mxData ( rData )
, mbRawStream ( bNewRawStream )
, mbFinished ( sal_False )
, mxTempIn ( xNewTempStream )
, mxTempSeek ( xNewTempStream, UNO_QUERY )
, mxTempOut ( xNewTempStream, UNO_QUERY )
, mxZipStream ( xNewZipStream )
, mxZipSeek ( xNewZipStream, UNO_QUERY )
, maInflater ( sal_True )
, maCipher ( NULL )
{
    mnZipCurrent = maEntry.nOffset;
    if (mbRawStream)
    {
        mnZipSize = maEntry.nMethod == DEFLATED ? maEntry.nCompressedSize : maEntry.nSize;
        mnZipEnd = maEntry.nOffset + mnZipSize;
    }
    else
    {
        mnZipSize = maEntry.nSize;
        mnZipEnd = maEntry.nMethod == DEFLATED ? maEntry.nOffset + maEntry.nCompressedSize : maEntry.nOffset + maEntry.nSize;
    }
    if ( !rData.isEmpty() && rData->aSalt.getLength() )
        ZipFile::StaticGetCipher ( rData, maCipher );
}

XFileStream::~XFileStream()
{
    if ( maCipher )
        rtl_cipher_destroy ( maCipher );
}

Any SAL_CALL  XFileStream::queryInterface( const Type& rType )
        throw(RuntimeException)
{
    return ::cppu::queryInterface ( rType                                       ,
                                        // OWeakObject interfaces
                                        reinterpret_cast< XInterface*       > ( this )  ,
                                        static_cast< XWeak*         > ( this )  ,
                                        // my interfaces
                                        static_cast< XInputStream*      > ( this )  ,
                                        static_cast< XSeekable*     > ( this ) );

}

void SAL_CALL  XFileStream::acquire(void)
    throw()
{
    OWeakObject::acquire();
}

void SAL_CALL  XFileStream::release(void)
    throw()
{
    OWeakObject::release();
}

void XFileStream::fill( sal_Int64 nUntil)
{
    sal_Int32 nRead;
    sal_Int64 nPosition = mxTempSeek->getPosition();
    mxTempSeek->seek ( mxTempSeek->getLength() );
    maBuffer.realloc ( n_ConstBufferSize );

    while ( mxTempSeek->getLength() < nUntil )
    {
        if ( !mbRawStream )
        {
            while ( 0 == ( nRead = maInflater.doInflate( maBuffer ) ) )
            {
                if ( maInflater.finished() || maInflater.needsDictionary() )
                {
                    // some error handling ?
                    return;
                }

                sal_Int64 nDiff = mnZipEnd - mnZipCurrent;
                if ( nDiff >= 0 )
                {
                    mxZipSeek->seek ( mnZipCurrent );
                    nRead = mxZipStream->readBytes ( maCompBuffer, static_cast < sal_Int32 > ( nDiff < n_ConstBufferSize ? nDiff : n_ConstBufferSize ) );
                    mnZipCurrent += nRead;
                    // maCompBuffer now has the uncompressed data, check if we need to decrypt
                    // before passing to the Inflater
                    if ( maCipher )
                    {
                        Sequence < sal_Int8 > aCryptBuffer ( nRead );
                        rtlCipherError aResult = rtl_cipher_decode ( maCipher,
                                      maCompBuffer.getConstArray(),
                                      nRead,
                                      reinterpret_cast < sal_uInt8 * > (aCryptBuffer.getArray()),
                                      nRead);
                        OSL_ASSERT (aResult == rtl_Cipher_E_None);
                        maCompBuffer = aCryptBuffer; // Now it holds the decrypted data

                    }
                    maInflater.setInput ( maCompBuffer );
                }
                else
                {
                    // some error handling ?
                    return;
                }
            }
        }
        else
        {
            sal_Int64 nDiff = mnZipEnd - mnZipCurrent;
            mxZipSeek->seek ( mnZipCurrent );
            nRead = mxZipStream->readBytes ( maBuffer, static_cast < sal_Int32 > ( nDiff < n_ConstBufferSize ? nDiff : n_ConstBufferSize ) );
            mnZipCurrent += nRead;
        }
        Sequence < sal_Int8 > aTmpBuffer ( maBuffer.getConstArray(), nRead );
        mxTempOut->writeBytes ( aTmpBuffer );
    }
    mxTempSeek->seek ( nPosition );
}

sal_Int32 SAL_CALL XFileStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
        throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    sal_Int64 nPosition = mxTempSeek->getPosition();
    if ( nPosition + nBytesToRead > mnZipSize )
        nBytesToRead = static_cast < sal_Int32 > ( mnZipSize - nPosition );

    sal_Int64 nUntil = nBytesToRead + nPosition + n_ConstBufferSize;
    if (nUntil > mnZipSize )
        nUntil = mnZipSize;
    if ( nUntil > mxTempSeek->getLength() )
        fill ( nUntil );
    sal_Int32 nRead = mxTempIn->readBytes ( aData, nBytesToRead );
    return nRead;
}

sal_Int32 SAL_CALL XFileStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
        throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    return readBytes ( aData, nMaxBytesToRead );
}
void SAL_CALL XFileStream::skipBytes( sal_Int32 nBytesToSkip )
        throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    seek ( mxTempSeek->getPosition() + nBytesToSkip );
}

sal_Int32 SAL_CALL XFileStream::available(  )
        throw( NotConnectedException, IOException, RuntimeException)
{
    return static_cast < sal_Int32 > ( mnZipSize - mxTempSeek->getPosition() );
}

void SAL_CALL XFileStream::closeInput(  )
        throw( NotConnectedException, IOException, RuntimeException)
{
}
void SAL_CALL XFileStream::seek( sal_Int64 location )
        throw( IllegalArgumentException, IOException, RuntimeException)
{
    if ( location > mnZipSize || location < 0 )
        throw IllegalArgumentException();
    if ( location > mxTempSeek->getLength() )
    {
        sal_Int64 nUntil = location + n_ConstBufferSize > mnZipSize ? mnZipSize : location + n_ConstBufferSize;
        fill ( nUntil );
    }
    mxTempSeek->seek ( location );
}
sal_Int64 SAL_CALL XFileStream::getPosition(  )
        throw(IOException, RuntimeException)
{
    return mxTempSeek->getPosition();
}
sal_Int64 SAL_CALL XFileStream::getLength(  )
        throw(IOException, RuntimeException)
{
    return mnZipSize;
}
<commit_msg>#93994# don't try to read 0 bytes and then decrypt and inflate it!<commit_after>/*************************************************************************
 *
 *  $RCSfile: XFileStream.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: mtg $ $Date: 2001-10-31 11:32:54 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _XFILE_STREAM_HXX
#include <XFileStream.hxx>
#endif
#ifndef _ENCRYPTION_DATA_HXX_
#include <EncryptionData.hxx>
#endif
#ifndef _COM_SUN_STAR_PACKAGES_ZIP_ZIPCONSTANTS_HPP_
#include <com/sun/star/packages/zip/ZipConstants.hpp>
#endif
#ifndef _PACKAGE_CONSTANTS_HXX_
#include <PackageConstants.hxx>
#endif
#ifndef _RTL_CIPHER_H_
#include <rtl/cipher.h>
#endif
#ifndef _ZIP_FILE_HXX
#include <ZipFile.hxx>
#endif

using namespace com::sun::star::packages::zip::ZipConstants;
using namespace com::sun::star::io;
using namespace com::sun::star::uno;
using com::sun::star::lang::IllegalArgumentException;
using ::rtl::OUString;

XFileStream::XFileStream( ZipEntry & rEntry,
                           com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream,
                           com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewTempStream,
                           const vos::ORef < EncryptionData > &rData,
                           sal_Bool bNewRawStream )
: maEntry ( rEntry )
, mxData ( rData )
, mbRawStream ( bNewRawStream )
, mbFinished ( sal_False )
, mxTempIn ( xNewTempStream )
, mxTempSeek ( xNewTempStream, UNO_QUERY )
, mxTempOut ( xNewTempStream, UNO_QUERY )
, mxZipStream ( xNewZipStream )
, mxZipSeek ( xNewZipStream, UNO_QUERY )
, maInflater ( sal_True )
, maCipher ( NULL )
{
    mnZipCurrent = maEntry.nOffset;
    if (mbRawStream)
    {
        mnZipSize = maEntry.nMethod == DEFLATED ? maEntry.nCompressedSize : maEntry.nSize;
        mnZipEnd = maEntry.nOffset + mnZipSize;
    }
    else
    {
        mnZipSize = maEntry.nSize;
        mnZipEnd = maEntry.nMethod == DEFLATED ? maEntry.nOffset + maEntry.nCompressedSize : maEntry.nOffset + maEntry.nSize;
    }
    if ( !rData.isEmpty() && rData->aSalt.getLength() )
        ZipFile::StaticGetCipher ( rData, maCipher );
}

XFileStream::~XFileStream()
{
    if ( maCipher )
        rtl_cipher_destroy ( maCipher );
}

Any SAL_CALL  XFileStream::queryInterface( const Type& rType )
        throw(RuntimeException)
{
    return ::cppu::queryInterface ( rType                                       ,
                                        // OWeakObject interfaces
                                        reinterpret_cast< XInterface*       > ( this )  ,
                                        static_cast< XWeak*         > ( this )  ,
                                        // my interfaces
                                        static_cast< XInputStream*      > ( this )  ,
                                        static_cast< XSeekable*     > ( this ) );

}

void SAL_CALL  XFileStream::acquire(void)
    throw()
{
    OWeakObject::acquire();
}

void SAL_CALL  XFileStream::release(void)
    throw()
{
    OWeakObject::release();
}

void XFileStream::fill( sal_Int64 nUntil)
{
    sal_Int32 nRead;
    sal_Int64 nPosition = mxTempSeek->getPosition();
    mxTempSeek->seek ( mxTempSeek->getLength() );
    maBuffer.realloc ( n_ConstBufferSize );

    while ( mxTempSeek->getLength() < nUntil )
    {
        if ( !mbRawStream )
        {
            while ( 0 == ( nRead = maInflater.doInflate( maBuffer ) ) )
            {
                if ( maInflater.finished() || maInflater.needsDictionary() )
                {
                    // some error handling ?
                    return;
                }

                sal_Int64 nDiff = mnZipEnd - mnZipCurrent;
                if ( nDiff > 0 )
                {
                    mxZipSeek->seek ( mnZipCurrent );
                    nRead = mxZipStream->readBytes ( maCompBuffer, static_cast < sal_Int32 > ( nDiff < n_ConstBufferSize ? nDiff : n_ConstBufferSize ) );
                    mnZipCurrent += nRead;
                    // maCompBuffer now has the uncompressed data, check if we need to decrypt
                    // before passing to the Inflater
                    if ( maCipher )
                    {
                        Sequence < sal_Int8 > aCryptBuffer ( nRead );
                        rtlCipherError aResult = rtl_cipher_decode ( maCipher,
                                      maCompBuffer.getConstArray(),
                                      nRead,
                                      reinterpret_cast < sal_uInt8 * > (aCryptBuffer.getArray()),
                                      nRead);
                        OSL_ASSERT (aResult == rtl_Cipher_E_None);
                        maCompBuffer = aCryptBuffer; // Now it holds the decrypted data

                    }
                    maInflater.setInput ( maCompBuffer );
                }
                else
                {
                    // some error handling ?
                    return;
                }
            }
        }
        else
        {
            sal_Int64 nDiff = mnZipEnd - mnZipCurrent;
            mxZipSeek->seek ( mnZipCurrent );
            nRead = mxZipStream->readBytes ( maBuffer, static_cast < sal_Int32 > ( nDiff < n_ConstBufferSize ? nDiff : n_ConstBufferSize ) );
            mnZipCurrent += nRead;
        }
        Sequence < sal_Int8 > aTmpBuffer ( maBuffer.getConstArray(), nRead );
        mxTempOut->writeBytes ( aTmpBuffer );
    }
    mxTempSeek->seek ( nPosition );
}

sal_Int32 SAL_CALL XFileStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
        throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    sal_Int64 nPosition = mxTempSeek->getPosition();
    if ( nPosition + nBytesToRead > mnZipSize )
        nBytesToRead = static_cast < sal_Int32 > ( mnZipSize - nPosition );

    sal_Int64 nUntil = nBytesToRead + nPosition + n_ConstBufferSize;
    if (nUntil > mnZipSize )
        nUntil = mnZipSize;
    if ( nUntil > mxTempSeek->getLength() )
        fill ( nUntil );
    sal_Int32 nRead = mxTempIn->readBytes ( aData, nBytesToRead );
    return nRead;
}

sal_Int32 SAL_CALL XFileStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
        throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    return readBytes ( aData, nMaxBytesToRead );
}
void SAL_CALL XFileStream::skipBytes( sal_Int32 nBytesToSkip )
        throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    seek ( mxTempSeek->getPosition() + nBytesToSkip );
}

sal_Int32 SAL_CALL XFileStream::available(  )
        throw( NotConnectedException, IOException, RuntimeException)
{
    return static_cast < sal_Int32 > ( mnZipSize - mxTempSeek->getPosition() );
}

void SAL_CALL XFileStream::closeInput(  )
        throw( NotConnectedException, IOException, RuntimeException)
{
}
void SAL_CALL XFileStream::seek( sal_Int64 location )
        throw( IllegalArgumentException, IOException, RuntimeException)
{
    if ( location > mnZipSize || location < 0 )
        throw IllegalArgumentException();
    if ( location > mxTempSeek->getLength() )
    {
        sal_Int64 nUntil = location + n_ConstBufferSize > mnZipSize ? mnZipSize : location + n_ConstBufferSize;
        fill ( nUntil );
    }
    mxTempSeek->seek ( location );
}
sal_Int64 SAL_CALL XFileStream::getPosition(  )
        throw(IOException, RuntimeException)
{
    return mxTempSeek->getPosition();
}
sal_Int64 SAL_CALL XFileStream::getLength(  )
        throw(IOException, RuntimeException)
{
    return mnZipSize;
}
<|endoftext|>


<commit_before>// $Id: boundary_info.C,v 1.46 2006-07-31 15:51:00 jwpeterson Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "libmesh_config.h"
#include "boundary_info.h"
#include "boundary_mesh.h"
#include "elem.h"
#include "mesh_data.h"

//------------------------------------------------------
// BoundaryInfo static member initializations
const short int BoundaryInfo::invalid_id = -1234;

//------------------------------------------------------
// BoundaryInfo functions
BoundaryInfo::BoundaryInfo(const MeshBase& m) :
  _mesh (m)
{
}

BoundaryInfo::~BoundaryInfo()
{
  this->clear();
}

void BoundaryInfo::clear()
{
  _boundary_node_id.clear();
  _boundary_side_id.clear();
  _boundary_ids.clear();
}

void BoundaryInfo::sync(BoundaryMesh& boundary_mesh,
			MeshData*     boundary_mesh_data,
			MeshData*     this_mesh_data)
{
  boundary_mesh.clear();

  /**
   * Re-create the boundary mesh.
   */

  std::map<unsigned int, unsigned int> new_node_numbers;

  boundary_mesh.set_n_subdomains() = this->n_boundary_ids();

  // Add sides to the structure.
  std::map<short int, unsigned int> id_map;

  // Original Code
  //     unsigned int cnt = 0;
  //     for (std::set<short int>::iterator pos = boundary_ids.begin();
  // 	 pos != boundary_ids.end(); ++pos)
  //       id_map[*pos] = cnt++;

  //     id_map[invalid_id] = cnt;

  // New code
  // Here we need to use iota() once it is in the
  // Utility namespace.
  std::for_each(_boundary_ids.begin(),
		_boundary_ids.end(),
		Fill(id_map));

  boundary_mesh.set_n_subdomains() = id_map.size();

  // Make individual copies of all the nodes in the current mesh
  // and add them to the boundary mesh.  Yes, this is overkill because
  // all of the current mesh nodes will not end up in the the boundary
  // mesh.  These nodes can be trimmed later via a call to prepare_for_use().
  {
    assert (boundary_mesh.n_nodes() == 0);
    boundary_mesh.reserve_nodes(_mesh.n_nodes());

    MeshBase::const_node_iterator it  = _mesh.nodes_begin();
    MeshBase::const_node_iterator end = _mesh.nodes_end();

    for(; it != end; ++it)
      {
	const Node* node = *it;
	boundary_mesh.add_point(*node);
      }
  }

  // Add additional sides that aren't flagged with boundary conditions
  MeshBase::const_element_iterator       el     = _mesh.active_elements_begin();
  const MeshBase::const_element_iterator end_el = _mesh.active_elements_end();

  for ( ; el != end_el; ++el)
    {
      const Elem* elem = *el;

      for (unsigned int s=0; s<elem->n_sides(); s++)
	if (elem->neighbor(s) == NULL) // on the boundary
	  {

	    // Build the side
	    AutoPtr<Elem> side (elem->build_side(s));

	    // Get the top-level parent for this element
	    const Elem* top_parent = elem->top_parent();

	    // A convenient typedef
	    typedef
	      std::multimap<const Elem*, std::pair<unsigned short int, short int> >::const_iterator
	      Iter;

	    // Find the right id number for that side
	    std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent);

	    while (pos.first != pos.second)
	      {
		if (pos.first->second.first == s) // already flagged with a boundary condition
		  {
		    side->subdomain_id() =
		      id_map[pos.first->second.second];

		    side->processor_id() =
		      side->subdomain_id();
		    break;
		  }

		++pos.first;
	      }

	    // either the element wasn't found or side s
	    // doesn't have a boundary condition
	    if (pos.first == pos.second)
	      {
		side->subdomain_id() = id_map[invalid_id];
	      }

	    // Add the side
	    Elem* new_elem = boundary_mesh.add_elem(side.release());

	    // This side's Node pointers still point to the nodes of the  original mesh.
	    // We need to re-point them to the boundary mesh's nodes!  Since we copied *ALL* of
	    // the original mesh's nodes over, we should be guaranteed to have the same ordering.
	    for (unsigned int nn=0; nn<new_elem->n_nodes(); ++nn)
	      {
		// Get the correct node pointer, based on the id()
		Node* new_node = boundary_mesh.node_ptr(new_elem->node(nn));

		// sanity check: be sure that the new Nodes global id really matches
		assert (new_node->id() == new_elem->node(nn));

		// Assign the new node pointer
		new_elem->set_node(nn) = new_node;
	      }
	  }
    } // end loop over active elements

  // When desired, copy the MeshData
  // to the boundary_mesh
  if ((boundary_mesh_data != NULL) && (this_mesh_data != NULL))
    boundary_mesh_data->assign(*this_mesh_data);
}

void BoundaryInfo::add_node(const unsigned int node,
			    const short int id)
{
  this->add_node (_mesh.node_ptr(node), id);
}

void BoundaryInfo::add_node(const Node* node,
			    const short int id)
{
  if (id == invalid_id)
    {
      std::cerr << "ERROR: You may not set a boundary ID of "
		<< invalid_id << std::endl
		<< " That is reserved for internal use.\n"
		<< std::endl;

      error();
    }

  _boundary_node_id[node] = id;
  _boundary_ids.insert(id);
}

void BoundaryInfo::add_side(const unsigned int e,
			    const unsigned short int side,
			    const short int id)
{
  this->add_side (_mesh.elem(e), side, id);
}

void BoundaryInfo::add_side(const Elem* elem,
			    const unsigned short int side,
			    const short int id)
{
  assert (elem != NULL);

  // Only add BCs for level-0 elements.
  assert (elem->level() == 0);

  if (id == invalid_id)
    {
      std::cerr << "ERROR: You may not set a boundary ID of "
		<< invalid_id << std::endl
		<< " That is reserved for internal use.\n"
		<< std::endl;

      error();
    }

  std::pair<unsigned short int, short int> p(side,id);
  std::pair<const Elem*, std::pair<unsigned short int, short int> >
    kv (elem, p);

  _boundary_side_id.insert(kv);
  _boundary_ids.insert(id);

  // Possilby add the nodes of the side,
  // if they aren't already there.
  {
    // MGF meshes seem to cause some trouble here, so don't
    // do this if the library is initialized with
    // --enable-mgf-workaround as an argument
    // command line can't change at run-time, so use a static here.
    static bool mgf_workaround =
      libMesh::on_command_line("--enable-mgf-workaround");

    if (!mgf_workaround)
      {
	assert (side < elem->n_sides());

	AutoPtr<Elem> side_elem(elem->build_side(side));

	for (unsigned int n=0; n<side_elem->n_nodes(); n++)
	  if (this->boundary_id(side_elem->get_node(n)) == invalid_id)
	    this->add_node(side_elem->get_node(n), id);
      }
  }
}

short int BoundaryInfo::boundary_id(const Node* node) const
{
  std::map<const Node*, short int>::const_iterator
    n = _boundary_node_id.find(node);

  // node not in the data structure
  if (n == _boundary_node_id.end())
    return invalid_id;

  return n->second;
}

short int BoundaryInfo::boundary_id(const Elem* const elem,
				    const unsigned short int side) const
{
  assert (elem != NULL);

  // Only level-0 elements store BCs.  If this is not a level-0
  // element get its level-0 parent and infer the BCs.
  const Elem*  searched_elem = elem;
  if (elem->level() != 0)
    searched_elem = elem->top_parent ();

  std::pair<std::multimap<const Elem*,
                          std::pair<unsigned short int, short int> >::const_iterator,
            std::multimap<const Elem*,
                          std::pair<unsigned short int, short int> >::const_iterator >
    e = _boundary_side_id.equal_range(searched_elem);

  // elem not in the data structure
  if (e.first == e.second)
    return invalid_id;

  // elem is there, maybe multiple occurances
  while (e.first != e.second)
    {
      // if this is true we found the requested side
      // of the element and want to return the id
      if (e.first->second.first == side)
	return e.first->second.second;

      ++e.first;
    }

  // if we get here, we found elem in the data structure but not
  // the requested side, so return the default value
  return invalid_id;
}

void BoundaryInfo::build_node_list (std::vector<unsigned int>& nl,
				    std::vector<short int>&    il) const
{
  // Reserve the size, then use push_back
  nl.reserve (_boundary_node_id.size());
  il.reserve (_boundary_node_id.size());

  std::map<const Node*, short int>::const_iterator pos;

  for (pos=_boundary_node_id.begin(); pos != _boundary_node_id.end();
       ++pos)
    {
      nl.push_back (pos->first->id());
      il.push_back (pos->second);
    }
}

void BoundaryInfo::build_side_list (std::vector<unsigned int>&       el,
				    std::vector<unsigned short int>& sl,
				    std::vector<short int>&          il) const
{
  // Reserve the size, then use push_back
  el.reserve (_boundary_side_id.size());
  sl.reserve (_boundary_side_id.size());
  il.reserve (_boundary_side_id.size());

  std::multimap<const Elem*,
                std::pair<unsigned short int,
                          short int> >::const_iterator pos;

  for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end();
       ++pos)
    {
      el.push_back (pos->first->id());
      sl.push_back (pos->second.first);
      il.push_back (pos->second.second);
    }
}

void BoundaryInfo::print_info() const
{
  // Print out the nodal BCs
  if (!_boundary_node_id.empty())
    {
      std::cout << "Nodal Boundary conditions:" << std::endl
		<< "--------------------------" << std::endl
		<< "  (Node No., ID)               " << std::endl;

//       std::for_each(_boundary_node_id.begin(),
// 		    _boundary_node_id.end(),
// 		    PrintNodeInfo());

      std::map<const Node*, short int>::const_iterator it        = _boundary_node_id.begin();
      const std::map<const Node*, short int>::const_iterator end = _boundary_node_id.end();

      for (; it != end; ++it)
	std::cout << "  (" << (*it).first->id()
		  << ", "  << (*it).second
		  << ")"  << std::endl;
    }

  // Print out the element BCs
  if (!_boundary_side_id.empty())
    {
      std::cout << std::endl
		<< "Side Boundary conditions:" << std::endl
		<< "-------------------------" << std::endl
		<< "  (Elem No., Side No., ID)      " << std::endl;

//       std::for_each(_boundary_side_id.begin(),
// 		    _boundary_side_id.end(),
//   		    PrintSideInfo());

      std::multimap<const Elem*,
	std::pair<unsigned short int, short int> >::const_iterator it = _boundary_side_id.begin();
      const std::multimap<const Elem*,
	std::pair<unsigned short int, short int> >::const_iterator end = _boundary_side_id.end();

     for (; it != end; ++it)
       std::cout << "  (" << (*it).first->id()
		 << ", "  << (*it).second.first
		 << ", "  << (*it).second.second
		 << ")"   << std::endl;
    }
}
<commit_msg>Initialize iterator outside for loop.<commit_after>// $Id: boundary_info.C,v 1.47 2007-01-29 16:36:49 jwpeterson Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "libmesh_config.h"
#include "boundary_info.h"
#include "boundary_mesh.h"
#include "elem.h"
#include "mesh_data.h"

//------------------------------------------------------
// BoundaryInfo static member initializations
const short int BoundaryInfo::invalid_id = -1234;

//------------------------------------------------------
// BoundaryInfo functions
BoundaryInfo::BoundaryInfo(const MeshBase& m) :
  _mesh (m)
{
}

BoundaryInfo::~BoundaryInfo()
{
  this->clear();
}

void BoundaryInfo::clear()
{
  _boundary_node_id.clear();
  _boundary_side_id.clear();
  _boundary_ids.clear();
}

void BoundaryInfo::sync(BoundaryMesh& boundary_mesh,
			MeshData*     boundary_mesh_data,
			MeshData*     this_mesh_data)
{
  boundary_mesh.clear();

  /**
   * Re-create the boundary mesh.
   */

  std::map<unsigned int, unsigned int> new_node_numbers;

  boundary_mesh.set_n_subdomains() = this->n_boundary_ids();

  // Add sides to the structure.
  std::map<short int, unsigned int> id_map;

  // Original Code
  //     unsigned int cnt = 0;
  //     for (std::set<short int>::iterator pos = boundary_ids.begin();
  // 	 pos != boundary_ids.end(); ++pos)
  //       id_map[*pos] = cnt++;

  //     id_map[invalid_id] = cnt;

  // New code
  // Here we need to use iota() once it is in the
  // Utility namespace.
  std::for_each(_boundary_ids.begin(),
		_boundary_ids.end(),
		Fill(id_map));

  boundary_mesh.set_n_subdomains() = id_map.size();

  // Make individual copies of all the nodes in the current mesh
  // and add them to the boundary mesh.  Yes, this is overkill because
  // all of the current mesh nodes will not end up in the the boundary
  // mesh.  These nodes can be trimmed later via a call to prepare_for_use().
  {
    assert (boundary_mesh.n_nodes() == 0);
    boundary_mesh.reserve_nodes(_mesh.n_nodes());

    MeshBase::const_node_iterator it  = _mesh.nodes_begin();
    MeshBase::const_node_iterator end = _mesh.nodes_end();

    for(; it != end; ++it)
      {
	const Node* node = *it;
	boundary_mesh.add_point(*node);
      }
  }

  // Add additional sides that aren't flagged with boundary conditions
  MeshBase::const_element_iterator       el     = _mesh.active_elements_begin();
  const MeshBase::const_element_iterator end_el = _mesh.active_elements_end();

  for ( ; el != end_el; ++el)
    {
      const Elem* elem = *el;

      for (unsigned int s=0; s<elem->n_sides(); s++)
	if (elem->neighbor(s) == NULL) // on the boundary
	  {

	    // Build the side
	    AutoPtr<Elem> side (elem->build_side(s));

	    // Get the top-level parent for this element
	    const Elem* top_parent = elem->top_parent();

	    // A convenient typedef
	    typedef
	      std::multimap<const Elem*, std::pair<unsigned short int, short int> >::const_iterator
	      Iter;

	    // Find the right id number for that side
	    std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent);

	    while (pos.first != pos.second)
	      {
		if (pos.first->second.first == s) // already flagged with a boundary condition
		  {
		    side->subdomain_id() =
		      id_map[pos.first->second.second];

		    side->processor_id() =
		      side->subdomain_id();
		    break;
		  }

		++pos.first;
	      }

	    // either the element wasn't found or side s
	    // doesn't have a boundary condition
	    if (pos.first == pos.second)
	      {
		side->subdomain_id() = id_map[invalid_id];
	      }

	    // Add the side
	    Elem* new_elem = boundary_mesh.add_elem(side.release());

	    // This side's Node pointers still point to the nodes of the  original mesh.
	    // We need to re-point them to the boundary mesh's nodes!  Since we copied *ALL* of
	    // the original mesh's nodes over, we should be guaranteed to have the same ordering.
	    for (unsigned int nn=0; nn<new_elem->n_nodes(); ++nn)
	      {
		// Get the correct node pointer, based on the id()
		Node* new_node = boundary_mesh.node_ptr(new_elem->node(nn));

		// sanity check: be sure that the new Nodes global id really matches
		assert (new_node->id() == new_elem->node(nn));

		// Assign the new node pointer
		new_elem->set_node(nn) = new_node;
	      }
	  }
    } // end loop over active elements

  // When desired, copy the MeshData
  // to the boundary_mesh
  if ((boundary_mesh_data != NULL) && (this_mesh_data != NULL))
    boundary_mesh_data->assign(*this_mesh_data);
}

void BoundaryInfo::add_node(const unsigned int node,
			    const short int id)
{
  this->add_node (_mesh.node_ptr(node), id);
}

void BoundaryInfo::add_node(const Node* node,
			    const short int id)
{
  if (id == invalid_id)
    {
      std::cerr << "ERROR: You may not set a boundary ID of "
		<< invalid_id << std::endl
		<< " That is reserved for internal use.\n"
		<< std::endl;

      error();
    }

  _boundary_node_id[node] = id;
  _boundary_ids.insert(id);
}

void BoundaryInfo::add_side(const unsigned int e,
			    const unsigned short int side,
			    const short int id)
{
  this->add_side (_mesh.elem(e), side, id);
}

void BoundaryInfo::add_side(const Elem* elem,
			    const unsigned short int side,
			    const short int id)
{
  assert (elem != NULL);

  // Only add BCs for level-0 elements.
  assert (elem->level() == 0);

  if (id == invalid_id)
    {
      std::cerr << "ERROR: You may not set a boundary ID of "
		<< invalid_id << std::endl
		<< " That is reserved for internal use.\n"
		<< std::endl;

      error();
    }

  std::pair<unsigned short int, short int> p(side,id);
  std::pair<const Elem*, std::pair<unsigned short int, short int> >
    kv (elem, p);

  _boundary_side_id.insert(kv);
  _boundary_ids.insert(id);

  // Possilby add the nodes of the side,
  // if they aren't already there.
  {
    // MGF meshes seem to cause some trouble here, so don't
    // do this if the library is initialized with
    // --enable-mgf-workaround as an argument
    // command line can't change at run-time, so use a static here.
    static bool mgf_workaround =
      libMesh::on_command_line("--enable-mgf-workaround");

    if (!mgf_workaround)
      {
	assert (side < elem->n_sides());

	AutoPtr<Elem> side_elem(elem->build_side(side));

	for (unsigned int n=0; n<side_elem->n_nodes(); n++)
	  if (this->boundary_id(side_elem->get_node(n)) == invalid_id)
	    this->add_node(side_elem->get_node(n), id);
      }
  }
}

short int BoundaryInfo::boundary_id(const Node* node) const
{
  std::map<const Node*, short int>::const_iterator
    n = _boundary_node_id.find(node);

  // node not in the data structure
  if (n == _boundary_node_id.end())
    return invalid_id;

  return n->second;
}

short int BoundaryInfo::boundary_id(const Elem* const elem,
				    const unsigned short int side) const
{
  assert (elem != NULL);

  // Only level-0 elements store BCs.  If this is not a level-0
  // element get its level-0 parent and infer the BCs.
  const Elem*  searched_elem = elem;
  if (elem->level() != 0)
    searched_elem = elem->top_parent ();

  std::pair<std::multimap<const Elem*,
                          std::pair<unsigned short int, short int> >::const_iterator,
            std::multimap<const Elem*,
                          std::pair<unsigned short int, short int> >::const_iterator >
    e = _boundary_side_id.equal_range(searched_elem);

  // elem not in the data structure
  if (e.first == e.second)
    return invalid_id;

  // elem is there, maybe multiple occurances
  while (e.first != e.second)
    {
      // if this is true we found the requested side
      // of the element and want to return the id
      if (e.first->second.first == side)
	return e.first->second.second;

      ++e.first;
    }

  // if we get here, we found elem in the data structure but not
  // the requested side, so return the default value
  return invalid_id;
}

void BoundaryInfo::build_node_list (std::vector<unsigned int>& nl,
				    std::vector<short int>&    il) const
{
  // Reserve the size, then use push_back
  nl.reserve (_boundary_node_id.size());
  il.reserve (_boundary_node_id.size());

  std::map<const Node*, short int>::const_iterator pos
    = _boundary_node_id.begin();

  for (; pos != _boundary_node_id.end(); ++pos)
    {
      nl.push_back (pos->first->id());
      il.push_back (pos->second);
    }
}

void BoundaryInfo::build_side_list (std::vector<unsigned int>&       el,
				    std::vector<unsigned short int>& sl,
				    std::vector<short int>&          il) const
{
  // Reserve the size, then use push_back
  el.reserve (_boundary_side_id.size());
  sl.reserve (_boundary_side_id.size());
  il.reserve (_boundary_side_id.size());

  std::multimap<const Elem*,
                std::pair<unsigned short int,
                          short int> >::const_iterator pos;

  for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end();
       ++pos)
    {
      el.push_back (pos->first->id());
      sl.push_back (pos->second.first);
      il.push_back (pos->second.second);
    }
}

void BoundaryInfo::print_info() const
{
  // Print out the nodal BCs
  if (!_boundary_node_id.empty())
    {
      std::cout << "Nodal Boundary conditions:" << std::endl
		<< "--------------------------" << std::endl
		<< "  (Node No., ID)               " << std::endl;

//       std::for_each(_boundary_node_id.begin(),
// 		    _boundary_node_id.end(),
// 		    PrintNodeInfo());

      std::map<const Node*, short int>::const_iterator it        = _boundary_node_id.begin();
      const std::map<const Node*, short int>::const_iterator end = _boundary_node_id.end();

      for (; it != end; ++it)
	std::cout << "  (" << (*it).first->id()
		  << ", "  << (*it).second
		  << ")"  << std::endl;
    }

  // Print out the element BCs
  if (!_boundary_side_id.empty())
    {
      std::cout << std::endl
		<< "Side Boundary conditions:" << std::endl
		<< "-------------------------" << std::endl
		<< "  (Elem No., Side No., ID)      " << std::endl;

//       std::for_each(_boundary_side_id.begin(),
// 		    _boundary_side_id.end(),
//   		    PrintSideInfo());

      std::multimap<const Elem*,
	std::pair<unsigned short int, short int> >::const_iterator it = _boundary_side_id.begin();
      const std::multimap<const Elem*,
	std::pair<unsigned short int, short int> >::const_iterator end = _boundary_side_id.end();

     for (; it != end; ++it)
       std::cout << "  (" << (*it).first->id()
		 << ", "  << (*it).second.first
		 << ", "  << (*it).second.second
		 << ")"   << std::endl;
    }
}
<|endoftext|>


<commit_before>#include "sevensegment.h"
#include <ostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <stdexcept>

namespace sevensegment {
	using digit = std::vector<std::string>;
	using digit_vector = std::vector<digit>;

	digit_vector const digits {
		{ " - ", "| |", "   ", "| |", " - " }, // 0
		{ "   ", "  |", "   ", "  |", "   " }, // 1
		{ " - ", "  |", " - ", "|  ", " - " }, // 2
		{ " - ", "  |", " - ", "  |", " - " }, // 3
		{ "   ", "| |", " - ", "  |", "   " }, // 4
		{ " - ", "|  ", " - ", "  |", " - " }, // 5
		{ " - ", "|  ", " - ", "| |", " - " }, // 6
		{ " - ", "  |", "   ", "  |", "   " }, // 7
		{ " - ", "| |", " - ", "| |", " - " }, // 8
		{ " - ", "| |", " - ", "  |", " - " }  // 9
	};
	digit const minus_sign
		{ "   ", "   ", " - ", "   ", "   " }; // -

	std::string stretchDigitLine(std::string const& line, unsigned const scale_factor) {
		std::string stretched_line(scale_factor+2, line[1]); // stretch the center
		stretched_line.front() = line[0]; // fix first char
		stretched_line.back() = line[2]; // fix last char
		return stretched_line;
	}

	digit_vector split_digits(int const i, digit_vector& vector) {
	    if(i >= 10)
	       split_digits(i / 10, vector);

	    vector.push_back(digits.at(i % 10));
	    return vector;
	}

	digit_vector split_digits(int i) {
		digit_vector vector {};
		if (i<0) {
			vector.push_back(minus_sign);
			i = -i;
		}

		return split_digits(i, vector);
	}

	std::string lineOfLargeDigits(digit_vector const& vector,
			unsigned const line_nr, unsigned const scale_factor){

		std::string const letter_space(scale_factor/2, ' ');
		std::string line {};
		bool first_digit = true;

		// NOTE: It would be really nice to have an infix_iterator.
		// http://stackoverflow.com/questions/3496982/printing-lists-with-commas-c/3497021#3497021
		for(digit d : vector) {
			if (!first_digit) line += letter_space;
			line += stretchDigitLine(d[line_nr], scale_factor);
			first_digit = false;
		}

		return line;
	}

	unsigned const display_size { 8 };
	std::vector<int> const line_numbers { 0, 1, 2, 3, 4 };

	void printDigitSequence(digit_vector const& vector,
			std::ostream& out, unsigned const scale_factor){

		if (scale_factor<1)
			throw std::out_of_range { "invalid scale" };
		if (vector.size() > display_size)
			throw std::overflow_error { "too many digits" };

		std::ostream_iterator<std::string> out_it(out, "\n");

		// iterate through lines, not digits
		// OPTIMIZE: transpose vector first to get more cache hits
		for_each(begin(line_numbers), end(line_numbers), [&](int line_nr) {
			auto count = (line_nr == 1 || line_nr == 3) ? scale_factor : 1;
			auto line = lineOfLargeDigits(vector, line_nr, scale_factor);
			std::fill_n(out_it, count, line);
		});
	}

	// Requested for the assignment. Used nowhere but in the tests.
	void printLargeDigit(unsigned const i, std::ostream& out, unsigned const scale_factor) {
		auto const d = digits.at(i); // NOTE: will throw std::out_of_range if i not within 0..9
		digit_vector const single_digit_vector { d };
		printDigitSequence(single_digit_vector, out, scale_factor);
	}

	void printLargeNumber(int const i, std::ostream& out, unsigned const scale_factor) {
		printDigitSequence(split_digits(i), out, scale_factor);
	}

	digit_vector const error {
		{ " - ", "|  ", " - ", "|  ", " - " }, // E
		{ "   ", "   ", " - ", "|  ", "   " }, // r
		{ "   ", "   ", " - ", "|  ", "   " }, // r
		{ "   ", "   ", " - ", "| |", " - " }, // o
		{ "   ", "   ", " - ", "|  ", "   " }, // r
	};

	void printLargeError(std::ostream& out, unsigned const scale_factor) {
		printDigitSequence(error, out, scale_factor);
	}
}
<commit_msg>explicitly list captures for lambda<commit_after>#include "sevensegment.h"
#include <ostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <stdexcept>

namespace sevensegment {
	using digit = std::vector<std::string>;
	using digit_vector = std::vector<digit>;

	digit_vector const digits {
		{ " - ", "| |", "   ", "| |", " - " }, // 0
		{ "   ", "  |", "   ", "  |", "   " }, // 1
		{ " - ", "  |", " - ", "|  ", " - " }, // 2
		{ " - ", "  |", " - ", "  |", " - " }, // 3
		{ "   ", "| |", " - ", "  |", "   " }, // 4
		{ " - ", "|  ", " - ", "  |", " - " }, // 5
		{ " - ", "|  ", " - ", "| |", " - " }, // 6
		{ " - ", "  |", "   ", "  |", "   " }, // 7
		{ " - ", "| |", " - ", "| |", " - " }, // 8
		{ " - ", "| |", " - ", "  |", " - " }  // 9
	};
	digit const minus_sign
		{ "   ", "   ", " - ", "   ", "   " }; // -

	std::string stretchDigitLine(std::string const& line, unsigned const scale_factor) {
		std::string stretched_line(scale_factor+2, line[1]); // stretch the center
		stretched_line.front() = line[0]; // fix first char
		stretched_line.back() = line[2]; // fix last char
		return stretched_line;
	}

	digit_vector split_digits(int const i, digit_vector& vector) {
	    if(i >= 10)
	       split_digits(i / 10, vector);

	    vector.push_back(digits.at(i % 10));
	    return vector;
	}

	digit_vector split_digits(int i) {
		digit_vector vector {};
		if (i<0) {
			vector.push_back(minus_sign);
			i = -i;
		}

		return split_digits(i, vector);
	}

	std::string lineOfLargeDigits(digit_vector const& vector,
			unsigned const line_nr, unsigned const scale_factor){

		std::string const letter_space(scale_factor/2, ' ');
		std::string line {};
		bool first_digit = true;

		// NOTE: It would be really nice to have an infix_iterator.
		// http://stackoverflow.com/questions/3496982/printing-lists-with-commas-c/3497021#3497021
		for(digit d : vector) {
			if (!first_digit) line += letter_space;
			line += stretchDigitLine(d[line_nr], scale_factor);
			first_digit = false;
		}

		return line;
	}

	unsigned const display_size { 8 };
	std::vector<int> const line_numbers { 0, 1, 2, 3, 4 };

	void printDigitSequence(digit_vector const& vector,
			std::ostream& out, unsigned const scale_factor){

		if (scale_factor<1)
			throw std::out_of_range { "invalid scale" };
		if (vector.size() > display_size)
			throw std::overflow_error { "too many digits" };

		std::ostream_iterator<std::string> out_it(out, "\n");

		// iterate through lines, not digits
		// OPTIMIZE: transpose vector first to get more cache hits
		for_each(begin(line_numbers), end(line_numbers),
				[scale_factor,&vector,&out_it](int line_nr) {

			auto count = (line_nr == 1 || line_nr == 3) ? scale_factor : 1;
			auto line = lineOfLargeDigits(vector, line_nr, scale_factor);
			std::fill_n(out_it, count, line);
		});
	}

	// Requested for the assignment. Used nowhere but in the tests.
	void printLargeDigit(unsigned const i, std::ostream& out, unsigned const scale_factor) {
		auto const d = digits.at(i); // NOTE: will throw std::out_of_range if i not within 0..9
		digit_vector const single_digit_vector { d };
		printDigitSequence(single_digit_vector, out, scale_factor);
	}

	void printLargeNumber(int const i, std::ostream& out, unsigned const scale_factor) {
		printDigitSequence(split_digits(i), out, scale_factor);
	}

	digit_vector const error {
		{ " - ", "|  ", " - ", "|  ", " - " }, // E
		{ "   ", "   ", " - ", "|  ", "   " }, // r
		{ "   ", "   ", " - ", "|  ", "   " }, // r
		{ "   ", "   ", " - ", "| |", " - " }, // o
		{ "   ", "   ", " - ", "|  ", "   " }, // r
	};

	void printLargeError(std::ostream& out, unsigned const scale_factor) {
		printDigitSequence(error, out, scale_factor);
	}
}
<|endoftext|>


<commit_before>/*
*****************************************************************************
*                      ___       _   _    _ _
*                     / _ \ __ _| |_| |__(_) |_ ___
*                    | (_) / _` | / / '_ \ |  _(_-<
*                     \___/\__,_|_\_\_.__/_|\__/__/
*                          Copyright (c) 2012
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*****************************************************************************/
/**
* @author   R. Picard
* @date     2012/01/03
*
*****************************************************************************/
#include <new>
#include "MemAlignProbe.h"
#include "ExeContext.h"
#include "HeapEntry.h"

/**
* @date     2012/01/03
*
*  Constructor.
*
******************************************************************************/
MemAlignProbe::MemAlignProbe(void):
   MemProbe(),
   AlignFunc(NULL)
{
   return;
}

/**
* @date     2012/01/03
*
*  Destructor.
*
******************************************************************************/
MemAlignProbe::~MemAlignProbe()
{
   return;
}

/**
* @date     2012/01/03
*
*  Probe initialization.
*
******************************************************************************/
void MemAlignProbe::InitCheck(void)
{
   if(AlignFunc == NULL)
   {
      AlignFunc = (memalign_t) rtsym_resolve("memalign");
   }
   return;
}

/**
* @date     2012/04/29
*
*  Probe initialization. This method is used for unitest so that a fake align
*  function can be used.
*
******************************************************************************/
void MemAlignProbe::InitCheck(memalign_t AlignHook)
{
   if(AlignFunc == NULL)
   {
      AlignFunc = AlignHook;
   }
   return;
}

/**
* @date     2012/01/03
*
*  Probe Passthrough : The original function is called direclty.
*
******************************************************************************/
void* MemAlignProbe::PassThrough(size_t i_Boundary, size_t i_Size)
{
   void *Data;
   memalign_t AlignFunc;

   AlignFunc = (memalign_t) rtsym_resolve("memalign");
   if(AlignFunc != NULL)
   {
      Data = AlignFunc(i_Boundary, i_Size);
   }
   return(Data);
}

/**
* @date     2012/01/03
*
*  Frees previously allocated data.
*
******************************************************************************/
void* MemAlignProbe::MemAlign(size_t i_Boundary, size_t i_Size, const CallStack& Callers)
{
   uint8_t  *Data = NULL;
   uint32_t Padding = MemProbe::GetAlignmentPadding(i_Boundary, sizeof(HeapEntry));

   if(AlignFunc != NULL)
   {
      if(GetHeap()->Lock() == 0)
      {
         Data = (uint8_t*)AlignFunc(i_Boundary, i_Size + sizeof(HeapEntry) + Padding);
         if(Data != NULL)
         {
            ExeContext *p_Context = ExeContext::Get(Callers);
            HeapEntry  *Entry = new (Data + Padding) HeapEntry(i_Size, p_Context);

            Entry->Start = Data;
            GetHeap()->GetEntryList()->AppendItem(Entry);
            if(p_Context != NULL)
               p_Context->UpdateMemory(i_Size);

            Data = Data + sizeof(HeapEntry) + Padding;
         }
      }
      else
      {
         Data = (uint8_t*)AlignFunc(i_Boundary, i_Size);
      }
      GetHeap()->Unlock();

   }
   return(Data);
}

<commit_msg>Fixes #11<commit_after>/*
*****************************************************************************
*                      ___       _   _    _ _
*                     / _ \ __ _| |_| |__(_) |_ ___
*                    | (_) / _` | / / '_ \ |  _(_-<
*                     \___/\__,_|_\_\_.__/_|\__/__/
*                          Copyright (c) 2012
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*****************************************************************************/
/**
* @author   R. Picard
* @date     2012/01/03
*
*****************************************************************************/
#include <new>
#include "MemAlignProbe.h"
#include "ExeContext.h"
#include "HeapEntry.h"

/**
* @date     2012/01/03
*
*  Constructor.
*
******************************************************************************/
MemAlignProbe::MemAlignProbe(void):
   MemProbe(),
   AlignFunc(NULL)
{
   return;
}

/**
* @date     2012/01/03
*
*  Destructor.
*
******************************************************************************/
MemAlignProbe::~MemAlignProbe()
{
   return;
}

/**
* @date     2012/01/03
*
*  Probe initialization.
*
******************************************************************************/
void MemAlignProbe::InitCheck(void)
{
   if(AlignFunc == NULL)
   {
      AlignFunc = (memalign_t) rtsym_resolve("memalign");
   }
   return;
}

/**
* @date     2012/04/29
*
*  Probe initialization. This method is used for unitest so that a fake align
*  function can be used.
*
******************************************************************************/
void MemAlignProbe::InitCheck(memalign_t AlignHook)
{
   if(AlignFunc == NULL)
   {
      AlignFunc = AlignHook;
   }
   return;
}

/**
* @date     2012/01/03
*
*  Probe Passthrough : The original function is called direclty.
*
******************************************************************************/
void* MemAlignProbe::PassThrough(size_t i_Boundary, size_t i_Size)
{
   void *Data = NULL;
   memalign_t AlignFunc;

   AlignFunc = (memalign_t) rtsym_resolve("memalign");
   if(AlignFunc != NULL)
   {
      Data = AlignFunc(i_Boundary, i_Size);
   }
   return(Data);
}

/**
* @date     2012/01/03
*
*  Frees previously allocated data.
*
******************************************************************************/
void* MemAlignProbe::MemAlign(size_t i_Boundary, size_t i_Size, const CallStack& Callers)
{
   uint8_t  *Data = NULL;
   uint32_t Padding = MemProbe::GetAlignmentPadding(i_Boundary, sizeof(HeapEntry));

   if(AlignFunc != NULL)
   {
      if(GetHeap()->Lock() == 0)
      {
         Data = (uint8_t*)AlignFunc(i_Boundary, i_Size + sizeof(HeapEntry) + Padding);
         if(Data != NULL)
         {
            ExeContext *p_Context = ExeContext::Get(Callers);
            HeapEntry  *Entry = new (Data + Padding) HeapEntry(i_Size, p_Context);

            Entry->Start = Data;
            GetHeap()->GetEntryList()->AppendItem(Entry);
            if(p_Context != NULL)
               p_Context->UpdateMemory(i_Size);

            Data = Data + sizeof(HeapEntry) + Padding;
         }
      }
      else
      {
         Data = (uint8_t*)AlignFunc(i_Boundary, i_Size);
      }
      GetHeap()->Unlock();

   }
   return(Data);
}

<|endoftext|>


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

Daemon GPL Source Code
Copyright (C) 2012 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code 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.

Daemon Source Code 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 Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

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

// Code to deal with libRocket's loading and handling of documents and elements

#include "rocket.h"
#include "client.h"

void Rocket_LoadDocument( const char *path )
{
	Rocket::Core::ElementDocument* document = menuContext->LoadDocument( path );
	Rocket::Core::ElementDocument* other;

	if( document )
	{
		document->Hide();
		document->RemoveReference();
		menuContext->PullDocumentToFront( document ); // Ensure any duplicates will be found first.

		// Close any other documents which may have the same ID
		other = menuContext->GetDocument( document->GetId() );
		if ( other && other != document )
		{
			other->Close();
		}
	}

}

void Rocket_LoadCursor( const char *path )
{
	Rocket::Core::ElementDocument* document = menuContext->LoadMouseCursor( path );
	if( document )
	{
		document->RemoveReference();
	}
}

void Rocket_DocumentAction( const char *name, const char *action )
{
	if ( !Q_stricmp( action, "show" ) || !Q_stricmp( action, "open" ) )
	{
		Rocket::Core::ElementDocument* document = menuContext->GetDocument( name );
		if ( document )
		{
			document->Show();
		}
	}
	else if ( !Q_stricmp( "close", action ) )
	{
		if ( !*name ) // If name is empty, hide active
		{
			if ( menuContext->GetFocusElement() &&
				menuContext->GetFocusElement()->GetOwnerDocument() )
			{
				menuContext->GetFocusElement()->GetOwnerDocument()->Close();
			}

			return;
		}

		Rocket::Core::ElementDocument* document = menuContext->GetDocument( name );
		if ( document )
		{
			document->Close();
		}
	}
	else if ( !Q_stricmp( "goto", action ) )
	{
		Rocket::Core::ElementDocument* document = menuContext->GetDocument( name );
		if ( document )
		{
			Rocket::Core::ElementDocument *owner = menuContext->GetFocusElement()->GetOwnerDocument();
			if ( owner )
			{
				owner->Close();
			}
			document->Show();
		}
	}
	else if ( !Q_stricmp( "load", action ) )
	{
		Rocket_LoadDocument( name );
	}
	else if ( !Q_stricmp( "blur", action ) || !Q_stricmp( "hide", action ) )
	{
		if ( !*name ) // If name is empty, hide active
		{
			if ( menuContext->GetFocusElement() &&
				menuContext->GetFocusElement()->GetOwnerDocument() )
			{
				menuContext->GetFocusElement()->GetOwnerDocument()->Hide();
			}

			return;
		}

		Rocket::Core::ElementDocument* document = menuContext->GetDocument( name );
		if ( document )
		{
			document->Hide();
		}
	}
	else if ( !Q_stricmp ( "blurall", action ) )
	{
		for ( int i = 0; i < menuContext->GetNumDocuments(); ++i )
		{
			menuContext->GetDocument( i )->Hide();
		}
	}
}
<commit_msg>Add a reload document action to simplify reloading documents<commit_after>/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 2012 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code 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.

Daemon Source Code 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 Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

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

// Code to deal with libRocket's loading and handling of documents and elements

#include "rocket.h"
#include "client.h"

void Rocket_LoadDocument( const char *path )
{
	Rocket::Core::ElementDocument* document = menuContext->LoadDocument( path );
	Rocket::Core::ElementDocument* other;

	if( document )
	{
		document->Hide();
		document->RemoveReference();
		menuContext->PullDocumentToFront( document ); // Ensure any duplicates will be found first.

		// Close any other documents which may have the same ID
		other = menuContext->GetDocument( document->GetId() );
		if ( other && other != document )
		{
			other->Close();
		}
	}

}

void Rocket_LoadCursor( const char *path )
{
	Rocket::Core::ElementDocument* document = menuContext->LoadMouseCursor( path );
	if( document )
	{
		document->RemoveReference();
	}
}

void Rocket_DocumentAction( const char *name, const char *action )
{
	if ( !Q_stricmp( action, "show" ) || !Q_stricmp( action, "open" ) )
	{
		Rocket::Core::ElementDocument* document = menuContext->GetDocument( name );
		if ( document )
		{
			document->Show();
		}
	}
	else if ( !Q_stricmp( "close", action ) )
	{
		if ( !*name ) // If name is empty, hide active
		{
			if ( menuContext->GetFocusElement() &&
				menuContext->GetFocusElement()->GetOwnerDocument() )
			{
				menuContext->GetFocusElement()->GetOwnerDocument()->Close();
			}

			return;
		}

		Rocket::Core::ElementDocument* document = menuContext->GetDocument( name );
		if ( document )
		{
			document->Close();
		}
	}
	else if ( !Q_stricmp( "goto", action ) )
	{
		Rocket::Core::ElementDocument* document = menuContext->GetDocument( name );
		if ( document )
		{
			Rocket::Core::ElementDocument *owner = menuContext->GetFocusElement()->GetOwnerDocument();
			if ( owner )
			{
				owner->Close();
			}
			document->Show();
		}
	}
	else if ( !Q_stricmp( "load", action ) )
	{
		Rocket_LoadDocument( name );
	}
	else if ( !Q_stricmp( "blur", action ) || !Q_stricmp( "hide", action ) )
	{
		Rocket::Core::ElementDocument* document = nullptr;

		if ( !*name ) // If name is empty, hide active
		{
			if ( menuContext->GetFocusElement() &&
				menuContext->GetFocusElement()->GetOwnerDocument() )
			{
				document = menuContext->GetFocusElement()->GetOwnerDocument();
			}
		}
		else
		{
			Rocket::Core::ElementDocument* document = menuContext->GetDocument( name );
		}

		if ( document )
		{
			document->Hide();
		}
	}
	else if ( !Q_stricmp ( "blurall", action ) )
	{
		for ( int i = 0; i < menuContext->GetNumDocuments(); ++i )
		{
			menuContext->GetDocument( i )->Hide();
		}
	}
	else if ( !Q_stricmp( "reload", action ) )
	{
		Rocket::Core::ElementDocument* document = nullptr;

		if ( !*name ) // If name is empty, hide active
		{
			if ( menuContext->GetFocusElement() &&
				menuContext->GetFocusElement()->GetOwnerDocument() )
			{
				document = menuContext->GetFocusElement()->GetOwnerDocument();
			}
		}
		else
		{
			document = menuContext->GetDocument( name );
		}

		if ( document )
		{
			Rocket::Core::String url = document->GetSourceURL();
			document->Close();
			document = menuContext->LoadDocument( url );
			document->Show();
		}
	}
}
<|endoftext|>


<commit_before>/**
 * @file    Kmer.hpp
 * @ingroup common
 * @author  Patrick Flick
 * @brief   Implements the Kmer class.
 *
 * Copyright (c) TODO
 *
 * TODO add Licence
 */
#ifndef BLISS_COMMON_KMER_H
#define BLISS_COMMON_KMER_H

// C std lib includes:
#include <cstdlib>

// C++ STL includes:
#include <iterator>
#include <type_traits>

// own includes
#include <common/base_types.hpp>
#include <common/bit_ops.hpp>
#include <common/padding.hpp>

namespace bliss
{

template <unsigned int KMER_SIZE, unsigned int BITS_PER_CHAR, typename word_type=WordType>
class Kmer
{
  static constexpr unsigned int size = KMER_SIZE;
  static constexpr unsigned int bitsPerChar = BITS_PER_CHAR;
  static constexpr unsigned int nBits = size * bitsPerChar;
  static constexpr unsigned int nBytes = intCeil<unsigned int>(nBits, 8);
  static constexpr unsigned int nWords = intCeil<unsigned int>(nBytes, sizeof(word_type));
  // padding internal to Kmer (only in last storage word)
  static constexpr unsigned int padBits = nWords*sizeof(word_type)*8 - nBits;
  static constexpr unsigned int invPadBits = sizeof(word_type)*8 - padBits;
  static constexpr unsigned int padBytes = nWords*sizeof(word_type) - nBytes;

  // last character offsets (and whether or not it is split accord storage words)
  static constexpr unsigned int lastCharOffset = nBits - bitsPerChar;
  static constexpr bool lastCharIsSplit = (lastCharOffset < (nWords-1)*sizeof(word_type)*8);
  static constexpr unsigned int lastCharWordOffset = lastCharOffset % (sizeof(word_type)*8);
  static constexpr unsigned int leftSplitSize = sizeof(word_type)*8 - lastCharWordOffset;

  // storage:
  word_type data[nWords];

public:

  Kmer()
  {
    // make this a valid Kmer
    do_sanitize();
  }

  template<typename InputIterator>
  Kmer(InputIterator begin)
  {
    static_assert(std::is_same<typename std::iterator_traits<InputIterator>::value_type, word_type>::value, "Input iterator must have same value type as the Kmer storage");
    word_type* out = data;
    for (unsigned int i = 0; i < nWords; ++i)
    {
      *(out++) = *(begin++);
    }
    do_sanitize();
  }

  inline void do_sanitize()
  {
    // TODO use templated helper struct for <0> template specialization
    data[nWords-1] &= getBitMask<word_type>(invPadBits);
  }

  // TODO template specialization for nWords = 1 (just use base type shift)
  // TODO implement more efficient version doing fixed left shift by BITS_PER_CHAR
  inline void do_left_shift(size_t shift)
  {
    // inspired by STL bitset implementation
    // TODO: replace by std::div
    const size_t word_shift = shift / (sizeof(word_type)*8);
    const size_t offset = shift % (sizeof(word_type)*8);

    if (offset == 0)
    {
      // no bit shifting, just shift words around
      for (size_t i = nWords - 1; i >= word_shift; --i)
      {
        data[i] = data[i - word_shift];
      }
    }
    else
    {
      const size_t inv_offset = sizeof(word_type)*8 - offset;
      for (size_t i = nWords - 1; i > word_shift; --i)
      {
        data[i] = ((data[i - word_shift] << offset) | (data[i - word_shift - 1] >> inv_offset));
      }
      data[word_shift] = data[0] << offset;
    }
    // set all others to 0
    std::fill(data, data+word_shift, static_cast<word_type>(0));
  }

  // TODO template specialization for nWords = 1 (just use base type shift)
  // TODO implement more efficient version doing fixed left shift by BITS_PER_CHAR
  inline void do_right_shift(size_t shift)
  {
    // inspired by STL bitset implementation
    // TODO replace by std::div
    const size_t word_shift = shift / (sizeof(word_type)*8);
    const size_t offset = shift % (sizeof(word_type)*8);

    if (offset == 0)
    {
      // no bit shifting, just shift words around
      for (size_t i = 0; i < nWords - word_shift; ++i)
      {
        data[i] = data[i + word_shift];
      }
    }
    else
    {
      const size_t inv_offset = sizeof(word_type)*8 - offset;
      for (size_t i = 0; i < nWords - word_shift - 1; ++i)
      {
        data[i] = ((data[i + word_shift] >> offset) | (data[i + word_shift + 1] << inv_offset));
      }
      data[nWords - word_shift - 1] = data[nWords-1] >> offset;
    }
    // set all others to 0
    std::fill(data + (nWords - word_shift), data + nWords, static_cast<word_type>(0));
  }

  template <typename InputIterator>
  Kmer& fillFromPaddedStream(InputIterator begin)
  {
    // remove padding copy to own data structure
    // TODO somehow save current offset for nextKmerFromPaddedStream() ?
    typedef typename std::iterator_traits<InputIterator>::value_type input_word_type;
    const unsigned int paddingBits = PaddingTraits<input_word_type, bitsPerChar>::padding_bits;
    removePadding(begin, data, size*bitsPerChar, paddingBits);
    // set unused bits to 0
    do_sanitize();

    return (*this);
  }

  template <typename InputIterator>
  Kmer& nextKmerFromPaddedStream(InputIterator& begin, unsigned int& offset)
  {
    typedef typename std::iterator_traits<InputIterator>::value_type input_word_type;
    // 1.) right shift this kmer by BITS_PER_CHAR
    do_right_shift(bitsPerChar);

    // iterate to next word if the current one is done
    while (offset >= PaddingTraits<input_word_type, bitsPerChar>::data_bits)
    {
      ++begin;
      offset -= PaddingTraits<input_word_type, bitsPerChar>::data_bits;
    }

    typedef typename std::conditional<sizeof(input_word_type) < sizeof(word_type), word_type, input_word_type>::type bigger_word_type;

    bigger_word_type curWord = static_cast<bigger_word_type>(*begin);
    int shift_by = offset - lastCharWordOffset;
    if (shift_by > 0)
    {
      data[nWords - 1 - lastCharIsSplit] = static_cast<word_type>(curWord >> shift_by);
    }
    else
    {
      data[nWords - 1 - lastCharIsSplit] |= static_cast<word_type>(curWord << -shift_by);
    }
    // NOTE: this branch is removed by the compiler
    if (lastCharIsSplit)
    {
      data[nWords - 1] = static_cast<word_type>(curWord >> (offset + (bitsPerChar - leftSplitSize)));
    }
    // set unused bits to 0
    do_sanitize();

    // increase offset
    offset += bitsPerChar;

    return (*this);
  }

  bool operator==(const Kmer& rhs) const
  {
    return std::equal(data, data+nWords, rhs.data);
  }

  bool operator!=(const Kmer& rhs) const
  {
    return !(this->operator==(rhs));
  }

};

} // namespace bliss

#endif // BLISS_COMMON_KMER_H<commit_msg>fixing issue #1<commit_after>/**
 * @file    Kmer.hpp
 * @ingroup common
 * @author  Patrick Flick
 * @brief   Implements the Kmer class.
 *
 * Copyright (c) TODO
 *
 * TODO add Licence
 */
#ifndef BLISS_COMMON_KMER_H
#define BLISS_COMMON_KMER_H

// C std lib includes:
#include <cstdlib>

// C++ STL includes:
#include <iterator>
#include <type_traits>

// own includes
#include <common/base_types.hpp>
#include <common/bit_ops.hpp>
#include <common/padding.hpp>

namespace bliss
{

template <unsigned int KMER_SIZE, unsigned int BITS_PER_CHAR, typename word_type=WordType>
class Kmer
{
  static constexpr unsigned int size = KMER_SIZE;
  static constexpr unsigned int bitsPerChar = BITS_PER_CHAR;
  static constexpr unsigned int nBits = size * bitsPerChar;
  static constexpr unsigned int nBytes = intCeil<unsigned int>(nBits, 8);
  static constexpr unsigned int nWords = intCeil<unsigned int>(nBytes, sizeof(word_type));
  // padding internal to Kmer (only in last storage word)
  static constexpr unsigned int padBits = nWords*sizeof(word_type)*8 - nBits;
  static constexpr unsigned int invPadBits = sizeof(word_type)*8 - padBits;
  static constexpr unsigned int padBytes = nWords*sizeof(word_type) - nBytes;

  // last character offsets (and whether or not it is split accord storage words)
  static constexpr unsigned int lastCharOffset = nBits - bitsPerChar;
  static constexpr bool lastCharIsSplit = (lastCharOffset < (nWords-1)*sizeof(word_type)*8);
  static constexpr unsigned int lastCharWordOffset = lastCharOffset % (sizeof(word_type)*8);
  static constexpr unsigned int leftSplitSize = sizeof(word_type)*8 - lastCharWordOffset;

  // storage:
  word_type data[nWords];

public:

  Kmer()
  {
    // make this a valid Kmer
    do_sanitize();
  }

  template<typename InputIterator>
  Kmer(InputIterator begin)
  {
    static_assert(std::is_same<typename std::iterator_traits<InputIterator>::value_type, word_type>::value, "Input iterator must have same value type as the Kmer storage");
    word_type* out = data;
    for (unsigned int i = 0; i < nWords; ++i)
    {
      *(out++) = *(begin++);
    }
    do_sanitize();
  }

  inline void do_sanitize()
  {
    // TODO use templated helper struct for <0> template specialization
    data[nWords-1] &= getBitMask<word_type>(invPadBits);
  }

  // TODO template specialization for nWords = 1 (just use base type shift)
  // TODO implement more efficient version doing fixed left shift by BITS_PER_CHAR
  inline void do_left_shift(size_t shift)
  {
    // inspired by STL bitset implementation
    // TODO: replace by std::div
    const size_t word_shift = shift / (sizeof(word_type)*8);
    const size_t offset = shift % (sizeof(word_type)*8);

    if (offset == 0)
    {
      // no bit shifting, just shift words around
      for (size_t i = nWords - 1; i >= word_shift; --i)
      {
        data[i] = data[i - word_shift];
      }
    }
    else
    {
      const size_t inv_offset = sizeof(word_type)*8 - offset;
      for (size_t i = nWords - 1; i > word_shift; --i)
      {
        data[i] = ((data[i - word_shift] << offset) | (data[i - word_shift - 1] >> inv_offset));
      }
      data[word_shift] = data[0] << offset;
    }
    // set all others to 0
    std::fill(data, data+word_shift, static_cast<word_type>(0));
  }

  // TODO template specialization for nWords = 1 (just use base type shift)
  // TODO implement more efficient version doing fixed left shift by BITS_PER_CHAR
  inline void do_right_shift(size_t shift)
  {
    // inspired by STL bitset implementation
    // TODO replace by std::div
    const size_t word_shift = shift / (sizeof(word_type)*8);
    const size_t offset = shift % (sizeof(word_type)*8);

    if (offset == 0)
    {
      // no bit shifting, just shift words around
      for (size_t i = 0; i < nWords - word_shift; ++i)
      {
        data[i] = data[i + word_shift];
      }
    }
    else
    {
      const size_t inv_offset = sizeof(word_type)*8 - offset;
      for (size_t i = 0; i < nWords - word_shift - 1; ++i)
      {
        data[i] = ((data[i + word_shift] >> offset) | (data[i + word_shift + 1] << inv_offset));
      }
      data[nWords - word_shift - 1] = data[nWords-1] >> offset;
    }
    // set all others to 0
    std::fill(data + (nWords - word_shift), data + nWords, static_cast<word_type>(0));
  }

  template <typename InputIterator>
  Kmer& fillFromPaddedStream(InputIterator begin)
  {
    // remove padding copy to own data structure
    // TODO somehow save current offset for nextKmerFromPaddedStream() ?
    typedef typename std::iterator_traits<InputIterator>::value_type input_word_type;
    const unsigned int paddingBits = PaddingTraits<input_word_type, bitsPerChar>::padding_bits;
    removePadding(begin, data, size*bitsPerChar, paddingBits);
    // set unused bits to 0
    do_sanitize();

    return (*this);
  }

  template <typename InputIterator>
  Kmer& nextKmerFromPaddedStream(InputIterator& begin, unsigned int& offset)
  {
    typedef typename std::iterator_traits<InputIterator>::value_type input_word_type;
    // 1.) right shift this kmer by BITS_PER_CHAR
    do_right_shift(bitsPerChar);

    // iterate to next word if the current one is done
    while (offset >= PaddingTraits<input_word_type, bitsPerChar>::data_bits)
    {
      ++begin;
      offset -= PaddingTraits<input_word_type, bitsPerChar>::data_bits;
    }

    typedef typename std::conditional<sizeof(input_word_type) < sizeof(word_type), word_type, input_word_type>::type bigger_word_type;

    bigger_word_type curWord = static_cast<bigger_word_type>(*begin);
    int shift_by = offset - lastCharWordOffset;
    if (shift_by > 0)
    {
      data[nWords - 1 - lastCharIsSplit] = static_cast<word_type>(curWord >> shift_by);
    }
    else
    {
      data[nWords - 1 - lastCharIsSplit] |= static_cast<word_type>(curWord << -shift_by);
    }
    // NOTE: this branch is removed by the compiler (result known at compile time)
    if (lastCharIsSplit)
    {
      data[nWords - 1] = static_cast<word_type>(curWord >> (offset + leftSplitSize));
    }
    // set unused bits to 0
    do_sanitize();

    // increase offset
    offset += bitsPerChar;

    return (*this);
  }

  bool operator==(const Kmer& rhs) const
  {
    return std::equal(data, data+nWords, rhs.data);
  }

  bool operator!=(const Kmer& rhs) const
  {
    return !(this->operator==(rhs));
  }

};

} // namespace bliss

#endif // BLISS_COMMON_KMER_H<|endoftext|>