<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: sunjre.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_jvmfwk.hxx"

#include "osl/thread.h"
#include "sunjre.hxx"
#include "sunversion.hxx"
#include "diagnostics.h"

using namespace rtl;
using namespace std;

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
namespace jfw_plugin
{

Reference<VendorBase> SunInfo::createInstance()
{
    return new SunInfo;
}

char const* const* SunInfo::getJavaExePaths(int * size)
{
    static char const * ar[] = {
#if defined(WNT) || defined(OS2)
        "java.exe",
        "bin/java.exe",
        "jre/bin/java.exe"
#elif UNX
        "java",
        "bin/java",
        "jre/bin/java"
#endif
    };
        *size = sizeof (ar) / sizeof (char*);
    return ar;
}

char const* const* SunInfo::getRuntimePaths(int * size)
{
    static char const* ar[]= {
#if defined(WNT) || defined(OS2)
        "/bin/client/jvm.dll",
        "/bin/hotspot/jvm.dll",
        "/bin/classic/jvm.dll"
#elif UNX
        "/lib/" JFW_PLUGIN_ARCH "/client/libjvm.so",
        "/lib/" JFW_PLUGIN_ARCH "/server/libjvm.so",
        "/lib/" JFW_PLUGIN_ARCH "/classic/libjvm.so"
#endif

    };
    *size = sizeof(ar) / sizeof (char*);
    return ar;
}

char const* const* SunInfo::getLibraryPaths(int* size)
{
#ifdef UNX
    static char const * ar[] = {

        "/lib/" JFW_PLUGIN_ARCH "/client",
        "/lib/" JFW_PLUGIN_ARCH "/native_threads",
        "/lib/" JFW_PLUGIN_ARCH

    };
    *size = sizeof(ar) / sizeof (char*);
    return ar;
#else
    size = 0;
    return NULL;
#endif
}

int SunInfo::compareVersions(const rtl::OUString& sSecond) const
{
    OUString sFirst = getVersion();

    SunVersion version1(sFirst);
    JFW_ENSURE(version1, OUSTR("[Java framework] sunjavaplugin"SAL_DLLEXTENSION
                               " does not know the version: ")
               + sFirst + OUSTR(" as valid for a SUN JRE."));
    SunVersion version2(sSecond);
    if ( ! version2)
        throw MalformedVersionException();

    if(version1 == version2)
        return 0;
    if(version1 > version2)
        return 1;
    else
        return -1;
}

}
<commit_msg>INTEGRATION: CWS os2port03 (1.8.18); FILE MERGED 2008/07/16 12:25:32 obr 1.8.18.2: RESYNC: (1.8-1.9); FILE MERGED 2008/01/14 16:56:58 ydario 1.8.18.1: os2 needs different order for dll. Issue number:i85203 Submitted by:ydario<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: sunjre.cxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_jvmfwk.hxx"

#include "osl/thread.h"
#include "sunjre.hxx"
#include "sunversion.hxx"
#include "diagnostics.h"

using namespace rtl;
using namespace std;

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
namespace jfw_plugin
{

Reference<VendorBase> SunInfo::createInstance()
{
    return new SunInfo;
}

char const* const* SunInfo::getJavaExePaths(int * size)
{
    static char const * ar[] = {
#if defined(WNT) || defined(OS2)
        "java.exe",
        "bin/java.exe",
        "jre/bin/java.exe"
#elif UNX
        "java",
        "bin/java",
        "jre/bin/java"
#endif
    };
        *size = sizeof (ar) / sizeof (char*);
    return ar;
}

char const* const* SunInfo::getRuntimePaths(int * size)
{
    static char const* ar[]= {
#if defined(WNT)
        "/bin/client/jvm.dll",
        "/bin/hotspot/jvm.dll",
        "/bin/classic/jvm.dll"
#elif defined(OS2)
        "/bin/classic/jvm.dll",
        "/bin/client/jvm.dll",
        "/bin/hotspot/jvm.dll"
#elif UNX
        "/lib/" JFW_PLUGIN_ARCH "/client/libjvm.so",
        "/lib/" JFW_PLUGIN_ARCH "/server/libjvm.so",
        "/lib/" JFW_PLUGIN_ARCH "/classic/libjvm.so"
#endif

    };
    *size = sizeof(ar) / sizeof (char*);
    return ar;
}

char const* const* SunInfo::getLibraryPaths(int* size)
{
#ifdef UNX
    static char const * ar[] = {

        "/lib/" JFW_PLUGIN_ARCH "/client",
        "/lib/" JFW_PLUGIN_ARCH "/native_threads",
        "/lib/" JFW_PLUGIN_ARCH

    };
    *size = sizeof(ar) / sizeof (char*);
    return ar;
#else
    size = 0;
    return NULL;
#endif
}

int SunInfo::compareVersions(const rtl::OUString& sSecond) const
{
    OUString sFirst = getVersion();

    SunVersion version1(sFirst);
    JFW_ENSURE(version1, OUSTR("[Java framework] sunjavaplugin"SAL_DLLEXTENSION
                               " does not know the version: ")
               + sFirst + OUSTR(" as valid for a SUN JRE."));
    SunVersion version2(sSecond);
    if ( ! version2)
        throw MalformedVersionException();

    if(version1 == version2)
        return 0;
    if(version1 > version2)
        return 1;
    else
        return -1;
}

}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2013 - 2017)
//   Rene Milk       (2014, 2016 - 2017)
//   Tobias Leibner  (2014, 2016)

#ifndef DUNE_GDT_PROLONGATIONS_HH
#define DUNE_GDT_PROLONGATIONS_HH

#include <vector>

#include <dune/common/dynvector.hh>

#include <dune/xt/functions/reinterpret.hh>
#include <dune/xt/la/container/vector-interface.hh>

#include <dune/gdt/discretefunction/bochner.hh>
#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/discretefunction/reinterpret.hh>
#include <dune/gdt/interpolations.hh>
#include <dune/gdt/spaces/bochner.hh>
#include <dune/gdt/spaces/interface.hh>

namespace Dune {
namespace GDT {

// ## Variants for a DiscreteFunction ##

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [most general
 *        variant].
 *
 * \note This does not clear target.dofs().vector(). Thus, if prolongation_grid_view only covers a part of the domain of
 *       target.space().grid_view(), other contributions in target remain (which is on purpose).
 *
 * \sa interpolate
 * \sa reinterpret
 */
template <class SV, class SGV, size_t r, size_t rC, class SR, class TV, class TGV, class TR, class PGV>
std::enable_if_t<std::is_same<XT::Grid::extract_entity_t<TGV>, typename PGV::Grid::template Codim<0>::Entity>::value,
                 void>
prolong(const DiscreteFunction<SV, SGV, r, rC, SR>& source,
        DiscreteFunction<TV, TGV, r, rC, TR>& target,
        const GridView<PGV>& prolongation_grid_view)
{
  interpolate(reinterpret(source, prolongation_grid_view), target, prolongation_grid_view);
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [uses
 *        target.space().grid_view() as prolongation_grid_view].
 */
template <class SV, class SGV, size_t r, size_t rC, class SR, class TV, class TGV, class TR>
void prolong(const DiscreteFunction<SV, SGV, r, rC, SR>& source, DiscreteFunction<TV, TGV, r, rC, TR>& target)
{
  prolong(source, target, target.space().grid_view());
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [creates
 *        suitable target_function, TargetVectorType has to be provided].
 *
 * Use as in
\code
auto target_function = prolong<TargetVectorType>(source, target_space, prolongation_grid_view);
\endcode
 */
template <class TargetVectorType, class SV, class SGV, size_t r, size_t rC, class SR, class TGV, class TR, class PGV>
std::enable_if_t<XT::LA::is_vector<TargetVectorType>::value
                     && std::is_same<XT::Grid::extract_entity_t<TGV>,
                                     typename PGV::Grid::template Codim<0>::Entity>::value,
                 DiscreteFunction<TargetVectorType, TGV, r, rC, TR>>
prolong(const DiscreteFunction<SV, SGV, r, rC, SR>& source,
        const SpaceInterface<TGV, r, rC, TR>& target_space,
        const GridView<PGV>& prolongation_grid_view)
{
  auto target_function = make_discrete_function<TargetVectorType>(target_space);
  prolong(source, target_function, prolongation_grid_view);
  return target_function;
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [creates
 *        suitable target_function, TargetVectorType has to be provided, uses target.space().grid_view() as
 *        prolongation_grid_view].
 *
 * Use as in
\code
auto target_function = prolong<TargetVectorType>(source, target_space);
\endcode
 */
template <class TargetVectorType, class SV, class SGV, size_t r, size_t rC, class SR, class TGV, class TR>
std::enable_if_t<XT::LA::is_vector<TargetVectorType>::value, DiscreteFunction<TargetVectorType, TGV, r, rC, TR>>
prolong(const DiscreteFunction<SV, SGV, r, rC, SR>& source, const SpaceInterface<TGV, r, rC, TR>& target_space)
{
  auto target_function = make_discrete_function<TargetVectorType>(target_space);
  prolong(source, target_function);
  return target_function;
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [creates
 *        suitable target_function with same VectorType as source].
 */
template <class V, class SGV, size_t r, size_t rC, class SR, class TGV, class TR, class PGV>
std::enable_if_t<std::is_same<XT::Grid::extract_entity_t<TGV>, typename PGV::Grid::template Codim<0>::Entity>::value,
                 DiscreteFunction<V, TGV, r, rC, TR>>
prolong(const DiscreteFunction<V, SGV, r, rC, SR>& source,
        const SpaceInterface<TGV, r, rC, TR>& target_space,
        const GridView<PGV>& prolongation_grid_view)
{
  auto target_function = make_discrete_function<V>(target_space);
  prolong(source, target_function, prolongation_grid_view);
  return target_function;
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [creates
 *        suitable target_function with same VectorType as source, uses target.space().grid_view() as
 *        prolongation_grid_view].
 */
template <class V, class SGV, size_t r, size_t rC, class SR, class TGV, class TR>
DiscreteFunction<V, TGV, r, rC, TR> prolong(const DiscreteFunction<V, SGV, r, rC, SR>& source,
                                            const SpaceInterface<TGV, r, rC, TR>& target_space)
{
  auto target_function = make_discrete_function<V>(target_space);
  prolong(source, target_function);
  return target_function;
}

// ## Variants for a DiscreteBochnerFunction ##

/**
 * \brief Prolongs a DiscreteBochnerFunction from one (usually coarser) time grid onto another (usually finer) one [most
 *        general variant].
 *
 * \note Uses prolong() in space.
 *
 * \sa prolong
 * \sa interpolate
 * \sa reinterpret
 */
template <class SV, class SGV, class TV, class TGV, class PGV>
void prolong(const DiscreteBochnerFunction<SV, SGV>& source,
             DiscreteBochnerFunction<TV, TGV>& target,
             const GridView<PGV>& spatial_prolongation_grid_view)
{
  // prepare
  target.dof_vectors().set_all(0.);
  const auto& temporal_space = target.space().temporal_space();
  DynamicVector<size_t> local_dof_indices(temporal_space.mapper().max_local_size());
  std::vector<bool> dof_has_been_handled(temporal_space.mapper().size(), false);
  // walk the time intervals
  for (auto&& time_interval : elements(temporal_space.grid_view())) {
    temporal_space.mapper().global_indices(time_interval, local_dof_indices);
    const auto& lagrange_points_in_time =
        temporal_space.finite_element(time_interval.geometry().type()).lagrange_points();
    for (size_t ii = 0; ii < lagrange_points_in_time.size(); ++ii) {
      const size_t global_dof_index = local_dof_indices[ii];
      if (!dof_has_been_handled[global_dof_index]) {
        const auto& point_in_time = time_interval.geometry().global(lagrange_points_in_time[ii]);
        // evaluate in time
        const auto coarse_spatial_function =
            make_discrete_function(source.space().spatial_space(), source.evaluate(point_in_time));
        // prolong in space
        auto fine_spatial_function =
            make_discrete_function(target.space().spatial_space(), target.dof_vectors()[global_dof_index]);
        prolong(coarse_spatial_function, fine_spatial_function, spatial_prolongation_grid_view);
        dof_has_been_handled[global_dof_index] = true;
      }
    }
  }
} // ... prolong(...)

/**
 * \brief Prolongs a DiscreteBochnerFunction from one (usually coarser) time grid onto another (usually finer) one [uses
 *        target.space().spatial_space().grid_view() as spatial_prolongation_grid_view].
 *
 * \note Uses prolong() in space.
 *
 * \sa prolong
 * \sa interpolate
 * \sa reinterpret
 */
template <class SV, class SGV, class TV, class TGV>
void prolong(const DiscreteBochnerFunction<SV, SGV>& source, DiscreteBochnerFunction<TV, TGV>& target)
{
  prolong(source, target, target.space().spatial_space().grid_view());
}

/**
 * \brief Prolongs a DiscreteBochnerFunction from one (usually coarser) time grid onto another (usually finer) one
 *        [creates suitable target_function, TargetVectorType has to be provided].
 *
 * Use as in
\code
auto target_function = prolong<TargetVectorType>(source, target_space, spatial_prolongation_grid_view);
\endcode
 */
template <class TargetVectorType, class SV, class SGV, class TGV, size_t r, size_t rC, class R, class PGV>
std::enable_if_t<XT::LA::is_vector<TargetVectorType>::value
                     && std::is_same<XT::Grid::extract_entity_t<TGV>,
                                     typename PGV::Grid::template Codim<0>::Entity>::value,
                 DiscreteBochnerFunction<TargetVectorType, TGV, r, rC, R>>
prolong(const DiscreteBochnerFunction<SV, SGV>& source,
        const BochnerSpace<TGV, r, rC, R>& target_space,
        const GridView<PGV>& spatial_prolongation_grid_view)
{
  auto target_function = make_discrete_bochner_function<TargetVectorType>(target_space);
  prolong(source, target_function, spatial_prolongation_grid_view);
  return target_function;
}

template <class TargetVectorType, class SV, class SGV, class TGV, size_t r, size_t rC, class R>
std::enable_if_t<XT::LA::is_vector<TargetVectorType>::value, DiscreteBochnerFunction<TargetVectorType, TGV, r, rC, R>>
prolong(const DiscreteBochnerFunction<SV, SGV>& source, const BochnerSpace<TGV, r, rC, R>& target_space)
{
  return prolong<TargetVectorType>(source, target_space, target_space.spatial_space().grid_view());
}

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PROLONGATIONS_HH
<commit_msg>[prolongations] some improvements<commit_after>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2013 - 2017)
//   Rene Milk       (2014, 2016 - 2017)
//   Tobias Leibner  (2014, 2016)

#ifndef DUNE_GDT_PROLONGATIONS_HH
#define DUNE_GDT_PROLONGATIONS_HH

#include <vector>

#include <dune/common/dynvector.hh>

#include <dune/xt/la/container/vector-interface.hh>

#include <dune/gdt/discretefunction/bochner.hh>
#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/discretefunction/reinterpret.hh>
#include <dune/gdt/interpolations.hh>
#include <dune/gdt/spaces/bochner.hh>
#include <dune/gdt/spaces/interface.hh>

namespace Dune {
namespace GDT {

// ## Variants for a DiscreteFunction ##

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [most general
 *        variant].
 *
 * \note This does not clear target.dofs().vector(). Thus, if prolongation_grid_view only covers a part of the domain of
 *       target.space().grid_view(), other contributions in target remain (which is on purpose).
 *
 * \sa interpolate
 * \sa reinterpret
 */
template <class SV, class SGV, size_t r, size_t rC, class SR, class TV, class TGV, class TR, class PGV>
std::enable_if_t<std::is_same<XT::Grid::extract_entity_t<TGV>, typename PGV::Grid::template Codim<0>::Entity>::value,
                 void>
prolong(const DiscreteFunction<SV, SGV, r, rC, SR>& source,
        DiscreteFunction<TV, TGV, r, rC, TR>& target,
        const GridView<PGV>& prolongation_grid_view)
{
  interpolate(reinterpret(source, prolongation_grid_view), target, prolongation_grid_view);
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [uses
 *        target.space().grid_view() as prolongation_grid_view].
 */
template <class SV, class SGV, size_t r, size_t rC, class SR, class TV, class TGV, class TR>
void prolong(const DiscreteFunction<SV, SGV, r, rC, SR>& source, DiscreteFunction<TV, TGV, r, rC, TR>& target)
{
  prolong(source, target, target.space().grid_view());
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [creates
 *        suitable target_function, TargetVectorType has to be provided].
 *
 * Use as in
\code
auto target_function = prolong<TargetVectorType>(source, target_space, prolongation_grid_view);
\endcode
 */
template <class TargetVectorType, class SV, class SGV, size_t r, size_t rC, class SR, class TGV, class TR, class PGV>
std::enable_if_t<XT::LA::is_vector<TargetVectorType>::value
                     && std::is_same<XT::Grid::extract_entity_t<TGV>,
                                     typename PGV::Grid::template Codim<0>::Entity>::value,
                 DiscreteFunction<TargetVectorType, TGV, r, rC, TR>>
prolong(const DiscreteFunction<SV, SGV, r, rC, SR>& source,
        const SpaceInterface<TGV, r, rC, TR>& target_space,
        const GridView<PGV>& prolongation_grid_view)
{
  auto target_function = make_discrete_function<TargetVectorType>(target_space);
  prolong(source, target_function, prolongation_grid_view);
  return target_function;
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [creates
 *        suitable target_function, TargetVectorType has to be provided, uses target.space().grid_view() as
 *        prolongation_grid_view].
 *
 * Use as in
\code
auto target_function = prolong<TargetVectorType>(source, target_space);
\endcode
 */
template <class TargetVectorType, class SV, class SGV, size_t r, size_t rC, class SR, class TGV, class TR>
std::enable_if_t<XT::LA::is_vector<TargetVectorType>::value, DiscreteFunction<TargetVectorType, TGV, r, rC, TR>>
prolong(const DiscreteFunction<SV, SGV, r, rC, SR>& source, const SpaceInterface<TGV, r, rC, TR>& target_space)
{
  auto target_function = make_discrete_function<TargetVectorType>(target_space);
  prolong(source, target_function);
  return target_function;
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [creates
 *        suitable target_function with same VectorType as source].
 */
template <class V, class SGV, size_t r, size_t rC, class SR, class TGV, class TR, class PGV>
std::enable_if_t<std::is_same<XT::Grid::extract_entity_t<TGV>, typename PGV::Grid::template Codim<0>::Entity>::value,
                 DiscreteFunction<V, TGV, r, rC, TR>>
prolong(const DiscreteFunction<V, SGV, r, rC, SR>& source,
        const SpaceInterface<TGV, r, rC, TR>& target_space,
        const GridView<PGV>& prolongation_grid_view)
{
  auto target_function = make_discrete_function<V>(target_space);
  prolong(source, target_function, prolongation_grid_view);
  return target_function;
}

/**
 * \brief Prolongs a DiscreteFunction from one (usually coarser) GridView onto another (usually finer) one [creates
 *        suitable target_function with same VectorType as source, uses target.space().grid_view() as
 *        prolongation_grid_view].
 */
template <class V, class SGV, size_t r, size_t rC, class SR, class TGV, class TR>
DiscreteFunction<V, TGV, r, rC, TR> prolong(const DiscreteFunction<V, SGV, r, rC, SR>& source,
                                            const SpaceInterface<TGV, r, rC, TR>& target_space)
{
  auto target_function = make_discrete_function<V>(target_space);
  prolong(source, target_function);
  return target_function;
}

// ## Variants for a DiscreteBochnerFunction ##

/**
 * \brief Prolongs a DiscreteBochnerFunction from one (usually coarser) time grid onto another (usually finer) one [most
 *        general variant].
 *
 * \note Uses prolong() in space.
 *
 * \sa prolong
 * \sa interpolate
 * \sa reinterpret
 */
template <class SV, class SGV, size_t r, size_t rC, class R, class TV, class TGV, class PGV>
void prolong(const DiscreteBochnerFunction<SV, SGV, r, rC, R>& source,
             DiscreteBochnerFunction<TV, TGV, r, rC, R>& target,
             const GridView<PGV>& spatial_prolongation_grid_view)
{
  // prepare
  const auto& temporal_space = target.space().temporal_space();
  DynamicVector<size_t> local_dof_indices(temporal_space.mapper().max_local_size());
  std::vector<bool> dof_has_been_handled(temporal_space.mapper().size(), false);
  // walk the time intervals
  for (auto&& time_interval : elements(temporal_space.grid_view())) {
    temporal_space.mapper().global_indices(time_interval, local_dof_indices);
    const auto& lagrange_points_in_time =
        temporal_space.finite_element(time_interval.geometry().type()).lagrange_points();
    for (size_t ii = 0; ii < lagrange_points_in_time.size(); ++ii) {
      const size_t global_dof_index = local_dof_indices[ii];
      if (!dof_has_been_handled[global_dof_index]) {
        const auto& point_in_time = time_interval.geometry().global(lagrange_points_in_time[ii]);
        // evaluate in time
        const auto coarse_spatial_function =
            make_discrete_function(source.space().spatial_space(), source.evaluate(point_in_time));
        // prolong in space
        auto fine_spatial_function =
            make_discrete_function(target.space().spatial_space(), target.dof_vectors()[global_dof_index].vector());
        prolong(coarse_spatial_function, fine_spatial_function, spatial_prolongation_grid_view);
        dof_has_been_handled[global_dof_index] = true;
      }
    }
  }
} // ... prolong(...)

/**
 * \brief Prolongs a DiscreteBochnerFunction from one (usually coarser) time grid onto another (usually finer) one [uses
 *        target.space().spatial_space().grid_view() as spatial_prolongation_grid_view].
 *
 * \note Uses prolong() in space.
 *
 * \sa prolong
 * \sa interpolate
 * \sa reinterpret
 */
template <class SV, class SGV, size_t r, size_t rC, class R, class TV, class TGV>
void prolong(const DiscreteBochnerFunction<SV, SGV, r, rC, R>& source,
             DiscreteBochnerFunction<TV, TGV, r, rC, R>& target)
{
  prolong(source, target, target.space().spatial_space().grid_view());
}

/**
 * \brief Prolongs a DiscreteBochnerFunction from one (usually coarser) time grid onto another (usually finer) one
 *        [creates suitable target_function, TargetVectorType has to be provided].
 *
 * Use as in
\code
auto target_function = prolong<TargetVectorType>(source, target_space, spatial_prolongation_grid_view);
\endcode
 */
template <class TargetVectorType, class SV, class SGV, size_t r, size_t rC, class R, class TGV, class PGV>
std::enable_if_t<XT::LA::is_vector<TargetVectorType>::value
                     && std::is_same<XT::Grid::extract_entity_t<TGV>,
                                     typename PGV::Grid::template Codim<0>::Entity>::value,
                 DiscreteBochnerFunction<TargetVectorType, TGV, r, rC, R>>
prolong(const DiscreteBochnerFunction<SV, SGV, r, rC, R>& source,
        const BochnerSpace<TGV, r, rC, R>& target_space,
        const GridView<PGV>& spatial_prolongation_grid_view)
{
  auto target_function = make_discrete_bochner_function<TargetVectorType>(target_space);
  prolong(source, target_function, spatial_prolongation_grid_view);
  return target_function;
}

template <class TargetVectorType, class SV, class SGV, size_t r, size_t rC, class R, class TGV>
std::enable_if_t<XT::LA::is_vector<TargetVectorType>::value, DiscreteBochnerFunction<TargetVectorType, TGV, r, rC, R>>
prolong(const DiscreteBochnerFunction<SV, SGV, r, rC, R>& source, const BochnerSpace<TGV, r, rC, R>& target_space)
{
  return prolong<TargetVectorType>(source, target_space, target_space.spatial_space().grid_view());
}

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PROLONGATIONS_HH
<|endoftext|>


<commit_before>/*
 * SWE_Sphere_TS_ln_erk.hpp
 *
 *  Created on: 30 May 2017
 *      Author: Martin Schreiber <SchreiberX@gmail.com>
 */

#ifndef SRC_PROGRAMS_SWE_SPHERE_REXI_SWE_SPHERE_TS_LN_ERK_HPP_
#define SRC_PROGRAMS_SWE_SPHERE_REXI_SWE_SPHERE_TS_LN_ERK_HPP_

#include <sweet/sphere/SphereData_Spectral.hpp>
#include <sweet/sphere/SphereOperators_SphereData.hpp>
#include <sweet/sphere/SphereTimestepping_ExplicitRK.hpp>
#include <limits>
#include <sweet/SimulationVariables.hpp>

#include "SWE_Sphere_TS_interface.hpp"

class SWE_Sphere_TS_ln_erk	: public SWE_Sphere_TS_interface
{
public:
	bool implements_timestepping_method(const std::string &i_timestepping_method)
	{
		if (i_timestepping_method == "ln_erk")
			return true;

		return false;
	}

	std::string string_id()
	{
		return "ln_erk";
	}

	void setup_auto()
	{
		setup(simVars.disc.timestepping_order);
	}

private:
	SimulationVariables &simVars;
	SphereOperators_SphereData &op;

	int timestepping_order;

	// Sampler
	SphereTimestepping_ExplicitRK timestepping_rk;

private:
	void euler_timestep_update_pert(
			const SphereData_Spectral &i_phi,	///< prognostic variables
			const SphereData_Spectral &i_vort,	///< prognostic variables
			const SphereData_Spectral &i_div,	///< prognostic variables

			SphereData_Spectral &o_phi_t,	///< time updates
			SphereData_Spectral &o_vort_t,	///< time updates
			SphereData_Spectral &o_div_t,	///< time updates

			double i_simulation_timestamp = -1
	);

public:
	SWE_Sphere_TS_ln_erk(
			SimulationVariables &i_simVars,
			SphereOperators_SphereData &i_op
		);

	void setup(
			int i_order	///< order of RK time stepping method
	);

	void run_timestep(
			SphereData_Spectral &io_phi,	///< prognostic variables
			SphereData_Spectral &io_vort,	///< prognostic variables
			SphereData_Spectral &io_div,	///< prognostic variables

			double i_fixed_dt = 0,
			double i_simulation_timestamp = -1
	);

	virtual ~SWE_Sphere_TS_ln_erk();
};

#endif /* SRC_PROGRAMS_SWE_PLANE_REXI_SWE_PLANE_TS_LN_ERK_HPP_ */
<commit_msg>Make euler_timestep_update_pert Public<commit_after>/*
 * SWE_Sphere_TS_ln_erk.hpp
 *
 *  Created on: 30 May 2017
 *      Author: Martin Schreiber <SchreiberX@gmail.com>
 */

#ifndef SRC_PROGRAMS_SWE_SPHERE_REXI_SWE_SPHERE_TS_LN_ERK_HPP_
#define SRC_PROGRAMS_SWE_SPHERE_REXI_SWE_SPHERE_TS_LN_ERK_HPP_

#include <sweet/sphere/SphereData_Spectral.hpp>
#include <sweet/sphere/SphereOperators_SphereData.hpp>
#include <sweet/sphere/SphereTimestepping_ExplicitRK.hpp>
#include <limits>
#include <sweet/SimulationVariables.hpp>

#include "SWE_Sphere_TS_interface.hpp"

class SWE_Sphere_TS_ln_erk	: public SWE_Sphere_TS_interface
{
public:
	bool implements_timestepping_method(const std::string &i_timestepping_method)
	{
		if (i_timestepping_method == "ln_erk")
			return true;

		return false;
	}

	std::string string_id()
	{
		return "ln_erk";
	}

	void setup_auto()
	{
		setup(simVars.disc.timestepping_order);
	}

private:
	SimulationVariables &simVars;
	SphereOperators_SphereData &op;

	int timestepping_order;

	// Sampler
	SphereTimestepping_ExplicitRK timestepping_rk;

public:
	void euler_timestep_update_pert(
			const SphereData_Spectral &i_phi,	///< prognostic variables
			const SphereData_Spectral &i_vort,	///< prognostic variables
			const SphereData_Spectral &i_div,	///< prognostic variables

			SphereData_Spectral &o_phi_t,	///< time updates
			SphereData_Spectral &o_vort_t,	///< time updates
			SphereData_Spectral &o_div_t,	///< time updates

			double i_simulation_timestamp = -1
	);

public:
	SWE_Sphere_TS_ln_erk(
			SimulationVariables &i_simVars,
			SphereOperators_SphereData &i_op
		);

	void setup(
			int i_order	///< order of RK time stepping method
	);

	void run_timestep(
			SphereData_Spectral &io_phi,	///< prognostic variables
			SphereData_Spectral &io_vort,	///< prognostic variables
			SphereData_Spectral &io_div,	///< prognostic variables

			double i_fixed_dt = 0,
			double i_simulation_timestamp = -1
	);

	virtual ~SWE_Sphere_TS_ln_erk();
};

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


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/python/py_values.h"

#include "pybind11/pybind11.h"
#include "pybind11/pytypes.h"
#include "tensorflow/compiler/xla/primitive_util.h"
#include "tensorflow/compiler/xla/python/py_buffer.h"
#include "tensorflow/compiler/xla/python/python_ref_manager.h"
#include "tensorflow/compiler/xla/python/types.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/core/profiler/lib/traceme.h"
#include "tensorflow/python/lib/core/numpy.h"

namespace py = pybind11;

namespace xla {

namespace {

using DevicePutFunc = std::function<StatusOr<DevicePutResult>(
    py::handle, PjRtDevice*, const DevicePutOptions& options)>;

template <typename T, typename SquashedT>
StatusOr<DevicePutResult> HandlePythonScalar(py::handle obj,
                                             PjRtDevice* to_device,
                                             const DevicePutOptions& options) {
  T data;

  try {
    data = py::cast<T>(obj);
  } catch (const std::exception& e) {
    return InvalidArgument(
        "Unable to convert Python scalar to %s. This most likely means the "
        "value (%s) overflows the range of the type.",
        PrimitiveType_Name(primitive_util::NativeToPrimitiveType<T>()),
        py::repr(obj));
  }

  void* ptr;
  SquashedT squashed_data;
  Shape shape;
  if (std::is_same<T, SquashedT>() || !options.squash_64bit_types) {
    ptr = &data;
    shape = ShapeUtil::MakeShapeWithType<T>({});
  } else {
    // TODO(phawkins): we should check for overflow here, e.g., because of bugs
    // like https://github.com/google/jax/issues/2006
    squashed_data = static_cast<SquashedT>(data);
    ptr = &squashed_data;
    shape = ShapeUtil::MakeShapeWithType<SquashedT>({});
  }
  TF_ASSIGN_OR_RETURN(
      auto buffer,
      to_device->client()->BufferFromHostBuffer(
          ptr, shape, PjRtClient::HostBufferSemantics::kImmutableOnlyDuringCall,
          nullptr, to_device));
  return DevicePutResult(std::move(buffer), /*weak_type=*/true);
}

template <typename T, typename SquashedT = T>
StatusOr<DevicePutResult> HandleNumpyScalar(py::handle h, PjRtDevice* to_device,
                                            const DevicePutOptions& options) {
  T data;
  SquashedT data_squashed;
  void* ptr;
  Shape shape;
  if (std::is_same<T, bfloat16>()) {
    // For extension types, ScalarAsCtype returns a pointer to the data.
    PyArray_ScalarAsCtype(h.ptr(), &ptr);
    shape = ShapeUtil::MakeShape(BF16, {});
  } else if (std::is_same<T, SquashedT>() || !options.squash_64bit_types) {
    PyArray_ScalarAsCtype(h.ptr(), &data);
    ptr = &data;
    shape = ShapeUtil::MakeShapeWithType<T>({});
  } else {
    PyArray_ScalarAsCtype(h.ptr(), &data);
    data_squashed = static_cast<SquashedT>(data);
    ptr = &data_squashed;
    shape = ShapeUtil::MakeShapeWithType<SquashedT>({});
  }
  TF_ASSIGN_OR_RETURN(
      std::unique_ptr<PjRtBuffer> buffer,
      to_device->client()->BufferFromHostBuffer(
          ptr, shape, PjRtClient::HostBufferSemantics::kImmutableOnlyDuringCall,
          nullptr, to_device));
  return DevicePutResult(std::move(buffer), /*weak_type=*/false);
}

StatusOr<DevicePutResult> HandleNumpyArray(py::handle h, PjRtDevice* to_device,
                                           const DevicePutOptions& options) {
  py::array array = py::cast<py::array>(h);
  TF_ASSIGN_OR_RETURN(PrimitiveType type, DtypeToPrimitiveType(array.dtype()));

  PrimitiveType squashed_type;
  if (options.squash_64bit_types) {
    squashed_type = Squash64BitTypes(type);
    if (squashed_type != type) {
      TF_ASSIGN_OR_RETURN(py::dtype squashed_dtype,
                          PrimitiveTypeToDtype(squashed_type));
      array = py::reinterpret_steal<py::array>(PyArray_CastToType(
          reinterpret_cast<PyArrayObject*>(array.ptr()),
          reinterpret_cast<PyArray_Descr*>(squashed_dtype.release().ptr()),
          /*fortran=*/0));
    }
  } else {
    squashed_type = type;
  }
  array = py::array::ensure(
      array, py::array::c_style | py::detail::npy_api::NPY_ARRAY_ALIGNED_);

  absl::InlinedVector<int64, 4> dims(array.ndim());
  for (int i = 0; i < array.ndim(); ++i) {
    dims[i] = array.shape(i);
  }
  Shape shape = ShapeUtil::MakeShape(squashed_type, dims);
  if (array.size() * array.itemsize() != ShapeUtil::ByteSizeOf(shape)) {
    throw std::runtime_error(absl::StrCat(
        "Size mismatch for buffer: ", array.size() * array.itemsize(), " vs. ",
        ShapeUtil::ByteSizeOf(shape)));
  }
  void* data = const_cast<void*>(array.data());
  PjRtClient::HostBufferSemantics host_buffer_semantics =
      PjRtClient::HostBufferSemantics::kImmutableOnlyDuringCall;
  std::function<void()> on_done_with_host_buffer;
  if (options.allow_zero_copy) {
    std::shared_ptr<PythonRefManager::ManagedPyObjects> py_buffer_ref =
        GlobalPyRefManager()->ManageReference(std::move(array));
    on_done_with_host_buffer =
        [py_buffer_ref{
            std::move(py_buffer_ref)}]() { /* keeps py_buffer_ref alive */ };
    host_buffer_semantics = PjRtClient::HostBufferSemantics::kZeroCopy;
  }
  TF_ASSIGN_OR_RETURN(auto buffer,
                      to_device->client()->BufferFromHostBuffer(
                          data, shape, host_buffer_semantics,
                          std::move(on_done_with_host_buffer), to_device));
  return DevicePutResult(std::move(buffer), /*weak_type=*/false);
}

StatusOr<DevicePutResult> PyBufferHelper(py::handle obj, py::handle py_buffer,
                                         PyBuffer* buffer,
                                         PjRtDevice* to_device) {
  bool weak_type = buffer->weak_type()
                       ? *buffer->weak_type()
                       : py::cast<bool>(obj.attr("aval").attr("weak_type"));
  if (buffer->buffer()->device() == to_device) {
    return DevicePutResult(
        buffer->buffer(), weak_type,
        /*owning_pybuffer=*/py::reinterpret_borrow<py::object>(py_buffer));
  } else {
    TF_ASSIGN_OR_RETURN(std::unique_ptr<PjRtBuffer> copied_buffer,
                        buffer->buffer()->CopyToDevice(to_device));
    return DevicePutResult(std::move(copied_buffer), weak_type);
  }
}

StatusOr<DevicePutResult> HandlePyBuffer(py::handle obj, PjRtDevice* to_device,
                                         const DevicePutOptions& options) {
  return PyBufferHelper(obj, obj, py::cast<PyBuffer*>(obj), to_device);
}

StatusOr<DevicePutResult> HandleDeviceArray(py::handle obj,
                                            PjRtDevice* to_device,
                                            const DevicePutOptions& options) {
  // Handle Python DeviceArray objects provided they have a .device_buffer field
  // Otherwise, fallback to handling as a NumPy array, since we do not
  // understand how to get a buffer object out. For example, ShardedDeviceArray
  // in JAX is handled by this path.
  py::object buffer = py::getattr(obj, "device_buffer", py::none());
  if (buffer.is_none()) {
    return HandleNumpyArray(obj, to_device, options);
  }

  // Force buffers with a non-trivial lazy expression.
  py::object forced;
  if (!py::getattr(obj, "_lazy_expr").is_none()) {
    if (!options.force_lazy_arrays) {
      return InvalidArgument("Lazy arrays are not supported by device_put");
    }
    static py::function& force = *[]() {
      const auto xla_module = py::module::import("jax.interpreters.xla");
      return new py::function(
          py::cast<py::function>(xla_module.attr("_force")));
    }();
    forced = force(obj);
    buffer = forced.attr("device_buffer");
    obj = forced;
  }

  return PyBufferHelper(obj, buffer, py::cast<PyBuffer*>(buffer), to_device);
}

}  // namespace

StatusOr<DevicePutResult> DevicePut(pybind11::handle arg, PjRtDevice* to_device,
                                    const DevicePutOptions& options,
                                    PyBuffer* py_buffer) {
  tensorflow::profiler::TraceMe traceme("DevicePut");
  if (py_buffer) {
    return PyBufferHelper(arg, arg, py_buffer, to_device);
  }
  static const absl::flat_hash_map<PyObject*, DevicePutFunc>* const handlers =
      [] {
        auto p = new absl::flat_hash_map<PyObject*, DevicePutFunc>();
        const NumpyScalarTypes& dtypes = GetNumpyScalarTypes();
        // Python scalar types.
        static_assert(sizeof(bool) == 1,
                      "Conversion code assumes bool is 1 byte");
        (*p)[reinterpret_cast<PyObject*>(&PyBool_Type)] =
            HandlePythonScalar<bool, bool>;
        (*p)[reinterpret_cast<PyObject*>(&PyLong_Type)] =
            HandlePythonScalar<int64_t, int32_t>;
        (*p)[reinterpret_cast<PyObject*>(&PyFloat_Type)] =
            HandlePythonScalar<double, float>;
        (*p)[reinterpret_cast<PyObject*>(&PyComplex_Type)] =
            HandlePythonScalar<complex128, complex64>;

        // Generic subclasses of DeviceArray, e.g., ShardedDeviceArray.
        (*p)[py::type::handle_of<DeviceArrayBase>().ptr()] = HandleDeviceArray;
        // The C++ PyBuffer class is handled specially.
        (*p)[py::type::handle_of<PyBuffer>().ptr()] = HandlePyBuffer;

        try {
          py::object xla_module = py::module::import("jax.interpreters.xla");
          py::object device_array =
              py::getattr(xla_module, "_DeviceArray", py::none());
          if (!device_array.is_none()) {
            (*p)[device_array.ptr()] = HandleDeviceArray;
          }
        } catch (const py::error_already_set& e) {
          // Ignore; jax may not be present.
        }

        try {
          py::object pxla_module = py::module::import("jax.interpreters.pxla");
          py::object sda =
              py::getattr(pxla_module, "ShardedDeviceArray", py::none());
          if (!sda.is_none()) {
            (*p)[sda.ptr()] = HandleDeviceArray;
          }
        } catch (const py::error_already_set& e) {
          // Ignore; jax may not be present.
        }

        const auto numpy = py::module::import("numpy");
        (*p)[numpy.attr("ndarray").ptr()] = HandleNumpyArray;

        // Numpy scalar types. For some of them, we share the handler with
        // Python types (np_int64, np_float64, np_complex128).
        (*p)[dtypes.np_bool.ptr()] = HandleNumpyScalar<bool>;
        (*p)[dtypes.np_int8.ptr()] = HandleNumpyScalar<int8_t>;
        (*p)[dtypes.np_int16.ptr()] = HandleNumpyScalar<int16_t>;
        (*p)[dtypes.np_int32.ptr()] = HandleNumpyScalar<int32_t>;
        (*p)[dtypes.np_int64.ptr()] = HandleNumpyScalar<int64_t, int32_t>;
        (*p)[dtypes.np_uint8.ptr()] = HandleNumpyScalar<uint8_t>;
        (*p)[dtypes.np_uint16.ptr()] = HandleNumpyScalar<uint16_t>;
        (*p)[dtypes.np_uint32.ptr()] = HandleNumpyScalar<uint32_t>;
        (*p)[dtypes.np_uint64.ptr()] = HandleNumpyScalar<uint64_t, uint32_t>;
        (*p)[dtypes.np_bfloat16.ptr()] = HandleNumpyScalar<bfloat16>;
        (*p)[dtypes.np_float16.ptr()] = HandleNumpyScalar<half>;
        (*p)[dtypes.np_float32.ptr()] = HandleNumpyScalar<float>;
        (*p)[dtypes.np_float64.ptr()] = HandleNumpyScalar<double, float>;
        (*p)[dtypes.np_complex64.ptr()] = HandleNumpyScalar<complex64>;
        (*p)[dtypes.np_complex128.ptr()] =
            HandleNumpyScalar<complex128, complex64>;
        static_assert(sizeof(long long) == sizeof(int64_t),  // NOLINT
                      "long long must be the same size as int64_t");
        (*p)[dtypes.np_longlong.ptr()] = HandleNumpyScalar<int64_t, int32_t>;
        static_assert(sizeof(int) == sizeof(int32_t),
                      "int must be the same size as int32_t");
        (*p)[dtypes.np_intc.ptr()] = HandleNumpyScalar<int32_t>;

        return p;
      }();

  auto res = handlers->find(arg.get_type().ptr());
  if (res == handlers->end()) {
    for (auto base_class : arg.get_type().attr("mro")()) {
      res = handlers->find(base_class.ptr());
      if (res != handlers->end()) {
        return res->second(arg, to_device, options);
      }
    }
    return InvalidArgument(
        "%s", absl::StrCat(
                  "Not supported: The C++ jax jit execution path, only accepts "
                  "DeviceArray, Numpy arrays scalars of supported types "
                  "(see implementation), or Python scalars. Got type ",
                  py::cast<std::string>(py::str(arg.get_type()))));
  } else {
    return res->second(arg, to_device, options);
  }
}

}  // namespace xla
<commit_msg>Copybara import of the project:<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/python/py_values.h"

#include "pybind11/pybind11.h"
#include "pybind11/pytypes.h"
#include "tensorflow/compiler/xla/primitive_util.h"
#include "tensorflow/compiler/xla/python/py_buffer.h"
#include "tensorflow/compiler/xla/python/python_ref_manager.h"
#include "tensorflow/compiler/xla/python/types.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/core/profiler/lib/traceme.h"
#include "tensorflow/python/lib/core/numpy.h"

namespace py = pybind11;

namespace xla {

namespace {

using DevicePutFunc = std::function<StatusOr<DevicePutResult>(
    py::handle, PjRtDevice*, const DevicePutOptions& options)>;

template <typename T, typename SquashedT>
StatusOr<DevicePutResult> HandlePythonScalar(py::handle obj,
                                             PjRtDevice* to_device,
                                             const DevicePutOptions& options) {
  T data;

  try {
    data = py::cast<T>(obj);
  } catch (const std::exception& e) {
    return InvalidArgument(
        "Unable to convert Python scalar to %s. This most likely means the "
        "value (%s) overflows the range of the type.",
        PrimitiveType_Name(primitive_util::NativeToPrimitiveType<T>()),
        py::repr(obj));
  }

  void* ptr;
  SquashedT squashed_data;
  Shape shape;
  if (std::is_same<T, SquashedT>() || !options.squash_64bit_types) {
    ptr = &data;
    shape = ShapeUtil::MakeShapeWithType<T>({});
  } else {
    // TODO(phawkins): we should check for overflow here, e.g., because of bugs
    // like https://github.com/google/jax/issues/2006
    squashed_data = static_cast<SquashedT>(data);
    ptr = &squashed_data;
    shape = ShapeUtil::MakeShapeWithType<SquashedT>({});
  }
  TF_ASSIGN_OR_RETURN(
      auto buffer,
      to_device->client()->BufferFromHostBuffer(
          ptr, shape, PjRtClient::HostBufferSemantics::kImmutableOnlyDuringCall,
          nullptr, to_device));
  return DevicePutResult(std::move(buffer), /*weak_type=*/true);
}

StatusOr<DevicePutResult> HandlePythonInt(py::handle obj, PjRtDevice* to_device,
                                          const DevicePutOptions& options) {
  void* ptr;
  Shape shape;
  int64 data_int64;
  int32 data_int32;

  if (options.squash_64bit_types) {
    try {
      data_int32 = py::cast<int32>(obj);
    } catch (const std::exception& e) {
      return InvalidArgument(
          "Unable to convert Python scalar to %s. This most likely means the "
          "value (%s) overflows the range of the type.",
          PrimitiveType_Name(primitive_util::NativeToPrimitiveType<int32>()),
          py::repr(obj));
    }
    ptr = &data_int32;
    shape = ShapeUtil::MakeShapeWithType<int32>({});
  } else {
    try {
      data_int64 = py::cast<int64>(obj);
    } catch (const std::exception& e) {
      return InvalidArgument(
          "Unable to convert Python scalar to %s. This most likely means the "
          "value (%s) overflows the range of the type.",
          PrimitiveType_Name(primitive_util::NativeToPrimitiveType<int64>()),
          py::repr(obj));
    }
    ptr = &data_int64;
    shape = ShapeUtil::MakeShapeWithType<int64>({});
  }
  TF_ASSIGN_OR_RETURN(
      auto buffer,
      to_device->client()->BufferFromHostBuffer(
          ptr, shape, PjRtClient::HostBufferSemantics::kImmutableOnlyDuringCall,
          nullptr, to_device));
  return DevicePutResult(std::move(buffer), /*weak_type=*/true);
}

template <typename T, typename SquashedT = T>
StatusOr<DevicePutResult> HandleNumpyScalar(py::handle h, PjRtDevice* to_device,
                                            const DevicePutOptions& options) {
  T data;
  SquashedT data_squashed;
  void* ptr;
  Shape shape;
  if (std::is_same<T, bfloat16>()) {
    // For extension types, ScalarAsCtype returns a pointer to the data.
    PyArray_ScalarAsCtype(h.ptr(), &ptr);
    shape = ShapeUtil::MakeShape(BF16, {});
  } else if (std::is_same<T, SquashedT>() || !options.squash_64bit_types) {
    PyArray_ScalarAsCtype(h.ptr(), &data);
    ptr = &data;
    shape = ShapeUtil::MakeShapeWithType<T>({});
  } else {
    PyArray_ScalarAsCtype(h.ptr(), &data);
    data_squashed = static_cast<SquashedT>(data);
    ptr = &data_squashed;
    shape = ShapeUtil::MakeShapeWithType<SquashedT>({});
  }
  TF_ASSIGN_OR_RETURN(
      std::unique_ptr<PjRtBuffer> buffer,
      to_device->client()->BufferFromHostBuffer(
          ptr, shape, PjRtClient::HostBufferSemantics::kImmutableOnlyDuringCall,
          nullptr, to_device));
  return DevicePutResult(std::move(buffer), /*weak_type=*/false);
}

StatusOr<DevicePutResult> HandleNumpyArray(py::handle h, PjRtDevice* to_device,
                                           const DevicePutOptions& options) {
  py::array array = py::cast<py::array>(h);
  TF_ASSIGN_OR_RETURN(PrimitiveType type, DtypeToPrimitiveType(array.dtype()));

  PrimitiveType squashed_type;
  if (options.squash_64bit_types) {
    squashed_type = Squash64BitTypes(type);
    if (squashed_type != type) {
      TF_ASSIGN_OR_RETURN(py::dtype squashed_dtype,
                          PrimitiveTypeToDtype(squashed_type));
      array = py::reinterpret_steal<py::array>(PyArray_CastToType(
          reinterpret_cast<PyArrayObject*>(array.ptr()),
          reinterpret_cast<PyArray_Descr*>(squashed_dtype.release().ptr()),
          /*fortran=*/0));
    }
  } else {
    squashed_type = type;
  }
  array = py::array::ensure(
      array, py::array::c_style | py::detail::npy_api::NPY_ARRAY_ALIGNED_);

  absl::InlinedVector<int64, 4> dims(array.ndim());
  for (int i = 0; i < array.ndim(); ++i) {
    dims[i] = array.shape(i);
  }
  Shape shape = ShapeUtil::MakeShape(squashed_type, dims);
  if (array.size() * array.itemsize() != ShapeUtil::ByteSizeOf(shape)) {
    throw std::runtime_error(absl::StrCat(
        "Size mismatch for buffer: ", array.size() * array.itemsize(), " vs. ",
        ShapeUtil::ByteSizeOf(shape)));
  }
  void* data = const_cast<void*>(array.data());
  PjRtClient::HostBufferSemantics host_buffer_semantics =
      PjRtClient::HostBufferSemantics::kImmutableOnlyDuringCall;
  std::function<void()> on_done_with_host_buffer;
  if (options.allow_zero_copy) {
    std::shared_ptr<PythonRefManager::ManagedPyObjects> py_buffer_ref =
        GlobalPyRefManager()->ManageReference(std::move(array));
    on_done_with_host_buffer =
        [py_buffer_ref{
            std::move(py_buffer_ref)}]() { /* keeps py_buffer_ref alive */ };
    host_buffer_semantics = PjRtClient::HostBufferSemantics::kZeroCopy;
  }
  TF_ASSIGN_OR_RETURN(auto buffer,
                      to_device->client()->BufferFromHostBuffer(
                          data, shape, host_buffer_semantics,
                          std::move(on_done_with_host_buffer), to_device));
  return DevicePutResult(std::move(buffer), /*weak_type=*/false);
}

StatusOr<DevicePutResult> PyBufferHelper(py::handle obj, py::handle py_buffer,
                                         PyBuffer* buffer,
                                         PjRtDevice* to_device) {
  bool weak_type = buffer->weak_type()
                       ? *buffer->weak_type()
                       : py::cast<bool>(obj.attr("aval").attr("weak_type"));
  if (buffer->buffer()->device() == to_device) {
    return DevicePutResult(
        buffer->buffer(), weak_type,
        /*owning_pybuffer=*/py::reinterpret_borrow<py::object>(py_buffer));
  } else {
    TF_ASSIGN_OR_RETURN(std::unique_ptr<PjRtBuffer> copied_buffer,
                        buffer->buffer()->CopyToDevice(to_device));
    return DevicePutResult(std::move(copied_buffer), weak_type);
  }
}

StatusOr<DevicePutResult> HandlePyBuffer(py::handle obj, PjRtDevice* to_device,
                                         const DevicePutOptions& options) {
  return PyBufferHelper(obj, obj, py::cast<PyBuffer*>(obj), to_device);
}

StatusOr<DevicePutResult> HandleDeviceArray(py::handle obj,
                                            PjRtDevice* to_device,
                                            const DevicePutOptions& options) {
  // Handle Python DeviceArray objects provided they have a .device_buffer field
  // Otherwise, fallback to handling as a NumPy array, since we do not
  // understand how to get a buffer object out. For example, ShardedDeviceArray
  // in JAX is handled by this path.
  py::object buffer = py::getattr(obj, "device_buffer", py::none());
  if (buffer.is_none()) {
    return HandleNumpyArray(obj, to_device, options);
  }

  // Force buffers with a non-trivial lazy expression.
  py::object forced;
  if (!py::getattr(obj, "_lazy_expr").is_none()) {
    if (!options.force_lazy_arrays) {
      return InvalidArgument("Lazy arrays are not supported by device_put");
    }
    static py::function& force = *[]() {
      const auto xla_module = py::module::import("jax.interpreters.xla");
      return new py::function(
          py::cast<py::function>(xla_module.attr("_force")));
    }();
    forced = force(obj);
    buffer = forced.attr("device_buffer");
    obj = forced;
  }

  return PyBufferHelper(obj, buffer, py::cast<PyBuffer*>(buffer), to_device);
}

}  // namespace

StatusOr<DevicePutResult> DevicePut(pybind11::handle arg, PjRtDevice* to_device,
                                    const DevicePutOptions& options,
                                    PyBuffer* py_buffer) {
  tensorflow::profiler::TraceMe traceme("DevicePut");
  if (py_buffer) {
    return PyBufferHelper(arg, arg, py_buffer, to_device);
  }
  static const absl::flat_hash_map<PyObject*, DevicePutFunc>* const handlers =
      [] {
        auto p = new absl::flat_hash_map<PyObject*, DevicePutFunc>();
        const NumpyScalarTypes& dtypes = GetNumpyScalarTypes();
        // Python scalar types.
        static_assert(sizeof(bool) == 1,
                      "Conversion code assumes bool is 1 byte");
        (*p)[reinterpret_cast<PyObject*>(&PyBool_Type)] =
            HandlePythonScalar<bool, bool>;
        (*p)[reinterpret_cast<PyObject*>(&PyLong_Type)] = HandlePythonInt;
        (*p)[reinterpret_cast<PyObject*>(&PyFloat_Type)] =
            HandlePythonScalar<double, float>;
        (*p)[reinterpret_cast<PyObject*>(&PyComplex_Type)] =
            HandlePythonScalar<complex128, complex64>;

        // Generic subclasses of DeviceArray, e.g., ShardedDeviceArray.
        (*p)[py::type::handle_of<DeviceArrayBase>().ptr()] = HandleDeviceArray;
        // The C++ PyBuffer class is handled specially.
        (*p)[py::type::handle_of<PyBuffer>().ptr()] = HandlePyBuffer;

        try {
          py::object xla_module = py::module::import("jax.interpreters.xla");
          py::object device_array =
              py::getattr(xla_module, "_DeviceArray", py::none());
          if (!device_array.is_none()) {
            (*p)[device_array.ptr()] = HandleDeviceArray;
          }
        } catch (const py::error_already_set& e) {
          // Ignore; jax may not be present.
        }

        try {
          py::object pxla_module = py::module::import("jax.interpreters.pxla");
          py::object sda =
              py::getattr(pxla_module, "ShardedDeviceArray", py::none());
          if (!sda.is_none()) {
            (*p)[sda.ptr()] = HandleDeviceArray;
          }
        } catch (const py::error_already_set& e) {
          // Ignore; jax may not be present.
        }

        const auto numpy = py::module::import("numpy");
        (*p)[numpy.attr("ndarray").ptr()] = HandleNumpyArray;

        // Numpy scalar types. For some of them, we share the handler with
        // Python types (np_int64, np_float64, np_complex128).
        (*p)[dtypes.np_bool.ptr()] = HandleNumpyScalar<bool>;
        (*p)[dtypes.np_int8.ptr()] = HandleNumpyScalar<int8_t>;
        (*p)[dtypes.np_int16.ptr()] = HandleNumpyScalar<int16_t>;
        (*p)[dtypes.np_int32.ptr()] = HandleNumpyScalar<int32_t>;
        (*p)[dtypes.np_int64.ptr()] = HandleNumpyScalar<int64_t, int32_t>;
        (*p)[dtypes.np_uint8.ptr()] = HandleNumpyScalar<uint8_t>;
        (*p)[dtypes.np_uint16.ptr()] = HandleNumpyScalar<uint16_t>;
        (*p)[dtypes.np_uint32.ptr()] = HandleNumpyScalar<uint32_t>;
        (*p)[dtypes.np_uint64.ptr()] = HandleNumpyScalar<uint64_t, uint32_t>;
        (*p)[dtypes.np_bfloat16.ptr()] = HandleNumpyScalar<bfloat16>;
        (*p)[dtypes.np_float16.ptr()] = HandleNumpyScalar<half>;
        (*p)[dtypes.np_float32.ptr()] = HandleNumpyScalar<float>;
        (*p)[dtypes.np_float64.ptr()] = HandleNumpyScalar<double, float>;
        (*p)[dtypes.np_complex64.ptr()] = HandleNumpyScalar<complex64>;
        (*p)[dtypes.np_complex128.ptr()] =
            HandleNumpyScalar<complex128, complex64>;
        static_assert(sizeof(long long) == sizeof(int64_t),  // NOLINT
                      "long long must be the same size as int64_t");
        (*p)[dtypes.np_longlong.ptr()] = HandleNumpyScalar<int64_t, int32_t>;
        static_assert(sizeof(int) == sizeof(int32_t),
                      "int must be the same size as int32_t");
        (*p)[dtypes.np_intc.ptr()] = HandleNumpyScalar<int32_t>;

        return p;
      }();

  auto res = handlers->find(arg.get_type().ptr());
  if (res == handlers->end()) {
    for (auto base_class : arg.get_type().attr("mro")()) {
      res = handlers->find(base_class.ptr());
      if (res != handlers->end()) {
        return res->second(arg, to_device, options);
      }
    }
    return InvalidArgument(
        "%s", absl::StrCat(
                  "Not supported: The C++ jax jit execution path, only accepts "
                  "DeviceArray, Numpy arrays scalars of supported types "
                  "(see implementation), or Python scalars. Got type ",
                  py::cast<std::string>(py::str(arg.get_type()))));
  } else {
    return res->second(arg, to_device, options);
  }
}

}  // namespace xla
<|endoftext|>


<commit_before>/**
* Project: dystring
* File: dystring.cpp
* Version: 1.0
* Author: Yusuf Shakeel
* Date: 08 August 2014 Friday
* Language: C++
*
* GitHub repository:
* https://github.com/yusufshakeel/CPP-Project/tree/master/dystring
*
* Author:
* https://www.facebook.com/yusufshakeel
* https://www.youtube.com/yusufshakeel
* https://plus.google.com/+YusufShakeel
* https://www.twitter.com/yusufshakeel
* https://github.com/yusufshakeel
*
* ======================================
* License
* ======================================
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Yusuf Shakeel
*
* 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.
*/

#include "dystring.h"

//----- DYSTRING CLASS FUNCTIONS ----------------------//

//----- PRIVATE FUNCTIONS -----------------------------//
/* memory allocation */
void dystring::__dymalloc(){
	if(dystr!=0)
		delete dystr;
	dystr = new char[dystrlen+1];
}

/* return length of the string s */
long dystring::__dystrlen(const char *s){
	long l = 0;
	while(*(s+l)!='\0')
		l++;
	return l;
}

/* reallocate memory space and retain previous string */
void dystring::__dyrealloc(){
	char *tmp = new char[dystrlen+1];
	long i;
	for(i=0; *(dystr+i)!='\0'; i++){
		*(tmp+i)=*(dystr+i);
	}
	*(tmp+i)='\0';
	delete dystr;
	dystr = tmp;
}

//----- PUBLIC FUNCTIONS ------------------------------//

//----- CONSTRUCTORS ----------------------------------//

//default constructor
dystring::dystring(void){
	dystrlen = 0;
	dystr = new char('\0');
}

//parameterized constructor
dystring::dystring(const char *s){
	copy(s);
}

//----- MEMBER FUNCTIONS ------------------------------//

/* concatenate source to string */
void dystring::concat(const char *source){
	long slen = __dystrlen(source);
	long i = dystrlen;
	dystrlen += slen;
	__dyrealloc();
	for(long j=0; *(source+j)!='\0'; j++,i++){
		*(dystr+i) = *(source+j);
	}
	*(dystr+i)='\0';
}

/* copy source to string */
void dystring::copy(const char *source){
	dystrlen = __dystrlen(source);
	__dymalloc();
	long i;
	for(i=0;*(source+i) != '\0';i++){
		*(dystr+i) = *(source+i);
	}
	*(dystr+i) = '\0';
}

/* get the content of the string */
char * dystring::get(){
	return dystr;
}

/* return true (1) if string is palindrome. false (0) otherwise */
bool dystring::isPalindrome(){
	for(long i=0, j=dystrlen-1; i<=j; i++,j--){
		if(*(dystr+i)!=*(dystr+j))
			return false;
	}
	return true;
}

/* get the length of the string */
long dystring::length(){
	return dystrlen;
}

/* reverse string */
void dystring::reverse(){
	char ch;
	for(long i=0, j=dystrlen-1; i<j; i++,j--){
		ch = *(dystr+i);
		*(dystr+i) = *(dystr+j);
		*(dystr+j) = ch;
	}
}

/* toggle case. change A to a and vice versa */
void dystring::toggleCase(){
	for(long i=0;i<dystrlen;i++){
		char ch = *(dystr+i);
		if(ch>=65 && ch<=90){
			*(dystr+i) = ch + 32;
		}else if(ch>=97 && ch<=122){
			*(dystr+i) = ch - 32;
		}
	}
}

/* toUpper case change a to A */
void dystring::toUpper(){
	for(long i=0;i<dystrlen;i++){
		char ch = *(dystr+i);
		if(ch>=97 && ch<=122){
			*(dystr+i) = ch - 32;
		}
	}
}
/* toLower case change A to a */
void dystring::toLower(){
	for(long i=0;i<dystrlen;i++){
		char ch = *(dystr+i);
		if(ch>=65 && ch<=90){
			*(dystr+i) = ch + 32;
		}
	}
}<commit_msg>functions implementation<commit_after>/**
* Project: dystring
* File: dystring.cpp
* Version: 1.0
* Author: Yusuf Shakeel
* Date: 08 August 2014 Friday
* Language: C++
*
* GitHub repository:
* https://github.com/yusufshakeel/CPP-Project/tree/master/dystring
*
* Author:
* https://www.facebook.com/yusufshakeel
* https://www.youtube.com/yusufshakeel
* https://plus.google.com/+YusufShakeel
* https://www.twitter.com/yusufshakeel
* https://github.com/yusufshakeel
*
* ======================================
* License
* ======================================
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Yusuf Shakeel
*
* 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.
*/

#include "dystring.h"

//----- DYSTRING CLASS FUNCTIONS ----------------------//

//----- PRIVATE FUNCTIONS -----------------------------//
/* memory allocation */
void dystring::__dymalloc(void){
	if(dystr != 0)
		delete dystr;
	dystr = new char[dystrlen + 1];
}

/* return length of the string s */
long dystring::__dystrlen(const char *s){
	long l = 0;
	while(*(s + l) != '\0')
		l++;
	return l;
}

/* reallocate memory space and retain previous string */
void dystring::__dyrealloc(void){
	char *tmp = new char[dystrlen + 1];
	long i;
	for(i = 0; *(dystr + i) != '\0'; i++){
		*(tmp + i) = *(dystr + i);
	}
	*(tmp + i) = '\0';
	delete dystr;
	dystr = tmp;
}

//----- PUBLIC FUNCTIONS ------------------------------//

//----- CONSTRUCTORS ----------------------------------//

//default constructor
dystring::dystring(void){
	dystrlen = 0;
	dystr = new char('\0');
}

//parameterized constructor
dystring::dystring(const char *s){
	copy(s);
}

//----- MEMBER FUNCTIONS ------------------------------//

/* concatenate source to string */
void dystring::concat(const char *source){
	long slen = __dystrlen(source);
	long i = dystrlen;
	dystrlen += slen;
	__dyrealloc();
	for(long j = 0; *(source + j) != '\0'; j++, i++){
		*(dystr + i) = *(source + j);
	}
	*(dystr + i)='\0';
}

/* copy source to string */
void dystring::copy(const char *source){
	dystrlen = __dystrlen(source);
	__dymalloc();
	long i;
	for(i = 0; *(source + i) != '\0'; i++){
		*(dystr + i) = *(source + i);
	}
	*(dystr + i) = '\0';
}

/* return character at the given index, NULL (\0) for invalid index. */
char dystring::charAt(long index){
	if(index < 0 || index >= dystrlen)
		return '\0';
	return *(dystr+index);
}

/* get the content of the string dystr */
char * dystring::get(void){
	return dystr;
}

/* return true (1) if string is palindrome. false (0) otherwise */
bool dystring::isPalindrome(void){
	for(long i = 0, j = dystrlen - 1; i <= j; i++, j--){
		if(*(dystr + i) != *(dystr + j))
			return false;
	}
	return true;
}

/* return index of first occurance of the character ch in string, -1 otherwise. */
long dystring::indexOf(const char ch){
	for(long i = 0; *(dystr + i) != '\0'; i++){
		if(*(dystr + i) == ch)
			return i;
	}
	return -1;
}

/* return index of first occurance of the substring str in string, -1 otherwise. */
long dystring::indexOf(const char *str){
	long slen = __dystrlen(str);
	for(long i = 0, c = 0; *(dystr + i) != '\0'; i++, c = 0){
		for(long j = 0; j < slen; j++){
			if(*(dystr + i + j) == *(str + j))
				c++;
		}
		if(c == slen)
			return i;
	}
	return -1;
}

/* insert character ch at position index in string when index is valid, ignore otherwise. */
void dystring::insertAt(const char ch, long index){
	if(index >= 0 && index < dystrlen){
		dystrlen++;
		__dyrealloc();
		for(long i = dystrlen - 1; i > index; i--){
			*(dystr + i) = *(dystr + i - 1);
		}
		*(dystr + index) = ch;
	}
}

/* return index of last occurance of the character ch in string, -1 otherwise. */
long dystring::lastIndexOf(const char ch){
	for(long i = dystrlen - 1; i >= 0; i--){
		if(*(dystr + i) == ch)
			return i;
	}
	return -1;
}

/* return index of last occurance of the substring str in string, -1 otherwise. */
long dystring::lastIndexOf(const char *str){
	long slen = __dystrlen(str);
	for(long i = dystrlen - slen, c = 0; i >= 0; i--, c = 0){
		for(long j = 0; j < slen; j++){
			if(*(dystr + i + j) == *(str + j))
				c++;
		}
		if(c == slen)
			return i;
	}
	return -1;
}

/* get the length of the string */
long dystring::length(void){
	return dystrlen;
}

/* replace all occurance of the character ch with nch in the string.*/
void dystring::replace(const char ch, const char nch){
	for(long i = 0; i < dystrlen; i++){
		if(*(dystr + i) == ch)
			*(dystr + i) = nch;
	}
}

/* reverse string */
void dystring::reverse(void){
	char ch;
	for(long i = 0, j = dystrlen - 1; i < j; i++, j--){
		ch = *(dystr + i);
		*(dystr + i) = *(dystr + j);
		*(dystr + j) = ch;
	}
}

/* toggle case. change A to a and vice versa */
void dystring::toggleCase(void){
	for(long i = 0; i < dystrlen; i++){
		char ch = *(dystr + i);
		if(ch >= 65 && ch <= 90){
			*(dystr + i) = ch + 32;
		}else if(ch >= 97 && ch <= 122){
			*(dystr + i) = ch - 32;
		}
	}
}

/* toLower case change A to a */
void dystring::toLower(void){
	for(long i = 0; i < dystrlen; i++){
		char ch = *(dystr + i);
		if(ch >= 65 && ch <= 90){
			*(dystr + i) = ch + 32;
		}
	}
}

/* toUpper case change a to A */
void dystring::toUpper(void){
	for(long i = 0; i < dystrlen; i++){
		char ch = *(dystr + i);
		if(ch >= 97 && ch <= 122){
			*(dystr + i) = ch - 32;
		}
	}
}

/* remove space from front and end of the string. */
void dystring::trim(void){
	long beg = 0, end = dystrlen - 1;
	while(*(dystr + beg) < 33)
		beg++;
	while(*(dystr + end) < 33)
		end--;
	dystrlen = end - beg + 1;
	char *tmp = new char[dystrlen + 1];
	long i;
	for(i = 0; i < dystrlen; i++){
		*(tmp + i) = *(dystr + beg + i);
	}
	*(tmp + i) = '\0';
	delete dystr;
	dystr = tmp;
}

/* return a substring from index start till the end of the string, for invalid start index return NULL (\0) */
char * dystring::substring(long start){
	if(start < 0 || start >= dystrlen)
		return '\0';

	long substrlen = dystrlen - start;
	char *str = new char[substrlen + 1];
	long i;
	for(i = 0; i < substrlen; i++){
		*(str + i) = *(dystr + start + i);
	}
	*(str + i) = '\0';
	return str;
}

/* return a substring from index start to end, for invalid index return NULL (\0) */
char * dystring::substring(long start, long end){
	if(start < 0 || start >= dystrlen || end < 0 || end >= dystrlen)
		return '\0';

	long substrlen = end - start + 1;
	char *str = new char[substrlen + 1];
	long i;
	for(i = 0; i < substrlen; i++){
		*(str + i) = *(dystr + start + i);
	}
	*(str + i) = '\0';
	return str;
}<|endoftext|>


<commit_before>// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#include "iceoryx_posh/internal/mepoo/shm_safe_unmanaged_chunk.hpp"

#include "iceoryx_posh/internal/mepoo/memory_manager.hpp"
#include "iceoryx_posh/internal/mepoo/shared_chunk.hpp"
#include "iceoryx_posh/mepoo/chunk_header.hpp"
#include "iceoryx_posh/mepoo/mepoo_config.hpp"
#include "iceoryx_utils/internal/posix_wrapper/shared_memory_object/allocator.hpp"

#include "test.hpp"

namespace
{
using namespace ::testing;

using namespace iox::mepoo;

class ShmSafeUnmanagedChunk_test : public Test
{
  public:
    void SetUp() override
    {
        MePooConfig mempoolconf;
        mempoolconf.addMemPool({CHUNK_SIZE, NUM_CHUNKS_IN_POOL});
        memoryManager.configureMemoryManager(mempoolconf, m_memoryAllocator, m_memoryAllocator);
    }

    SharedChunk getChunkFromMemoryManager()
    {
        auto chunkSettingsResult = iox::mepoo::ChunkSettings::create(sizeof(bool), alignof(bool));
        EXPECT_FALSE(chunkSettingsResult.has_error());
        if (chunkSettingsResult.has_error())
        {
            return nullptr;
        }
        auto& chunkSettings = chunkSettingsResult.value();

        return memoryManager.getChunk(chunkSettings);
    }

    iox::mepoo::MemoryManager memoryManager;

  private:
    static constexpr size_t KILOBYTE = 1 << 10;
    static constexpr size_t MEMORY_SIZE = 100 * KILOBYTE;
    std::unique_ptr<char[]> m_memory{new char[MEMORY_SIZE]};
    static constexpr uint32_t NUM_CHUNKS_IN_POOL = 100;
    static constexpr uint32_t CHUNK_SIZE = 128;

    iox::posix::Allocator m_memoryAllocator{m_memory.get(), MEMORY_SIZE};
};

TEST_F(ShmSafeUnmanagedChunk_test, DefaultConstructedResultsInLogicallyNullptr)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_TRUE(sut.isLogicalNullptr());
}

TEST_F(ShmSafeUnmanagedChunk_test, ConstructedWithEmptySharedChunkResultsInLogicallyNullptr)
{
    SharedChunk sharedChunk;
    ShmSafeUnmanagedChunk sut(sharedChunk);

    EXPECT_TRUE(sut.isLogicalNullptr());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallIsLogicalNullptrOnSutConstructedWithSharedChunkResultsNotInLogicalyNullptr)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    EXPECT_FALSE(sut.isLogicalNullptr());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallIsLogicalNullptrOnSutPreviouslyCalledReleaseToSharedChunkResultsInLogicalyNullptr)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);
    sut.releaseToSharedChunk();

    EXPECT_TRUE(sut.isLogicalNullptr());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallIsLogicalNullptrOnSutPreviouslyCalledDuplicateToSharedChunkResultsNotInLogicalyNullptr)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);
    sut.duplicateToSharedChunk();

    EXPECT_FALSE(sut.isLogicalNullptr());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallReleaseToSharedChunkOnDefaultConstructedSutResultsInEmptySharedChunk)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_FALSE(sut.releaseToSharedChunk());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallReleaseToSharedChunkOnSutConstructedWithSharedChunkResultsInNotEmptySharedChunk)
{
    ShmSafeUnmanagedChunk sut(getChunkFromMemoryManager());

    EXPECT_EQ(memoryManager.getMemPoolInfo(0).m_usedChunks, 1U);
    EXPECT_TRUE(sut.releaseToSharedChunk());
    EXPECT_EQ(memoryManager.getMemPoolInfo(0).m_usedChunks, 0U);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallReleaseToSharedChunkTwiceOnSutConstructedWithSharedChunkResultsInEmptySharedChunk)
{
    ShmSafeUnmanagedChunk sut(getChunkFromMemoryManager());
    sut.releaseToSharedChunk();

    EXPECT_FALSE(sut.releaseToSharedChunk());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallDuplicateToSharedChunkOnDefaultConstructedSutResultsEmptySharedChunk)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_FALSE(sut.duplicateToSharedChunk());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallDuplicateToSharedChunkOnSutConstructedWithSharedChunkResultsInNotEmptySharedChunk)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    auto duplicatedSharedChunk = sut.duplicateToSharedChunk();
    EXPECT_TRUE(duplicatedSharedChunk);

    sut.releaseToSharedChunk();
    EXPECT_EQ(memoryManager.getMemPoolInfo(0).m_usedChunks, 1U);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallDuplicateToSharedChunkOnSutPreviouslyCalledReleaseToSharedChunkResultsInEmptySharedChunk)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);
    sut.releaseToSharedChunk();

    EXPECT_FALSE(sut.duplicateToSharedChunk());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallGetChunkHeaderOnNonConstDefaultConstructedSutResultsInNullptr)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_EQ(sut.getChunkHeader(), nullptr);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallGetChunkHeaderOnNonConstSutConstructedWithSharedChunkResultsInValidHeader)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    auto chunkHeader = sut.getChunkHeader();
    EXPECT_NE(chunkHeader, nullptr);
    EXPECT_EQ(chunkHeader, sharedChunk.getChunkHeader());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallGetChunkHeaderOnConstDefaultConstructedSutResultsInNullptr)
{
    const ShmSafeUnmanagedChunk sut;

    EXPECT_EQ(sut.getChunkHeader(), nullptr);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallGetChunkHeaderOnConstSutConstructedWithSharedChunkResultsInValidHeader)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    [&](const ShmSafeUnmanagedChunk& sut) {
        auto chunkHeader = sut.getChunkHeader();
        EXPECT_NE(chunkHeader, nullptr);
        EXPECT_EQ(chunkHeader, sharedChunk.getChunkHeader());
    } (sut);

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallNonConstGetChunkHeaderResultsInNonConstChunkHeader)
{
    auto isNonConstReturn =
        std::is_same<decltype(std::declval<ShmSafeUnmanagedChunk>().getChunkHeader()), ChunkHeader*>::value;
    EXPECT_TRUE(isNonConstReturn);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallConstGetChunkHeaderResultsInConstChunkHeader)
{
    auto isConstReturn =
        std::is_same<decltype(std::declval<const ShmSafeUnmanagedChunk>().getChunkHeader()), const ChunkHeader*>::value;
    EXPECT_TRUE(isConstReturn);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallIsNotLogicalNullptrAndHasNoOtherOwnersOnDefaultConstructedResultsInFalse)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_FALSE(sut.isNotLogicalNullptrAndHasNoOtherOwners());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallIsNotLogicalNullptrAndHasNoOtherOwnersOnOnSutConstructedWithSharedChunkResultsInTrue)
{
    ShmSafeUnmanagedChunk sut(getChunkFromMemoryManager());

    EXPECT_TRUE(sut.isNotLogicalNullptrAndHasNoOtherOwners());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallIsNotLogicalNullptrAndHasNoOtherOwnersOnOnSutConstructedWithSharedChunkAndOtherOwnerResultsInFalse)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    EXPECT_FALSE(sut.isNotLogicalNullptrAndHasNoOtherOwners());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, Foo)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    EXPECT_EQ(memoryManager.getMemPoolInfo(0).m_usedChunks, 1U);

    sut.releaseToSharedChunk();
}

} // namespace
<commit_msg>iox-#713 additional tests for ShmSafeUnmanagedChunk<commit_after>// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#include "iceoryx_posh/internal/mepoo/shm_safe_unmanaged_chunk.hpp"

#include "iceoryx_posh/internal/mepoo/memory_manager.hpp"
#include "iceoryx_posh/internal/mepoo/shared_chunk.hpp"
#include "iceoryx_posh/mepoo/chunk_header.hpp"
#include "iceoryx_posh/mepoo/mepoo_config.hpp"
#include "iceoryx_utils/internal/posix_wrapper/shared_memory_object/allocator.hpp"

#include "test.hpp"

namespace
{
using namespace ::testing;

using namespace iox::mepoo;

class ShmSafeUnmanagedChunk_test : public Test
{
  public:
    void SetUp() override
    {
        MePooConfig mempoolconf;
        mempoolconf.addMemPool({CHUNK_SIZE, NUM_CHUNKS_IN_POOL});
        memoryManager.configureMemoryManager(mempoolconf, m_memoryAllocator, m_memoryAllocator);
    }

    SharedChunk getChunkFromMemoryManager()
    {
        auto chunkSettingsResult = iox::mepoo::ChunkSettings::create(sizeof(bool), alignof(bool));
        EXPECT_FALSE(chunkSettingsResult.has_error());
        if (chunkSettingsResult.has_error())
        {
            return nullptr;
        }
        auto& chunkSettings = chunkSettingsResult.value();

        return memoryManager.getChunk(chunkSettings);
    }

    iox::mepoo::MemoryManager memoryManager;

  private:
    static constexpr size_t KILOBYTE = 1 << 10;
    static constexpr size_t MEMORY_SIZE = 100 * KILOBYTE;
    std::unique_ptr<char[]> m_memory{new char[MEMORY_SIZE]};
    static constexpr uint32_t NUM_CHUNKS_IN_POOL = 100;
    static constexpr uint32_t CHUNK_SIZE = 128;

    iox::posix::Allocator m_memoryAllocator{m_memory.get(), MEMORY_SIZE};
};

TEST_F(ShmSafeUnmanagedChunk_test, DefaultConstructedResultsInLogicalNullptr)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_TRUE(sut.isLogicalNullptr());
}

TEST_F(ShmSafeUnmanagedChunk_test, ConstructedWithEmptySharedChunkResultsInLogicalNullptr)
{
    SharedChunk sharedChunk;
    ShmSafeUnmanagedChunk sut(sharedChunk);

    EXPECT_TRUE(sut.isLogicalNullptr());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallIsLogicalNullptrOnSutConstructedWithSharedChunkResultsNotInLogicalNullptr)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    EXPECT_FALSE(sut.isLogicalNullptr());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallIsLogicalNullptrOnSutPreviouslyCalledReleaseToSharedChunkResultsInLogicalNullptr)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);
    sut.releaseToSharedChunk();

    EXPECT_TRUE(sut.isLogicalNullptr());
}

TEST_F(ShmSafeUnmanagedChunk_test,
       CallIsLogicalNullptrOnSutPreviouslyCalledDuplicateToSharedChunkResultsNotInLogicalNullptr)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);
    sut.duplicateToSharedChunk();

    EXPECT_FALSE(sut.isLogicalNullptr());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallReleaseToSharedChunkOnDefaultConstructedSutResultsInEmptySharedChunk)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_FALSE(sut.releaseToSharedChunk());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallReleaseToSharedChunkOnSutConstructedWithSharedChunkResultsInNotEmptySharedChunk)
{
    ShmSafeUnmanagedChunk sut(getChunkFromMemoryManager());

    EXPECT_EQ(memoryManager.getMemPoolInfo(0).m_usedChunks, 1U);
    EXPECT_TRUE(sut.releaseToSharedChunk());
    EXPECT_EQ(memoryManager.getMemPoolInfo(0).m_usedChunks, 0U);
}

TEST_F(ShmSafeUnmanagedChunk_test,
       CallReleaseToSharedChunkTwiceOnSutConstructedWithSharedChunkResultsInEmptySharedChunk)
{
    ShmSafeUnmanagedChunk sut(getChunkFromMemoryManager());
    sut.releaseToSharedChunk();

    EXPECT_FALSE(sut.releaseToSharedChunk());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallDuplicateToSharedChunkOnDefaultConstructedSutResultsEmptySharedChunk)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_FALSE(sut.duplicateToSharedChunk());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test,
       CallDuplicateToSharedChunkOnSutConstructedWithSharedChunkResultsInNotEmptySharedChunk)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    auto duplicatedSharedChunk = sut.duplicateToSharedChunk();
    EXPECT_TRUE(duplicatedSharedChunk);

    sut.releaseToSharedChunk();
    EXPECT_EQ(memoryManager.getMemPoolInfo(0).m_usedChunks, 1U);
}

TEST_F(ShmSafeUnmanagedChunk_test,
       CallDuplicateToSharedChunkOnSutPreviouslyCalledReleaseToSharedChunkResultsInEmptySharedChunk)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);
    sut.releaseToSharedChunk();

    EXPECT_FALSE(sut.duplicateToSharedChunk());
}

TEST_F(ShmSafeUnmanagedChunk_test, CallGetChunkHeaderOnNonConstDefaultConstructedSutResultsInNullptr)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_EQ(sut.getChunkHeader(), nullptr);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallGetChunkHeaderOnNonConstSutConstructedWithSharedChunkResultsInValidHeader)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    auto chunkHeader = sut.getChunkHeader();
    EXPECT_NE(chunkHeader, nullptr);
    EXPECT_EQ(chunkHeader, sharedChunk.getChunkHeader());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallGetChunkHeaderOnConstDefaultConstructedSutResultsInNullptr)
{
    const ShmSafeUnmanagedChunk sut;

    EXPECT_EQ(sut.getChunkHeader(), nullptr);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallGetChunkHeaderOnConstSutConstructedWithSharedChunkResultsInValidHeader)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    [&](const ShmSafeUnmanagedChunk& sut) {
        auto chunkHeader = sut.getChunkHeader();
        EXPECT_NE(chunkHeader, nullptr);
        EXPECT_EQ(chunkHeader, sharedChunk.getChunkHeader());
    }(sut);

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test, CallNonConstGetChunkHeaderResultsInNonConstChunkHeader)
{
    auto isNonConstReturn =
        std::is_same<decltype(std::declval<ShmSafeUnmanagedChunk>().getChunkHeader()), ChunkHeader*>::value;
    EXPECT_TRUE(isNonConstReturn);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallConstGetChunkHeaderResultsInConstChunkHeader)
{
    auto isConstReturn =
        std::is_same<decltype(std::declval<const ShmSafeUnmanagedChunk>().getChunkHeader()), const ChunkHeader*>::value;
    EXPECT_TRUE(isConstReturn);
}

TEST_F(ShmSafeUnmanagedChunk_test, CallIsNotLogicalNullptrAndHasNoOtherOwnersOnDefaultConstructedResultsInFalse)
{
    ShmSafeUnmanagedChunk sut;

    EXPECT_FALSE(sut.isNotLogicalNullptrAndHasNoOtherOwners());
}

TEST_F(ShmSafeUnmanagedChunk_test,
       CallIsNotLogicalNullptrAndHasNoOtherOwnersOnOnSutConstructedWithSharedChunkResultsInTrue)
{
    ShmSafeUnmanagedChunk sut(getChunkFromMemoryManager());

    EXPECT_TRUE(sut.isNotLogicalNullptrAndHasNoOtherOwners());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test,
       CallIsNotLogicalNullptrAndHasNoOtherOwnersOnOnSutConstructedWithSharedChunkAndOtherOwnerResultsInFalse)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    EXPECT_FALSE(sut.isNotLogicalNullptrAndHasNoOtherOwners());

    sut.releaseToSharedChunk();
}

TEST_F(
    ShmSafeUnmanagedChunk_test,
    CallIsNotLogicalNullptrAndHasNoOtherOwnersOnOnSutConstructedWithSharedChunkAndOtherOwnerReleasedOwnershipResultsInTrue)
{
    auto sharedChunk = getChunkFromMemoryManager();

    ShmSafeUnmanagedChunk sut(sharedChunk);

    // release ownership by assigning an empty SharedChunk
    sharedChunk = SharedChunk();

    EXPECT_TRUE(sut.isNotLogicalNullptrAndHasNoOtherOwners());

    sut.releaseToSharedChunk();
}

TEST_F(ShmSafeUnmanagedChunk_test,
       CallIsNotLogicalNullptrAndHasNoOtherOwnersOnOnSutPreviouslyCalledReleaseToSharedChunkResultsInFalse)
{
    ShmSafeUnmanagedChunk sut(getChunkFromMemoryManager());
    sut.releaseToSharedChunk();

    EXPECT_FALSE(sut.isNotLogicalNullptrAndHasNoOtherOwners());
}

} // namespace
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2008 by Marc Boris Duerner
 *
 * 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.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "fileimpl.h"
#include "cxxtools/ioerror.h"
#include "cxxtools/systemerror.h"
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

namespace cxxtools {

// EACCES Permission denied.
// EMFILE Too many file descriptors in use by process.
// ENOENT Directory does not exist, or name is an empty string.
// ENOTDIR name is not a directory.
// EBUSY  pathname is currently in use by the system or some process that prevents its  removal.
// EFAULT pathname points outside your accessible address space.
// EINVAL pathname has .  as last component.
// ELOOP  Too many symbolic links were encountered in resolving pathname.
// ENAMETOOLONG pathname was too long.
// ENOMEM Insufficient kernel memory was available.
// ENOTEMPTY pathname contains entries other than . and .. ; or, pathname has ..  as its final component.
// EPERM  The directory containing pathname has the sticky bit (S_ISVTX) set
// EPERM  The filesystem containing pathname does not support the removal of directories.
// EROFS  pathname refers to a file on a read-only filesystem.
void throwErrno(const std::string& path, const cxxtools::SourceInfo& si)
{
    if(errno == EEXIST)
        throw AccessFailed(path, si);

    switch(errno)
    {
        case EIO:
        case EBADF:
        case EBUSY:
        case ENOSPC:
        case EMLINK:
        case ENOTEMPTY:
        case EXDEV:
            throw IOError( strerror(errno), si );

        case EACCES:
        case EPERM:
        case EROFS:
        case ENXIO:
            throw PermissionDenied(path, si);

        case ELOOP:
        case ENAMETOOLONG:
        case ENOENT:
        case ENOTDIR:
        case EISDIR:
            throw FileNotFound(path, si);

        case ENODEV:
            throw DeviceNotFound(path, si);

       case ENOMEM:
           throw std::bad_alloc();

        default: // EFAULT EMFILE EOVERFLOW
            throw SystemError( strerror(errno), si );
    }
}

void throwFileErrno(const std::string& path, const cxxtools::SourceInfo& si)
{
    switch(errno)
    {
        case ELOOP:
        case ENAMETOOLONG:
        case ENOENT:
        case ENOTDIR:
        case EISDIR:
            throw FileNotFound(path, si);

        default: throwErrno(path, si);
    }
}

std::size_t FileImpl::size(const std::string& path)
{
    struct stat buff;

    if( 0 != stat(path.c_str(), &buff) )
    {
        throwFileErrno(path, CXXTOOLS_SOURCEINFO);
    }

    return buff.st_size;
}

void FileImpl::resize(const std::string& path, std::size_t newSize)
{
    int ret = 0;
    do
    {
        ret = truncate(path.c_str(), newSize);
    }
    while ( ret == EINTR );

    if(ret != 0)
        throwFileErrno( path, CXXTOOLS_SOURCEINFO);
}

void FileImpl::remove(const std::string& path)
{
    if(0 != ::remove(path.c_str()))
        throwFileErrno(path, CXXTOOLS_SOURCEINFO);
}

void FileImpl::move(const std::string& path, const std::string& to)
{
    if( 0 != ::rename(path.c_str(), to.c_str()) )
        throwFileErrno(path, CXXTOOLS_SOURCEINFO);
}

void FileImpl::create(const std::string& path)
{
    int fd = open(path.c_str(), O_RDWR|O_EXCL|O_CREAT, 0777);
    if( fd < 0 )
        throwFileErrno(path, CXXTOOLS_SOURCEINFO);

    ::close(fd);
}

}
<commit_msg>add missing header<commit_after>/*
 * Copyright (C) 2005-2008 by Marc Boris Duerner
 *
 * 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.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "fileimpl.h"
#include "cxxtools/ioerror.h"
#include "cxxtools/systemerror.h"
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

namespace cxxtools {

// EACCES Permission denied.
// EMFILE Too many file descriptors in use by process.
// ENOENT Directory does not exist, or name is an empty string.
// ENOTDIR name is not a directory.
// EBUSY  pathname is currently in use by the system or some process that prevents its  removal.
// EFAULT pathname points outside your accessible address space.
// EINVAL pathname has .  as last component.
// ELOOP  Too many symbolic links were encountered in resolving pathname.
// ENAMETOOLONG pathname was too long.
// ENOMEM Insufficient kernel memory was available.
// ENOTEMPTY pathname contains entries other than . and .. ; or, pathname has ..  as its final component.
// EPERM  The directory containing pathname has the sticky bit (S_ISVTX) set
// EPERM  The filesystem containing pathname does not support the removal of directories.
// EROFS  pathname refers to a file on a read-only filesystem.
void throwErrno(const std::string& path, const cxxtools::SourceInfo& si)
{
    if(errno == EEXIST)
        throw AccessFailed(path, si);

    switch(errno)
    {
        case EIO:
        case EBADF:
        case EBUSY:
        case ENOSPC:
        case EMLINK:
        case ENOTEMPTY:
        case EXDEV:
            throw IOError( strerror(errno), si );

        case EACCES:
        case EPERM:
        case EROFS:
        case ENXIO:
            throw PermissionDenied(path, si);

        case ELOOP:
        case ENAMETOOLONG:
        case ENOENT:
        case ENOTDIR:
        case EISDIR:
            throw FileNotFound(path, si);

        case ENODEV:
            throw DeviceNotFound(path, si);

       case ENOMEM:
           throw std::bad_alloc();

        default: // EFAULT EMFILE EOVERFLOW
            throw SystemError( strerror(errno), si );
    }
}

void throwFileErrno(const std::string& path, const cxxtools::SourceInfo& si)
{
    switch(errno)
    {
        case ELOOP:
        case ENAMETOOLONG:
        case ENOENT:
        case ENOTDIR:
        case EISDIR:
            throw FileNotFound(path, si);

        default: throwErrno(path, si);
    }
}

std::size_t FileImpl::size(const std::string& path)
{
    struct stat buff;

    if( 0 != stat(path.c_str(), &buff) )
    {
        throwFileErrno(path, CXXTOOLS_SOURCEINFO);
    }

    return buff.st_size;
}

void FileImpl::resize(const std::string& path, std::size_t newSize)
{
    int ret = 0;
    do
    {
        ret = truncate(path.c_str(), newSize);
    }
    while ( ret == EINTR );

    if(ret != 0)
        throwFileErrno( path, CXXTOOLS_SOURCEINFO);
}

void FileImpl::remove(const std::string& path)
{
    if(0 != ::remove(path.c_str()))
        throwFileErrno(path, CXXTOOLS_SOURCEINFO);
}

void FileImpl::move(const std::string& path, const std::string& to)
{
    if( 0 != ::rename(path.c_str(), to.c_str()) )
        throwFileErrno(path, CXXTOOLS_SOURCEINFO);
}

void FileImpl::create(const std::string& path)
{
    int fd = open(path.c_str(), O_RDWR|O_EXCL|O_CREAT, 0777);
    if( fd < 0 )
        throwFileErrno(path, CXXTOOLS_SOURCEINFO);

    ::close(fd);
}

}
<|endoftext|>


<commit_before><commit_msg>Playground work.<commit_after>#include <iostream>
#include <fstream>
#include <array>

#include <cstdint>

using std::cout;
using std::endl;
using std::ofstream;

using colour_code = std::array<uint8_t, 3>;

static constexpr colour_code BLUE_VIOLET{ {0x8a, 0x2b, 0xe2} };

int main(int argc, char *argv[]) {
  ofstream spi_dev{"/dev/spidev0.0", ofstream::binary | ofstream::out};

  cout << spi_dev.is_open() << endl;

  spi_dev.close();
}
<|endoftext|>