<commit_before>/******************************************************************************
 * $Id$
 *
 * Project:  libLAS - http://liblas.org - A BSD library for LAS format data.
 * Purpose:  Exception subclasses for C++ libLAS
 * Author:   Mateusz Loskot, mateusz@loskot.net
 *
 ******************************************************************************
 * Copyright (c) 2008, Mateusz Loskot
 * Copyright (c) 2008, Howard Butler
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following
 * conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of the Martin Isenburg or Iowa Department
 *       of Natural Resources nor the names of its contributors may be
 *       used to endorse or promote products derived from this software
 *       without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef PDAL_EXCEPTION_HPP_INCLUDED
#define PDAL_EXCEPTION_HPP_INCLUDED

#include <stdexcept>

namespace pdal
{

// base class for all pdal exceptions
class pdal_error : public std::runtime_error
{
public:
    pdal_error(std::string const& msg)
        : std::runtime_error(msg)
    {}
};

/// Exception reporting invalid point data.
/// It's usually thrown by Point::Validate function.
class invalid_point_data : public pdal_error
{
public:
    invalid_point_data(std::string const& msg, unsigned int who)
        : pdal_error(msg), m_who(who)
    {}

    /// Return flags identifying invalid point data members.
    /// Flags are composed with composed with Point::DataMemberFlag.
    /// Testing flags example: bool timeValid = e.who() & Point::eTime;
    unsigned int who() const
   {
        return m_who;
    }

private:
    unsigned int m_who;
};

class invalid_expression : public pdal_error
{
public:

    invalid_expression(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this for conditions that indicate a program bug -- things
// that we'd assert can't happen
class internal_error : public pdal_error
{
public:

    internal_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

class invalid_format : public pdal_error
{
public:

    invalid_format(std::string const& msg)
        : pdal_error(msg)
    {}
};

// for when a stage doesn't get the schema it expects
class impedance_invalid : public pdal_error
{
public:

    impedance_invalid(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this for attempts to use a feature not compiled in, e.g. laszip or gdal
class configuration_error : public pdal_error
{
public:
    configuration_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this for situations where indeterminate point counts prevent some
// operation from happening
class indeterminate_count_error : public pdal_error
{
public:
    indeterminate_count_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

class dimension_not_found : public pdal_error
{
public:

    dimension_not_found(std::string const& msg)
        : pdal_error(msg)
    {}
};

class multiple_parent_dimensions : public pdal_error
{
public:

    multiple_parent_dimensions(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this for code still under development
class not_yet_implemented : public pdal_error
{
public:
    not_yet_implemented(std::string const& msg)
        : pdal_error(msg)
    {}
};

// for Option processing
class option_not_found : public pdal_error
{
public:
    option_not_found(std::string const& msg)
        : pdal_error(msg)
    {}
};

// for errors when reading pipeline XML
class pipeline_xml_error : public pdal_error
{
public:
    pipeline_xml_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this when an executing pipeline needs to abort per user request
class pipeline_interrupt : public pdal_error
{
public:
    pipeline_interrupt(std::string const& msg)
        : pdal_error(msg)
    {}
};

/// Used for pdal::Bounds
class bounds_error : public pdal_error
{
public:

    bounds_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

class gdal_error : public pdal_error
{
public:
    gdal_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

class schema_error : public std::runtime_error
{
public:
    schema_error(std::string const& msg)
        : std::runtime_error(msg)
    {}
};

class buffer_error : public std::runtime_error
{
public:
    buffer_error(std::string const& msg)
        : std::runtime_error(msg)
    {}
};

class python_error : public std::runtime_error
{
public:
    python_error(std::string const& msg)
        : std::runtime_error(msg)
    {}
};

} // namespace pdal

#endif // PDAL_EXCEPTION_HPP_INCLUDED
<commit_msg>add errors about metadata<commit_after>/******************************************************************************
 * $Id$
 *
 * Project:  libLAS - http://liblas.org - A BSD library for LAS format data.
 * Purpose:  Exception subclasses for C++ libLAS
 * Author:   Mateusz Loskot, mateusz@loskot.net
 *
 ******************************************************************************
 * Copyright (c) 2008, Mateusz Loskot
 * Copyright (c) 2008, Howard Butler
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following
 * conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of the Martin Isenburg or Iowa Department
 *       of Natural Resources nor the names of its contributors may be
 *       used to endorse or promote products derived from this software
 *       without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef PDAL_EXCEPTION_HPP_INCLUDED
#define PDAL_EXCEPTION_HPP_INCLUDED

#include <stdexcept>

namespace pdal
{

// base class for all pdal exceptions
class pdal_error : public std::runtime_error
{
public:
    pdal_error(std::string const& msg)
        : std::runtime_error(msg)
    {}
};

/// Exception reporting invalid point data.
/// It's usually thrown by Point::Validate function.
class invalid_point_data : public pdal_error
{
public:
    invalid_point_data(std::string const& msg, unsigned int who)
        : pdal_error(msg), m_who(who)
    {}

    /// Return flags identifying invalid point data members.
    /// Flags are composed with composed with Point::DataMemberFlag.
    /// Testing flags example: bool timeValid = e.who() & Point::eTime;
    unsigned int who() const
   {
        return m_who;
    }

private:
    unsigned int m_who;
};

class invalid_expression : public pdal_error
{
public:

    invalid_expression(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this for conditions that indicate a program bug -- things
// that we'd assert can't happen
class internal_error : public pdal_error
{
public:

    internal_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

class invalid_format : public pdal_error
{
public:

    invalid_format(std::string const& msg)
        : pdal_error(msg)
    {}
};

// for when a stage doesn't get the schema it expects
class impedance_invalid : public pdal_error
{
public:

    impedance_invalid(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this for attempts to use a feature not compiled in, e.g. laszip or gdal
class configuration_error : public pdal_error
{
public:
    configuration_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this for situations where indeterminate point counts prevent some
// operation from happening
class indeterminate_count_error : public pdal_error
{
public:
    indeterminate_count_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

class dimension_not_found : public pdal_error
{
public:

    dimension_not_found(std::string const& msg)
        : pdal_error(msg)
    {}
};

class multiple_parent_dimensions : public pdal_error
{
public:

    multiple_parent_dimensions(std::string const& msg)
        : pdal_error(msg)
    {}
};

class metadata_not_found : public pdal_error
{
public:

    metadata_not_found(std::string const& msg)
        : pdal_error(msg)
    {}
};

class metadata_error : public pdal_error
{
public:

    metadata_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

class multiple_parent_metadata : public pdal_error
{
public:

    multiple_parent_metadata(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this for code still under development
class not_yet_implemented : public pdal_error
{
public:
    not_yet_implemented(std::string const& msg)
        : pdal_error(msg)
    {}
};

// for Option processing
class option_not_found : public pdal_error
{
public:
    option_not_found(std::string const& msg)
        : pdal_error(msg)
    {}
};

// for errors when reading pipeline XML
class pipeline_xml_error : public pdal_error
{
public:
    pipeline_xml_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

// use this when an executing pipeline needs to abort per user request
class pipeline_interrupt : public pdal_error
{
public:
    pipeline_interrupt(std::string const& msg)
        : pdal_error(msg)
    {}
};

/// Used for pdal::Bounds
class bounds_error : public pdal_error
{
public:

    bounds_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

class gdal_error : public pdal_error
{
public:
    gdal_error(std::string const& msg)
        : pdal_error(msg)
    {}
};

class schema_error : public std::runtime_error
{
public:
    schema_error(std::string const& msg)
        : std::runtime_error(msg)
    {}
};

class buffer_error : public std::runtime_error
{
public:
    buffer_error(std::string const& msg)
        : std::runtime_error(msg)
    {}
};

class python_error : public std::runtime_error
{
public:
    python_error(std::string const& msg)
        : std::runtime_error(msg)
    {}
};

} // namespace pdal

#endif // PDAL_EXCEPTION_HPP_INCLUDED
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: processfactory.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 01:28:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _UNOTOOLS_PROCESSFACTORY_HXX_
#include <unotools/processfactory.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace osl;

namespace utl
{
    // just use the comphelper versions of both functions. The versions here in unotools will become obsolete
    // from SRC610 on.

    void setProcessServiceFactory(const Reference< XMultiServiceFactory >& xSMgr)
    {
        ::comphelper::setProcessServiceFactory(xSMgr);
    }

    Reference< XMultiServiceFactory > getProcessServiceFactory()
    {
        return ::comphelper::getProcessServiceFactory();
    }

} // namesapce utl

<commit_msg>INTEGRATION: CWS changefileheader (1.4.84); FILE MERGED 2008/04/01 16:03:34 thb 1.4.84.3: #i85898# Stripping all external header guards 2008/04/01 12:59:56 thb 1.4.84.2: #i85898# Stripping all external header guards 2008/03/31 13:03:40 rt 1.4.84.1: #i87441# Change license header to LPGL v3.<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: processfactory.cxx,v $
 * $Revision: 1.5 $
 *
 * 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_unotools.hxx"
#include <osl/mutex.hxx>
#include <unotools/processfactory.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>

using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace osl;

namespace utl
{
    // just use the comphelper versions of both functions. The versions here in unotools will become obsolete
    // from SRC610 on.

    void setProcessServiceFactory(const Reference< XMultiServiceFactory >& xSMgr)
    {
        ::comphelper::setProcessServiceFactory(xSMgr);
    }

    Reference< XMultiServiceFactory > getProcessServiceFactory()
    {
        return ::comphelper::getProcessServiceFactory();
    }

} // namesapce utl

<|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

#include "otbSarSensorModelAdapter.h"

#include <cassert>

#include "otbMacro.h"
#include "otbImageKeywordlist.h"

#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#include "ossim/ossimSarSensorModel.h"
#include "ossim/ossimPluginProjectionFactory.h"
#pragma GCC diagnostic pop
#else
#include "ossim/ossimSarSensorModel.h"
#include "ossim/ossimPluginProjectionFactory.h"
#endif

namespace otb
{

SarSensorModelAdapter::SarSensorModelAdapter():
  m_SensorModel(ITK_NULLPTR)
{
}

SarSensorModelAdapter::~SarSensorModelAdapter()
{
  if(m_SensorModel != ITK_NULLPTR)
    delete m_SensorModel;
}

bool SarSensorModelAdapter::LoadState(const ImageKeywordlist& image_kwl)
{
  // InternalModelPointer model = new ossimplugins::ossimSarSensorModel();

   ossimKeywordlist geom;
   image_kwl.convertToOSSIMKeywordlist(geom);

   if(m_SensorModel != ITK_NULLPTR)
     {
     delete m_SensorModel;
     }

   m_SensorModel =  dynamic_cast<ossimplugins::ossimSarSensorModel* >(ossimplugins::ossimPluginProjectionFactory::instance()->createProjection(geom));

   if(m_SensorModel != ITK_NULLPTR)
     {

     return true;
     }

   return false;
}

bool SarSensorModelAdapter::SaveState(ImageKeywordlist & image_kwl)
{
  if(m_SensorModel != ITK_NULLPTR)
    {
    ossimKeywordlist geom;

    bool success = m_SensorModel->saveState(geom);

    if(success)
      {
      image_kwl.Clear();
      image_kwl.SetKeywordlist(geom);

      }
    return success;
    }

  return false;
}

bool SarSensorModelAdapter::IsValidSensorModel() const
{
  return m_SensorModel != ITK_NULLPTR;
}

bool SarSensorModelAdapter::Deburst(std::vector<std::pair<unsigned long, unsigned long>> & lines)
{
  if(m_SensorModel != ITK_NULLPTR)
    {
    return m_SensorModel->deburst(lines);
    }

  return false;
}

bool SarSensorModelAdapter::ImageLineToDeburstLine(const std::vector<std::pair<unsigned long,unsigned long> >& lines, unsigned long imageLine, unsigned long & deburstLine)
{
  return ossimplugins::ossimSarSensorModel::imageLineToDeburstLine(lines,imageLine,deburstLine);
}

void SarSensorModelAdapter::DeburstLineToImageLine(const std::vector<std::pair<unsigned long,unsigned long> >& lines, unsigned long deburstLine, unsigned long & imageLine)
{
  ossimplugins::ossimSarSensorModel::deburstLineToImageLine(lines,deburstLine,imageLine);
}

} // namespace otb
<commit_msg>STY: Remove test before delete (from RFC review)<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

#include "otbSarSensorModelAdapter.h"

#include <cassert>

#include "otbMacro.h"
#include "otbImageKeywordlist.h"

#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#include "ossim/ossimSarSensorModel.h"
#include "ossim/ossimPluginProjectionFactory.h"
#pragma GCC diagnostic pop
#else
#include "ossim/ossimSarSensorModel.h"
#include "ossim/ossimPluginProjectionFactory.h"
#endif

namespace otb
{

SarSensorModelAdapter::SarSensorModelAdapter():
  m_SensorModel(ITK_NULLPTR)
{
}

SarSensorModelAdapter::~SarSensorModelAdapter()
{
    delete m_SensorModel;
}

bool SarSensorModelAdapter::LoadState(const ImageKeywordlist& image_kwl)
{
  // InternalModelPointer model = new ossimplugins::ossimSarSensorModel();

   ossimKeywordlist geom;
   image_kwl.convertToOSSIMKeywordlist(geom);

   if(m_SensorModel != ITK_NULLPTR)
     {
     delete m_SensorModel;
     }

   m_SensorModel =  dynamic_cast<ossimplugins::ossimSarSensorModel* >(ossimplugins::ossimPluginProjectionFactory::instance()->createProjection(geom));

   if(m_SensorModel != ITK_NULLPTR)
     {

     return true;
     }

   return false;
}

bool SarSensorModelAdapter::SaveState(ImageKeywordlist & image_kwl)
{
  if(m_SensorModel != ITK_NULLPTR)
    {
    ossimKeywordlist geom;

    bool success = m_SensorModel->saveState(geom);

    if(success)
      {
      image_kwl.Clear();
      image_kwl.SetKeywordlist(geom);

      }
    return success;
    }

  return false;
}

bool SarSensorModelAdapter::IsValidSensorModel() const
{
  return m_SensorModel != ITK_NULLPTR;
}

bool SarSensorModelAdapter::Deburst(std::vector<std::pair<unsigned long, unsigned long>> & lines)
{
  if(m_SensorModel != ITK_NULLPTR)
    {
    return m_SensorModel->deburst(lines);
    }

  return false;
}

bool SarSensorModelAdapter::ImageLineToDeburstLine(const std::vector<std::pair<unsigned long,unsigned long> >& lines, unsigned long imageLine, unsigned long & deburstLine)
{
  return ossimplugins::ossimSarSensorModel::imageLineToDeburstLine(lines,imageLine,deburstLine);
}

void SarSensorModelAdapter::DeburstLineToImageLine(const std::vector<std::pair<unsigned long,unsigned long> >& lines, unsigned long deburstLine, unsigned long & imageLine)
{
  ossimplugins::ossimSarSensorModel::deburstLineToImageLine(lines,deburstLine,imageLine);
}

} // namespace otb
<|endoftext|>


<commit_before>#include <turbo/container/bitwise_trie.hpp>
#include <turbo/container/bitwise_trie.hxx>
#include <chrono>
#include <map>
#include <random>
#include <gtest/gtest.h>
#include <turbo/memory/pool.hpp>
#include <turbo/memory/pool.hxx>

namespace turbo {
namespace container {

template <class key_t, class value_t, class allocator_t>
class bitwise_trie_tester
{
public:
    typedef bitwise_trie<key_t, value_t, allocator_t> trie_type;
    typedef typename trie_type::leaf leaf;
    typedef typename trie_type::branch branch;
    bitwise_trie_tester(trie_type& trie)
	:
	    trie_(trie)
    { }
    inline typename trie_type::branch* get_root()
    {
	return trie_.root_;
    }
    inline typename trie_type::branch* min()
    {
	return trie_.min();
    }
    inline typename trie_type::branch* max()
    {
	return trie_.max();
    }
    static inline typename trie_type::key_type get_prefix(typename trie_type::key_type key)
    {
	return trie_type::get_prefix(key);
    }
private:
    trie_type& trie_;
};

} // namespace container
} // namespace turbo

namespace tco = turbo::container;
namespace tme = turbo::memory;

TEST(bitwise_trie_test, empty_trie)
{
    typedef tco::bitwise_trie<std::uint32_t, std::string, tme::pool> string_map;
    tme::pool allocator1(8U, { {string_map::node_sizes[0], 8U}, {string_map::node_sizes[1], 8U} });
    string_map map1(allocator1);
    EXPECT_EQ(0U, map1.size()) << "Size of an empty trie is not 0";
    EXPECT_EQ(map1.cend(), map1.cbegin()) << "The cbegin and cend iterators of an empty trie are not equal";
    EXPECT_EQ(map1.crend(), map1.crbegin()) << "The crbegin and crend iterators of an empty trie are not equal";
}

TEST(bitwise_trie_test, emplace_basic)
{
    typedef tco::bitwise_trie<std::uint8_t, std::string, tme::pool> string_map;
    tme::pool allocator1(8U, { {string_map::node_sizes[0], 8U}, {string_map::node_sizes[1], 8U} });
    string_map map1(allocator1);
    auto result1 = map1.emplace(64U, "bar");
    EXPECT_TRUE(std::get<1>(result1)) << "Emplace failed";
    EXPECT_NE(map1.end(), std::get<0>(result1)) << "Emplace failed";
    EXPECT_EQ(std::string("bar"), *std::get<0>(result1)) << "Emplace failed";
    EXPECT_EQ(1U, map1.size()) << "Size of trie after 1 emplace is not 1";
    EXPECT_NE(map1.cend(), map1.find(64U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("bar"), *map1.find(64U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("bar"), *map1.cbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(64U, map1.cbegin().get_key()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(std::string("bar"), *map1.crbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(64U, map1.crbegin().get_key()) << "Just emplaced key & value is not ordered";
    auto result2 = map1.emplace(32U, "foo");
    EXPECT_TRUE(std::get<1>(result2)) << "Emplace failed";
    EXPECT_NE(map1.end(), std::get<0>(result2)) << "Emplace failed";
    EXPECT_EQ(std::string("foo"), *std::get<0>(result2)) << "Emplace failed";
    EXPECT_EQ(2U, map1.size()) << "Size of trie after 2 emplace is not 2";
    EXPECT_NE(map1.cend(), map1.find(32U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("foo"), *map1.find(32U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("foo"), *map1.cbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(32U, map1.cbegin().get_key()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(std::string("bar"), *map1.crbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(64U, map1.crbegin().get_key()) << "Just emplaced key & value is not ordered";
    auto result3 = map1.emplace(128U, "blah");
    EXPECT_TRUE(std::get<1>(result3)) << "Emplace failed";
    EXPECT_NE(map1.end(), std::get<0>(result3)) << "Emplace failed";
    EXPECT_EQ(std::string("blah"), *std::get<0>(result3)) << "Emplace failed";
    EXPECT_EQ(3U, map1.size()) << "Size of trie after 3 emplace is not 3";
    EXPECT_NE(map1.cend(), map1.find(128U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("blah"), *map1.find(128U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("foo"), *map1.cbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(32U, map1.cbegin().get_key()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(std::string("blah"), *map1.crbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(128U, map1.crbegin().get_key()) << "Just emplaced key & value is not ordered";
    auto iter1 = map1.cbegin();
    EXPECT_EQ(std::string("foo"), *iter1) << "Just emplaced key & value is not ordered";
    ++iter1;
    EXPECT_EQ(std::string("bar"), *iter1) << "Just emplaced key & value is not ordered";
    ++iter1;
    EXPECT_EQ(std::string("blah"), *iter1) << "Just emplaced key & value is not ordered";
    auto iter2 = map1.crbegin();
    EXPECT_EQ(std::string("blah"), *iter2) << "Just emplaced key & value is not ordered";
    ++iter2;
    EXPECT_EQ(std::string("bar"), *iter2) << "Just emplaced key & value is not ordered";
    ++iter2;
    EXPECT_EQ(std::string("foo"), *iter2) << "Just emplaced key & value is not ordered";
}

class bitwise_trie_perf_test : public ::testing::Test
{
public:
    typedef tco::bitwise_trie<std::uint64_t, std::uint64_t, tme::pool> uint_map;
    bitwise_trie_perf_test()
	:
	    allocator1(8U, { {uint_map::node_sizes[0], 1U << 15U}, {uint_map::node_sizes[1], (1U << 16U) - 1U} })
    { }
protected:
    tme::pool allocator1;
};

TEST_F(bitwise_trie_perf_test, perf_test_trie_emplace)
{
    uint_map map1(allocator1);
    std::mt19937 device(std::chrono::system_clock::now().time_since_epoch().count());
    for (std::uint64_t counter = 0U; counter <= std::numeric_limits<std::uint16_t>::max(); ++counter)
    {
	std::uint64_t value = device() >> 16U;
	map1.emplace(value, value);
    }
}

TEST_F(bitwise_trie_perf_test, perf_test_map_emplace)
{
    std::map<std::uint64_t, std::uint64_t> map1;
    std::mt19937 device(std::chrono::system_clock::now().time_since_epoch().count());
    for (std::uint64_t counter = 0U; counter <= std::numeric_limits<std::uint16_t>::max(); ++counter)
    {
	std::uint64_t value = device() >> 16U;
	map1.emplace(value, value);
    }
}
<commit_msg>added more test cases<commit_after>#include <turbo/container/bitwise_trie.hpp>
#include <turbo/container/bitwise_trie.hxx>
#include <chrono>
#include <map>
#include <random>
#include <gtest/gtest.h>
#include <turbo/memory/pool.hpp>
#include <turbo/memory/pool.hxx>

namespace turbo {
namespace container {

template <class key_t, class value_t, class allocator_t>
class bitwise_trie_tester
{
public:
    typedef bitwise_trie<key_t, value_t, allocator_t> trie_type;
    typedef typename trie_type::leaf leaf;
    typedef typename trie_type::branch branch;
    bitwise_trie_tester(trie_type& trie)
	:
	    trie_(trie)
    { }
    inline typename trie_type::branch* get_root()
    {
	return trie_.root_;
    }
    inline typename trie_type::branch* min()
    {
	return trie_.min();
    }
    inline typename trie_type::branch* max()
    {
	return trie_.max();
    }
    static inline typename trie_type::key_type get_prefix(typename trie_type::key_type key)
    {
	return trie_type::get_prefix(key);
    }
private:
    trie_type& trie_;
};

} // namespace container
} // namespace turbo

namespace tco = turbo::container;
namespace tme = turbo::memory;

TEST(bitwise_trie_test, empty_trie)
{
    typedef tco::bitwise_trie<std::uint32_t, std::string, tme::pool> string_map;
    tme::pool allocator1(8U, { {string_map::node_sizes[0], 8U}, {string_map::node_sizes[1], 8U} });
    string_map map1(allocator1);
    EXPECT_EQ(0U, map1.size()) << "Size of an empty trie is not 0";
    EXPECT_EQ(map1.cend(), map1.cbegin()) << "The cbegin and cend iterators of an empty trie are not equal";
    EXPECT_EQ(map1.crend(), map1.crbegin()) << "The crbegin and crend iterators of an empty trie are not equal";
}

TEST(bitwise_trie_test, emplace_invalid)
{
    typedef tco::bitwise_trie<std::uint8_t, std::string, tme::pool> string_map;
    tme::pool allocator1(8U, { {string_map::node_sizes[0], 8U}, {string_map::node_sizes[1], 8U} });
    string_map map1(allocator1);
    auto result1 = map1.emplace(64U, "bar");
    EXPECT_TRUE(std::get<1>(result1)) << "Emplace failed";
    EXPECT_NE(map1.end(), std::get<0>(result1)) << "Emplace failed";
    EXPECT_EQ(std::string("bar"), *std::get<0>(result1)) << "Emplace failed";
    EXPECT_EQ(1U, map1.size()) << "Size of trie after 1 emplace is not 1";
    auto result2 = map1.emplace(64U, "foo");
    EXPECT_FALSE(std::get<1>(result2)) << "Emplace of duplicate succeeded";
    EXPECT_NE(map1.end(), std::get<0>(result2)) << "Emplace of duplicate did not return an iterator to the existing value";
    EXPECT_EQ(std::string("bar"), *std::get<0>(result2)) << "Emplace of duplicate overwrote the existing value";
    EXPECT_EQ(1U, map1.size()) << "Emplace of duplicate increased the size of the trie";
}

TEST(bitwise_trie_test, emplace_basic)
{
    typedef tco::bitwise_trie<std::uint8_t, std::string, tme::pool> string_map;
    tme::pool allocator1(8U, { {string_map::node_sizes[0], 8U}, {string_map::node_sizes[1], 8U} });
    string_map map1(allocator1);
    auto result1 = map1.emplace(64U, "bar");
    EXPECT_TRUE(std::get<1>(result1)) << "Emplace failed";
    EXPECT_NE(map1.end(), std::get<0>(result1)) << "Emplace failed";
    EXPECT_EQ(std::string("bar"), *std::get<0>(result1)) << "Emplace failed";
    EXPECT_EQ(1U, map1.size()) << "Size of trie after 1 emplace is not 1";
    EXPECT_NE(map1.cend(), map1.find(64U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("bar"), *map1.find(64U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("bar"), *map1.cbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(64U, map1.cbegin().get_key()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(std::string("bar"), *map1.crbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(64U, map1.crbegin().get_key()) << "Just emplaced key & value is not ordered";
    auto result2 = map1.emplace(32U, "foo");
    EXPECT_TRUE(std::get<1>(result2)) << "Emplace failed";
    EXPECT_NE(map1.end(), std::get<0>(result2)) << "Emplace failed";
    EXPECT_EQ(std::string("foo"), *std::get<0>(result2)) << "Emplace failed";
    EXPECT_EQ(2U, map1.size()) << "Size of trie after 2 emplace is not 2";
    EXPECT_NE(map1.cend(), map1.find(32U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("foo"), *map1.find(32U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("foo"), *map1.cbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(32U, map1.cbegin().get_key()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(std::string("bar"), *map1.crbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(64U, map1.crbegin().get_key()) << "Just emplaced key & value is not ordered";
    auto result3 = map1.emplace(128U, "blah");
    EXPECT_TRUE(std::get<1>(result3)) << "Emplace failed";
    EXPECT_NE(map1.end(), std::get<0>(result3)) << "Emplace failed";
    EXPECT_EQ(std::string("blah"), *std::get<0>(result3)) << "Emplace failed";
    EXPECT_EQ(3U, map1.size()) << "Size of trie after 3 emplace is not 3";
    EXPECT_NE(map1.cend(), map1.find(128U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("blah"), *map1.find(128U)) << "Could not find just emplaced key & value";
    EXPECT_EQ(std::string("foo"), *map1.cbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(32U, map1.cbegin().get_key()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(std::string("blah"), *map1.crbegin()) << "Just emplaced key & value is not ordered";
    EXPECT_EQ(128U, map1.crbegin().get_key()) << "Just emplaced key & value is not ordered";
    auto iter1 = map1.cbegin();
    EXPECT_EQ(std::string("foo"), *iter1) << "Just emplaced key & value is not ordered";
    ++iter1;
    EXPECT_EQ(std::string("bar"), *iter1) << "Just emplaced key & value is not ordered";
    ++iter1;
    EXPECT_EQ(std::string("blah"), *iter1) << "Just emplaced key & value is not ordered";
    auto iter2 = map1.crbegin();
    EXPECT_EQ(std::string("blah"), *iter2) << "Just emplaced key & value is not ordered";
    ++iter2;
    EXPECT_EQ(std::string("bar"), *iter2) << "Just emplaced key & value is not ordered";
    ++iter2;
    EXPECT_EQ(std::string("foo"), *iter2) << "Just emplaced key & value is not ordered";
}

TEST(bitwise_trie_test, begin_basic)
{
    typedef tco::bitwise_trie<std::uint8_t, std::string, tme::pool> string_map;
    tme::pool allocator1(8U, { {string_map::node_sizes[0], 8U}, {string_map::node_sizes[1], 8U} });
    string_map map1(allocator1);
    map1.emplace(255U, "foo");
    auto iter1a = map1.cbegin();
    EXPECT_NE(map1.cend(), iter1a) << "Could not first value";
    EXPECT_EQ(std::string("foo"), *iter1a) << "Could not first value";
    auto iter1b = map1.crbegin();
    EXPECT_NE(map1.crend(), iter1b) << "Could not first value";
    EXPECT_EQ(std::string("foo"), *iter1b) << "Could not first value";
    string_map map2(allocator1);
    map2.emplace(0U, "foo");
    auto iter2a = map2.cbegin();
    EXPECT_NE(map2.cend(), iter2a) << "Could not first value";
    EXPECT_EQ(std::string("foo"), *iter2a) << "Could not first value";
    auto iter2b = map2.crbegin();
    EXPECT_NE(map2.crend(), iter2b) << "Could not first value";
    EXPECT_EQ(std::string("foo"), *iter2b) << "Could not first value";
}

TEST(bitwise_trie_test, successor_basic)
{
    typedef tco::bitwise_trie<std::uint8_t, std::string, tme::pool> string_map;
    tme::pool allocator1(8U, { {string_map::node_sizes[0], 8U}, {string_map::node_sizes[1], 8U} });
    string_map map1(allocator1);
    map1.emplace(0U, "foo");
    map1.emplace(128U, "bar");
    map1.emplace(255U, "blah");
    auto iter1 = map1.cbegin();
    ++iter1;
    EXPECT_NE(map1.cend(), iter1) << "Could not find successor";
    EXPECT_EQ(std::string("bar"), *iter1) << "Could not find successor";
    ++iter1;
    EXPECT_NE(map1.cend(), iter1) << "Could not find successor";
    EXPECT_EQ(std::string("blah"), *iter1) << "Could not find successor";
    ++iter1;
    EXPECT_EQ(map1.cend(), iter1) << "Successor of last vaue is not the end iterator";
    string_map map2(allocator1);
    map2.emplace(126U, "foo");
    map2.emplace(127U, "bar");
    map2.emplace(128U, "blah");
    auto iter2 = map2.cbegin();
    ++iter2;
    EXPECT_NE(map2.cend(), iter2) << "Could not find successor";
    EXPECT_EQ(std::string("bar"), *iter2) << "Could not find successor";
    ++iter2;
    EXPECT_NE(map2.cend(), iter2) << "Could not find successor";
    EXPECT_EQ(std::string("blah"), *iter2) << "Could not find successor";
    ++iter2;
    EXPECT_EQ(map2.cend(), iter2) << "Successor of last vaue is not the end iterator";
}

TEST(bitwise_trie_test, predecessor_basic)
{
    typedef tco::bitwise_trie<std::uint8_t, std::string, tme::pool> string_map;
    tme::pool allocator1(8U, { {string_map::node_sizes[0], 8U}, {string_map::node_sizes[1], 8U} });
    string_map map1(allocator1);
    map1.emplace(0U, "foo");
    map1.emplace(128U, "bar");
    map1.emplace(255U, "blah");
    auto iter1 = map1.crbegin();
    ++iter1;
    EXPECT_NE(map1.crend(), iter1) << "Could not find successor";
    EXPECT_EQ(std::string("bar"), *iter1) << "Could not find successor";
    ++iter1;
    EXPECT_NE(map1.crend(), iter1) << "Could not find successor";
    EXPECT_EQ(std::string("foo"), *iter1) << "Could not find successor";
    ++iter1;
    EXPECT_EQ(map1.crend(), iter1) << "Successor of last vaue is not the end iterator";
    string_map map2(allocator1);
    map2.emplace(126U, "foo");
    map2.emplace(127U, "bar");
    map2.emplace(128U, "blah");
    auto iter2 = map2.crbegin();
    ++iter2;
    EXPECT_NE(map2.crend(), iter2) << "Could not find successor";
    EXPECT_EQ(std::string("bar"), *iter2) << "Could not find successor";
    ++iter2;
    EXPECT_NE(map2.crend(), iter2) << "Could not find successor";
    EXPECT_EQ(std::string("foo"), *iter2) << "Could not find successor";
    ++iter2;
    EXPECT_EQ(map2.crend(), iter2) << "Successor of last vaue is not the end iterator";
}

class bitwise_trie_perf_test : public ::testing::Test
{
public:
    typedef tco::bitwise_trie<std::uint64_t, std::uint64_t, tme::pool> uint_map;
    bitwise_trie_perf_test()
	:
	    allocator1(8U, { {uint_map::node_sizes[0], 1U << 15U}, {uint_map::node_sizes[1], (1U << 16U) - 1U} })
    { }
protected:
    tme::pool allocator1;
};

TEST_F(bitwise_trie_perf_test, perf_test_trie_emplace)
{
    uint_map map1(allocator1);
    std::mt19937 device(std::chrono::system_clock::now().time_since_epoch().count());
    for (std::uint64_t counter = 0U; counter <= std::numeric_limits<std::uint16_t>::max(); ++counter)
    {
	std::uint64_t value = device() >> 16U;
	map1.emplace(value, value);
    }
}

TEST_F(bitwise_trie_perf_test, perf_test_map_emplace)
{
    std::map<std::uint64_t, std::uint64_t> map1;
    std::mt19937 device(std::chrono::system_clock::now().time_since_epoch().count());
    for (std::uint64_t counter = 0U; counter <= std::numeric_limits<std::uint16_t>::max(); ++counter)
    {
	std::uint64_t value = device() >> 16U;
	map1.emplace(value, value);
    }
}
<|endoftext|>


<commit_before>#ifndef MJOLNIR_READ_OBSERVER
#define MJOLNIR_READ_OBSERVER
#include <extlib/toml/toml.hpp>
#include <mjolnir/core/Observer.hpp>

namespace mjolnir
{

template<typename traitsT>
Observer<traitsT>
read_observer(const toml::Table& data)
{
    const auto& general = data.at("general").cast<toml::value_t::Table>();
    const std::string path  = toml::get<std::string>(general.at("output_path"));
    const std::string fname = toml::get<std::string>(general.at("file_name"));

    const auto& simulator = data.at("simulator").cast<toml::value_t::Table>();
    const std::size_t interval =
        toml::get<std::size_t>(simulator.at("observe_interval"));

    return Observer<traitsT>(path + fname + std::string(".xyz"),
                             path + fname + std::string(".ene"),
                             interval);
}

}
#endif// MJOLNIR_READ_OBSERVER
<commit_msg>use detail::value_at in read_observer<commit_after>#ifndef MJOLNIR_READ_OBSERVER
#define MJOLNIR_READ_OBSERVER
#include <extlib/toml/toml.hpp>
#include <mjolnir/core/Observer.hpp>
#include <mjolnir/input/get_toml_value.hpp>

namespace mjolnir
{

template<typename traitsT>
Observer<traitsT>
read_observer(const toml::Table& data)
{
    const auto& general = detail::value_at(data, "general", "<root>"
            ).cast<toml::value_t::Table>();
    const std::string path  = toml::get<std::string>(
            detail::value_at(general, "output_path", "[general]"));
    const std::string fname = toml::get<std::string>(
            detail::value_at(general, "file_name", "[general]"));

    const auto& simulator = detail::value_at(data, "simulator", "<root>"
            ).cast<toml::value_t::Table>();
    const std::size_t interval = toml::get<std::size_t>(
            detail::value_at(simulator, "observe_interval", "[simulator]"));

    return Observer<traitsT>(path + fname + std::string(".xyz"),
                             path + fname + std::string(".ene"),
                             interval);
}

}
#endif// MJOLNIR_READ_OBSERVER
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE "test_read_harmonic_potential"

#ifdef BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#else
#include <boost/test/included/unit_test.hpp>
#endif
#include <mjolnir/input/read_local_potential.hpp>
#include <mjolnir/input/read_global_potential.hpp>
#include <mjolnir/input/read_external_potential.hpp>
#include <tuple>

using test_types = std::tuple<double, float>;

constexpr inline float  tolerance_value(float)  noexcept {return 1e-4;}
constexpr inline double tolerance_value(double) noexcept {return 1e-8;}

template<typename Real>
decltype(boost::test_tools::tolerance(std::declval<Real>()))
tolerance() {return boost::test_tools::tolerance(tolerance_value(Real()));}

BOOST_AUTO_TEST_CASE_TEMPLATE(read_index_offset_local_potential, T, test_types)
{
    mjolnir::LoggerManager::set_default_logger("test_read_index_offset.log");

    using real_type = T;
    {
        using namespace toml::literals;
        const auto v = u8R"(
            parameters = [
                {indices = [1, 2],              k = 3.14, v0 = 2.71},
                {indices = [1, 2], offset =  1, k = 3.14, v0 = 2.71},
                {indices = [1, 2], offset = -1, k = 3.14, v0 = 2.71},
            ]
        )"_toml;

        const auto g = mjolnir::read_local_potential<2,
            mjolnir::HarmonicPotential<real_type>>(v);

        BOOST_TEST(g.size() == 3u);
        BOOST_TEST(g.at(0).first[0] == 1u);
        BOOST_TEST(g.at(0).first[1] == 2u);

        BOOST_TEST(g.at(1).first[0] == 2u);
        BOOST_TEST(g.at(1).first[1] == 3u);

        BOOST_TEST(g.at(2).first[0] == 0u);
        BOOST_TEST(g.at(2).first[1] == 1u);

        BOOST_TEST(g.at(0).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(0).second.v0() == real_type(2.71));
        BOOST_TEST(g.at(1).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(1).second.v0() == real_type(2.71));
        BOOST_TEST(g.at(2).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(2).second.v0() == real_type(2.71));
    }
}

BOOST_AUTO_TEST_CASE_TEMPLATE(read_index_offset_list_local_potential, T, test_types)
{
    mjolnir::LoggerManager::set_default_logger("test_read_index_offset.log");

    using real_type = T;
    {
        using namespace toml::literals;
        const auto v = u8R"(
            parameters = [
                {indices = [1, 2],                    k = 3.14, v0 = 2.71},
                {indices = [1, 2], offset =  [1, -1], k = 3.14, v0 = 2.71},
                {indices = [1, 2], offset =  [-1, 1], k = 3.14, v0 = 2.71},
            ]
        )"_toml;

        const auto g = mjolnir::read_local_potential<2,
            mjolnir::HarmonicPotential<real_type>>(v);

        BOOST_TEST(g.size() == 3u);
        BOOST_TEST(g.at(0).first[0] == 1u);
        BOOST_TEST(g.at(0).first[1] == 2u);

        BOOST_TEST(g.at(1).first[0] == 2u);
        BOOST_TEST(g.at(1).first[1] == 1u);

        BOOST_TEST(g.at(2).first[0] == 0u);
        BOOST_TEST(g.at(2).first[1] == 3u);

        BOOST_TEST(g.at(0).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(0).second.v0() == real_type(2.71));
        BOOST_TEST(g.at(1).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(1).second.v0() == real_type(2.71));
        BOOST_TEST(g.at(2).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(2).second.v0() == real_type(2.71));
    }
}
BOOST_AUTO_TEST_CASE_TEMPLATE(read_index_offset_global_potential, T, test_types)
{
    mjolnir::LoggerManager::set_default_logger("test_read_index_offset.log");

    using real_type = T;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const auto v = u8R"(
            interaction = "Pair"
            potential   = "LennardJones"
            spatial_partition.type  = "Naive"
            parameters = [
                {index =   0,               sigma =   2.0, epsilon = 1.5},
                {index =   5, offset =   1, sigma =   5.0, epsilon = 0.5},
                {index =  10, offset =  -1, sigma =   7.0, epsilon = 0.7},
                {index = 100, offset = 100, sigma = 100.0, epsilon = 0.1},
            ]
        )"_toml;

        const auto parameter_list = mjolnir::read_lennard_jones_potential<traits_type>(v);

        BOOST_TEST(!parameter_list.exclusion_list().is_ignored_molecule(0, 0));
        BOOST_TEST(!parameter_list.exclusion_list().is_ignored_molecule(0, 1));
        BOOST_TEST(!parameter_list.exclusion_list().is_ignored_molecule(1, 1));

        BOOST_TEST(parameter_list.participants().size() ==   4u);
        BOOST_TEST(parameter_list.participants().at(0)  ==   0u);
        BOOST_TEST(parameter_list.participants().at(1)  ==   6u);
        BOOST_TEST(parameter_list.participants().at(2)  ==   9u);
        BOOST_TEST(parameter_list.participants().at(3)  == 200u);

        const auto& lorentz_bertherot = dynamic_cast<
            mjolnir::LorentzBerthelotRule<traits_type, mjolnir::LennardJonesPotential<real_type>> const&>(
                parameter_list.cref());

        BOOST_TEST(lorentz_bertherot.parameters().at(  0).first  == real_type(  2.0), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(  6).first  == real_type(  5.0), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(  9).first  == real_type(  7.0), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(200).first  == real_type(100.0), tolerance<real_type>());

        BOOST_TEST(lorentz_bertherot.parameters().at(  0).second == real_type(1.5), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(  6).second == real_type(0.5), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(  9).second == real_type(0.7), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(200).second == real_type(0.1), tolerance<real_type>());
    }
}

BOOST_AUTO_TEST_CASE_TEMPLATE(read_index_offset_external_potential, T, test_types)
{
    mjolnir::LoggerManager::set_default_logger("test_read_index_offset.log");

    using real_type = T;
    using real_type = T;
    {
        using namespace toml::literals;
        const toml::value v = u8R"(
            interaction    = "Distance"
            potential      = "LennardJonesWall"
            shape.name     = "AxisAlignedPlane"
            shape.axis     = "+X"
            shape.position = 1.0
            shape.margin   = 0.5
            cutoff         = 3.14
            parameters     = [
                {index =  0,               sigma = 1.0, epsilon = 1.0},
                {index =  2, offset =   1, sigma = 2.0, epsilon = 2.0},
                {index =  9, offset =  -1, sigma = 3.0, epsilon = 3.0},
                {index = 10, offset =  10, sigma = 4.0, epsilon = 4.0},
            ]
        )"_toml;

        const auto g = mjolnir::read_lennard_jones_wall_potential<real_type>(v);

        BOOST_TEST(g.participants().size() ==  4u);
        BOOST_TEST(g.participants().at(0)  ==  0u);
        BOOST_TEST(g.participants().at(1)  ==  3u);
        BOOST_TEST(g.participants().at(2)  ==  8u);
        BOOST_TEST(g.participants().at(3)  == 20u);

        BOOST_TEST(g.parameters().at( 0).first  == real_type(1.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 3).first  == real_type(2.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 8).first  == real_type(3.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at(20).first  == real_type(4.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 0).second == real_type(1.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 3).second == real_type(2.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 8).second == real_type(3.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at(20).second == real_type(4.0), tolerance<real_type>());
        BOOST_TEST(g.cutoff() == real_type(3.14), tolerance<real_type>());
    }
}
<commit_msg>feat: update test_read_index_offset<commit_after>#define BOOST_TEST_MODULE "test_read_harmonic_potential"

#ifdef BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#else
#include <boost/test/included/unit_test.hpp>
#endif
#include <mjolnir/input/read_local_potential.hpp>
#include <mjolnir/input/read_global_potential.hpp>
#include <mjolnir/input/read_external_potential.hpp>
#include <tuple>

using test_types = std::tuple<double, float>;

constexpr inline float  tolerance_value(float)  noexcept {return 1e-4;}
constexpr inline double tolerance_value(double) noexcept {return 1e-8;}

template<typename Real>
decltype(boost::test_tools::tolerance(std::declval<Real>()))
tolerance() {return boost::test_tools::tolerance(tolerance_value(Real()));}

BOOST_AUTO_TEST_CASE_TEMPLATE(read_index_offset_local_potential, T, test_types)
{
    mjolnir::LoggerManager::set_default_logger("test_read_index_offset.log");

    using real_type = T;
    {
        using namespace toml::literals;
        const auto v = u8R"(
            parameters = [
                {indices = [1, 2],              k = 3.14, v0 = 2.71},
                {indices = [1, 2], offset =  1, k = 3.14, v0 = 2.71},
                {indices = [1, 2], offset = -1, k = 3.14, v0 = 2.71},
            ]
        )"_toml;

        const auto g = mjolnir::read_local_potential<2,
            mjolnir::HarmonicPotential<real_type>>(v);

        BOOST_TEST(g.size() == 3u);
        BOOST_TEST(g.at(0).first[0] == 1u);
        BOOST_TEST(g.at(0).first[1] == 2u);

        BOOST_TEST(g.at(1).first[0] == 2u);
        BOOST_TEST(g.at(1).first[1] == 3u);

        BOOST_TEST(g.at(2).first[0] == 0u);
        BOOST_TEST(g.at(2).first[1] == 1u);

        BOOST_TEST(g.at(0).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(0).second.v0() == real_type(2.71));
        BOOST_TEST(g.at(1).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(1).second.v0() == real_type(2.71));
        BOOST_TEST(g.at(2).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(2).second.v0() == real_type(2.71));
    }
}

BOOST_AUTO_TEST_CASE_TEMPLATE(read_index_offset_list_local_potential, T, test_types)
{
    mjolnir::LoggerManager::set_default_logger("test_read_index_offset.log");

    using real_type = T;
    {
        using namespace toml::literals;
        const auto v = u8R"(
            parameters = [
                {indices = [1, 2],                    k = 3.14, v0 = 2.71},
                {indices = [1, 2], offset =  [1, -1], k = 3.14, v0 = 2.71},
                {indices = [1, 2], offset =  [-1, 1], k = 3.14, v0 = 2.71},
            ]
        )"_toml;

        const auto g = mjolnir::read_local_potential<2,
            mjolnir::HarmonicPotential<real_type>>(v);

        BOOST_TEST(g.size() == 3u);
        BOOST_TEST(g.at(0).first[0] == 1u);
        BOOST_TEST(g.at(0).first[1] == 2u);

        BOOST_TEST(g.at(1).first[0] == 2u);
        BOOST_TEST(g.at(1).first[1] == 1u);

        BOOST_TEST(g.at(2).first[0] == 0u);
        BOOST_TEST(g.at(2).first[1] == 3u);

        BOOST_TEST(g.at(0).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(0).second.v0() == real_type(2.71));
        BOOST_TEST(g.at(1).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(1).second.v0() == real_type(2.71));
        BOOST_TEST(g.at(2).second.k()  == real_type(3.14));
        BOOST_TEST(g.at(2).second.v0() == real_type(2.71));
    }
}
BOOST_AUTO_TEST_CASE_TEMPLATE(read_index_offset_global_potential, T, test_types)
{
    mjolnir::LoggerManager::set_default_logger("test_read_index_offset.log");

    using real_type = T;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const auto v = u8R"(
            interaction = "Pair"
            potential   = "LennardJones"
            spatial_partition.type  = "Naive"
            parameters = [
                {index =   0,               sigma =   2.0, epsilon = 1.5},
                {index =   5, offset =   1, sigma =   5.0, epsilon = 0.5},
                {index =  10, offset =  -1, sigma =   7.0, epsilon = 0.7},
                {index = 100, offset = 100, sigma = 100.0, epsilon = 0.1},
            ]
        )"_toml;

        const auto parameter_list = mjolnir::read_lennard_jones_potential<traits_type>(v).second;

        BOOST_TEST(!parameter_list.exclusion_list().is_ignored_molecule(0, 0));
        BOOST_TEST(!parameter_list.exclusion_list().is_ignored_molecule(0, 1));
        BOOST_TEST(!parameter_list.exclusion_list().is_ignored_molecule(1, 1));

        BOOST_TEST(parameter_list.participants().size() ==   4u);
        BOOST_TEST(parameter_list.participants().at(0)  ==   0u);
        BOOST_TEST(parameter_list.participants().at(1)  ==   6u);
        BOOST_TEST(parameter_list.participants().at(2)  ==   9u);
        BOOST_TEST(parameter_list.participants().at(3)  == 200u);

        const auto& lorentz_bertherot = dynamic_cast<
            mjolnir::LorentzBerthelotRule<traits_type, mjolnir::LennardJonesPotential<real_type>> const&>(
                parameter_list.cref());

        BOOST_TEST(lorentz_bertherot.parameters().at(  0).sigma  == real_type(  2.0), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(  6).sigma  == real_type(  5.0), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(  9).sigma  == real_type(  7.0), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(200).sigma  == real_type(100.0), tolerance<real_type>());

        BOOST_TEST(lorentz_bertherot.parameters().at(  0).epsilon == real_type(1.5), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(  6).epsilon == real_type(0.5), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(  9).epsilon == real_type(0.7), tolerance<real_type>());
        BOOST_TEST(lorentz_bertherot.parameters().at(200).epsilon == real_type(0.1), tolerance<real_type>());
    }
}

BOOST_AUTO_TEST_CASE_TEMPLATE(read_index_offset_external_potential, T, test_types)
{
    mjolnir::LoggerManager::set_default_logger("test_read_index_offset.log");

    using real_type = T;
    using real_type = T;
    {
        using namespace toml::literals;
        const toml::value v = u8R"(
            interaction    = "Distance"
            potential      = "LennardJonesWall"
            shape.name     = "AxisAlignedPlane"
            shape.axis     = "+X"
            shape.position = 1.0
            shape.margin   = 0.5
            cutoff         = 3.14
            parameters     = [
                {index =  0,               sigma = 1.0, epsilon = 1.0},
                {index =  2, offset =   1, sigma = 2.0, epsilon = 2.0},
                {index =  9, offset =  -1, sigma = 3.0, epsilon = 3.0},
                {index = 10, offset =  10, sigma = 4.0, epsilon = 4.0},
            ]
        )"_toml;

        const auto g = mjolnir::read_lennard_jones_wall_potential<real_type>(v);

        BOOST_TEST(g.participants().size() ==  4u);
        BOOST_TEST(g.participants().at(0)  ==  0u);
        BOOST_TEST(g.participants().at(1)  ==  3u);
        BOOST_TEST(g.participants().at(2)  ==  8u);
        BOOST_TEST(g.participants().at(3)  == 20u);

        BOOST_TEST(g.parameters().at( 0).first  == real_type(1.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 3).first  == real_type(2.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 8).first  == real_type(3.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at(20).first  == real_type(4.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 0).second == real_type(1.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 3).second == real_type(2.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at( 8).second == real_type(3.0), tolerance<real_type>());
        BOOST_TEST(g.parameters().at(20).second == real_type(4.0), tolerance<real_type>());
        BOOST_TEST(g.cutoff() == real_type(3.14), tolerance<real_type>());
    }
}
<|endoftext|>


<commit_before>/* file_functions.cc
   Jeremy Barnes, 14 March 2005
   Copyright (c) 2005 Jeremy Barnes.  All rights reserved.

   This file is part of "Jeremy's Machine Learning Library", copyright (c)
   1999-2005 Jeremy Barnes.

   This program is available under the GNU General Public License, the terms
   of which are given by the file "license.txt" in the top level directory of
   the source code distribution.  If this file is missing, you have no right
   to use the program; please contact the author.

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

   ---

   Functions to deal with files.
*/

#include "file_functions.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "string_functions.h"
#include "jml/arch/exception.h"
#include "jml/arch/spinlock.h"
#include <iostream>
#include <boost/weak_ptr.hpp>
#include <map>
#include <grp.h>
#include <exception>
#include "guard.h"
#include <mutex>

using namespace std;

namespace ML {

size_t get_file_size(int fd)
{
    struct stat stats;
    int result = fstat(fd, &stats);
    if (result != 0)
        throw Exception("fstat: " + string(strerror(errno)));
    return stats.st_size;
}

size_t get_file_size(const std::string & filename)
{
    struct stat stats;
    int result = stat(filename.c_str(), &stats);
    if (result != 0)
        throw Exception("stat: " + string(strerror(errno)));
    return stats.st_size;
}

std::string get_link_target(const std::string & link)
{
    /* Interface to the readlink call */
    size_t bufsize = 1024;

    /* Loop over, making the buffer successively larger if it is too small. */
    while (true) {  // break in loop
        char buf[bufsize];
        int res = readlink(link.c_str(), buf, bufsize);
        if (res == -1)
            throw Exception(errno, "readlink", "get_link_name()");
        if (res == bufsize) {
            bufsize *= 2;
            continue;
        }
        buf[res] = 0;
        return buf;
    }
}

std::string get_name_from_fd(int fd)
{
    string fname = format("/proc/self/fd/%d", fd);
    return get_link_target(fname);
}

inode_type get_inode(const std::string & filename)
{
    struct stat st;

    int res = stat(filename.c_str(), &st);

    if (res != 0)
        throw Exception(errno, "fstat", "get_inode()");

    return make_pair(st.st_dev, st.st_ino);
}

inode_type get_inode(int fd)
{
    struct stat st;

    int res = fstat(fd, &st);

    if (res != 0)
        throw Exception(errno, "fstat", "get_inode()");

    return make_pair(st.st_dev, st.st_ino);
}

void delete_file(const std::string & filename)
{
    int res = unlink(filename.c_str());
    if (res != 0)
        throw Exception(errno, "couldn't delete file " + filename, "unlink");
}

void set_file_flag(int fd, int newFlag)
{
    int oldFlags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, oldFlags | newFlag);
}

void unset_file_flag(int fd, int oldFlag)
{
    int oldFlags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, oldFlags & ~oldFlag);
}

bool is_file_flag_set(int fd, int flag)
{
    int oldFlags = fcntl(fd, F_GETFL, 0);
    return ((oldFlags & flag) == flag);
}

/** Does the file exist? */
bool fileExists(const std::string & filename)
{
    struct stat stats;
    int res = stat(filename.c_str(), &stats);
    if (res == -1)
        return false;  // no chunks
    return true;
}

void set_permissions(std::string filename,
                     const std::string & perms,
                     const std::string & group)
{
    if (filename.find("ipc://") == 0)
        filename = string(filename, 6);

    char * endptr;
    if (perms != "") {
        int mode = strtol(perms.c_str(), &endptr, 8);
        if (*endptr != '\0')
            throw Exception(errno, "parsing permission modes %s",
                            perms.c_str());

        cerr << "setting permissions of " << filename << " to " << perms
             << "(" << mode << ")" << endl;

        int res = chmod(filename.c_str(), mode);
        if (res == -1)
            throw Exception(errno, "chmod on %s in setPermissions");
    }

    if (group != "") {
        int groupNum = strtol(group.c_str(), &endptr, 10);
        if (*endptr != '\0') {
            struct group * gr = getgrnam(group.c_str());
            if (gr == 0)
                throw Exception(errno, "finding group \"%s\"", group.c_str());
            groupNum = gr->gr_gid;
        }

        cerr << "setting group of " << filename << " to " << groupNum
             << " for group " << group << endl;

        int res = chown(filename.c_str(), -1, groupNum);

        if (res == -1)
            throw Exception(errno, "chown in setPermissions");
    }
}

std::string print(FileType type)
{
    switch (type) {
    case FT_FILE: return "FILE";
    case FT_DIR:  return "DIR";
    case FT_DIR_INACCESSIBLE: return "DIR_INACCESSIBLE";
    case FT_FILE_INACCESSIBLE: return "FILE_INACCESSIBLE";
    default:
        return ML::format("FileType(%d)", type);
    }
}

std::ostream &
operator << (std::ostream & stream, const FileType & type)
{
    return stream << print(type);
}

struct ScanFilesData;

static __thread ScanFilesData * scanFilesThreadData = 0;

struct ScanFilesData {
    ScanFilesData(const OnFileFound & onFileFound,
                  int maxDepth)
        : onFileFound(onFileFound),
          maxDepth(maxDepth),
          isThrown(false)
    {
    }

    OnFileFound onFileFound;
    int maxDepth;
    std::exception_ptr thrown;
    bool isThrown;

    static int onFile (const char *fpath, const struct stat *sb,
                       int typeflag, struct FTW *ftwbuf)
    {
        ScanFilesData * d = scanFilesThreadData;
        try {
            if (d->maxDepth != -1 && ftwbuf->level > d->maxDepth)
                return FTW_SKIP_SIBLINGS;
            string dir(fpath, fpath + ftwbuf->base);
            string basename(fpath + ftwbuf->base);

            FileAction action = d->onFileFound(dir, basename, *sb,
                                               (FileType)typeflag,
                                               ftwbuf->level);
            return action;
        } catch (...) {
            d->thrown = std::current_exception();
            d->isThrown = true;
            return FTW_STOP;
        }
    }
};

void scanFiles(const std::string & path,
               OnFileFound onFileFound,
               int maxDepth)
{
    ScanFilesData data(onFileFound, maxDepth);

    scanFilesThreadData = &data;

    int res = nftw(path.c_str(),
                   &ScanFilesData::onFile,
                   maxDepth == -1 ? 100 : maxDepth + 1,
                   FTW_ACTIONRETVAL);

    if (scanFilesThreadData->isThrown) {
        auto exc = scanFilesThreadData->thrown;
        scanFilesThreadData = 0;
        rethrow_exception(exc);
    }

    scanFilesThreadData = 0;

    if (res == -1)
        throw ML::Exception(errno, "ftw");
}

/** Call fdatasync on the file. */
void syncFile(const std::string & filename)
{
    int fd = ::open(filename.c_str(), O_RDONLY);
    if (fd == -1)
        throw ML::Exception(errno, "syncFile for " + filename);
    ML::Call_Guard guard([=] () { close(fd); });
    int res = fdatasync(fd);
    if (res == -1)
        throw ML::Exception(errno, "fdatasync for " + filename);
}

/*****************************************************************************/
/* FILE_READ_BUFFER                                                          */
/*****************************************************************************/

/** Helper class to specify and clean up a memory mapped region. */
class File_Read_Buffer::MMap_Region
    : public File_Read_Buffer::Region {

    inode_type inode;

    MMap_Region(int fd, inode_type inode)
        : inode(inode)
    {
        size = get_file_size(fd);

        if (size == 0) {
            start = 0;
        }
        else {
            start = (const char *)mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
            if (start == MAP_FAILED)
                throw Exception(errno, "mmap", "MMap_Region()");
        }

    }

    MMap_Region(const MMap_Region & other);

    MMap_Region & operator = (const MMap_Region & other);

    typedef std::map<inode_type, std::weak_ptr<MMap_Region> > cache_type;

    static cache_type & cache()
    {
        static cache_type result;
        return result;
    }

    static ML::Spinlock & lock()
    {
        static ML::Spinlock result;
        return result;
    }

public:
    static std::shared_ptr<MMap_Region> get(int fd)
    {
        std::lock_guard<ML::Spinlock> guard(lock());

        inode_type inode = get_inode(fd);
        std::weak_ptr<MMap_Region> & ptr = cache()[inode];

        std::shared_ptr<MMap_Region> result;
        result = ptr.lock();

        if (!result) {
            result.reset(new MMap_Region(fd, inode));
            ptr = result;
        }

        return result;
    }

    virtual ~MMap_Region()
    {
        if  (size) munmap((void *)start, size);

        std::lock_guard<ML::Spinlock> guard(lock());
        if (cache()[inode].expired())
            cache().erase(inode);
    }
};

/** Region that comes from a memory block. */
class File_Read_Buffer::Mem_Region : public File_Read_Buffer::Region {
public:
    Mem_Region(const char * start, size_t size,
               boost::function<void ()> onDone)
    {
        this->start = start;
        this->size = size;
        this->onDone = onDone;
    }

    boost::function<void ()> onDone;

    virtual ~Mem_Region()
    {
        if (onDone)
            onDone();
    }
};

File_Read_Buffer::Region::~Region()
{
}

/*****************************************************************************/
/* FILE_READ_BUFFER                                                          */
/*****************************************************************************/

File_Read_Buffer::File_Read_Buffer()
{
}

File_Read_Buffer::File_Read_Buffer(const std::string & filename)
{
    open(filename);
}

File_Read_Buffer::File_Read_Buffer(int fd)
{
    open(fd);
}

File_Read_Buffer::File_Read_Buffer(const char * start, size_t length,
                                   const std::string & filename,
                                   boost::function<void ()> onDone)
{
    open(start, length, filename, onDone);
}

File_Read_Buffer::File_Read_Buffer(const File_Read_Buffer & other)
    : filename_(other.filename_), region(other.region)
{
}

void File_Read_Buffer::open(const std::string & filename)
{
    int fd = ::open(filename.c_str(), O_RDONLY);

    if (fd == -1)
        throw Exception(errno, filename, "File_Read_Buffer::open()");

    try {
        region = MMap_Region::get(fd);
        filename_ = filename;
    }
    catch (...) {
        ::close(fd);
        throw;
    }
    ::close(fd);
}

void File_Read_Buffer::open(int fd)
{
    region = MMap_Region::get(fd);
    filename_ = get_name_from_fd(fd);
}

void File_Read_Buffer::open(const char * start, size_t length,
                            const std::string & filename,
                            boost::function<void ()> onDone)
{
    region.reset(new Mem_Region(start, length, onDone));
    filename_ = filename;
}

void File_Read_Buffer::close()
{
    region.reset();
    filename_ = "";
}

} // namespace ML
<commit_msg>scanFiles no longer throws an exception if the directory doesn't exist (PLAT-567)<commit_after>/* file_functions.cc
   Jeremy Barnes, 14 March 2005
   Copyright (c) 2005 Jeremy Barnes.  All rights reserved.

   This file is part of "Jeremy's Machine Learning Library", copyright (c)
   1999-2005 Jeremy Barnes.

   This program is available under the GNU General Public License, the terms
   of which are given by the file "license.txt" in the top level directory of
   the source code distribution.  If this file is missing, you have no right
   to use the program; please contact the author.

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

   ---

   Functions to deal with files.
*/

#include "file_functions.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "string_functions.h"
#include "jml/arch/exception.h"
#include "jml/arch/spinlock.h"
#include <iostream>
#include <boost/weak_ptr.hpp>
#include <map>
#include <grp.h>
#include <exception>
#include "guard.h"
#include <mutex>

using namespace std;

namespace ML {

size_t get_file_size(int fd)
{
    struct stat stats;
    int result = fstat(fd, &stats);
    if (result != 0)
        throw Exception("fstat: " + string(strerror(errno)));
    return stats.st_size;
}

size_t get_file_size(const std::string & filename)
{
    struct stat stats;
    int result = stat(filename.c_str(), &stats);
    if (result != 0)
        throw Exception("stat: " + string(strerror(errno)));
    return stats.st_size;
}

std::string get_link_target(const std::string & link)
{
    /* Interface to the readlink call */
    size_t bufsize = 1024;

    /* Loop over, making the buffer successively larger if it is too small. */
    while (true) {  // break in loop
        char buf[bufsize];
        int res = readlink(link.c_str(), buf, bufsize);
        if (res == -1)
            throw Exception(errno, "readlink", "get_link_name()");
        if (res == bufsize) {
            bufsize *= 2;
            continue;
        }
        buf[res] = 0;
        return buf;
    }
}

std::string get_name_from_fd(int fd)
{
    string fname = format("/proc/self/fd/%d", fd);
    return get_link_target(fname);
}

inode_type get_inode(const std::string & filename)
{
    struct stat st;

    int res = stat(filename.c_str(), &st);

    if (res != 0)
        throw Exception(errno, "fstat", "get_inode()");

    return make_pair(st.st_dev, st.st_ino);
}

inode_type get_inode(int fd)
{
    struct stat st;

    int res = fstat(fd, &st);

    if (res != 0)
        throw Exception(errno, "fstat", "get_inode()");

    return make_pair(st.st_dev, st.st_ino);
}

void delete_file(const std::string & filename)
{
    int res = unlink(filename.c_str());
    if (res != 0)
        throw Exception(errno, "couldn't delete file " + filename, "unlink");
}

void set_file_flag(int fd, int newFlag)
{
    int oldFlags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, oldFlags | newFlag);
}

void unset_file_flag(int fd, int oldFlag)
{
    int oldFlags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, oldFlags & ~oldFlag);
}

bool is_file_flag_set(int fd, int flag)
{
    int oldFlags = fcntl(fd, F_GETFL, 0);
    return ((oldFlags & flag) == flag);
}

/** Does the file exist? */
bool fileExists(const std::string & filename)
{
    struct stat stats;
    int res = stat(filename.c_str(), &stats);
    if (res == -1)
        return false;  // no chunks
    return true;
}

void set_permissions(std::string filename,
                     const std::string & perms,
                     const std::string & group)
{
    if (filename.find("ipc://") == 0)
        filename = string(filename, 6);

    char * endptr;
    if (perms != "") {
        int mode = strtol(perms.c_str(), &endptr, 8);
        if (*endptr != '\0')
            throw Exception(errno, "parsing permission modes %s",
                            perms.c_str());

        cerr << "setting permissions of " << filename << " to " << perms
             << "(" << mode << ")" << endl;

        int res = chmod(filename.c_str(), mode);
        if (res == -1)
            throw Exception(errno, "chmod on %s in setPermissions");
    }

    if (group != "") {
        int groupNum = strtol(group.c_str(), &endptr, 10);
        if (*endptr != '\0') {
            struct group * gr = getgrnam(group.c_str());
            if (gr == 0)
                throw Exception(errno, "finding group \"%s\"", group.c_str());
            groupNum = gr->gr_gid;
        }

        cerr << "setting group of " << filename << " to " << groupNum
             << " for group " << group << endl;

        int res = chown(filename.c_str(), -1, groupNum);

        if (res == -1)
            throw Exception(errno, "chown in setPermissions");
    }
}

std::string print(FileType type)
{
    switch (type) {
    case FT_FILE: return "FILE";
    case FT_DIR:  return "DIR";
    case FT_DIR_INACCESSIBLE: return "DIR_INACCESSIBLE";
    case FT_FILE_INACCESSIBLE: return "FILE_INACCESSIBLE";
    default:
        return ML::format("FileType(%d)", type);
    }
}

std::ostream &
operator << (std::ostream & stream, const FileType & type)
{
    return stream << print(type);
}

struct ScanFilesData;

static __thread ScanFilesData * scanFilesThreadData = 0;

struct ScanFilesData {
    ScanFilesData(const OnFileFound & onFileFound,
                  int maxDepth)
        : onFileFound(onFileFound),
          maxDepth(maxDepth),
          isThrown(false)
    {
    }

    OnFileFound onFileFound;
    int maxDepth;
    std::exception_ptr thrown;
    bool isThrown;

    static int onFile (const char *fpath, const struct stat *sb,
                       int typeflag, struct FTW *ftwbuf)
    {
        ScanFilesData * d = scanFilesThreadData;
        try {
            if (d->maxDepth != -1 && ftwbuf->level > d->maxDepth)
                return FTW_SKIP_SIBLINGS;
            string dir(fpath, fpath + ftwbuf->base);
            string basename(fpath + ftwbuf->base);

            FileAction action = d->onFileFound(dir, basename, *sb,
                                               (FileType)typeflag,
                                               ftwbuf->level);
            return action;
        } catch (...) {
            d->thrown = std::current_exception();
            d->isThrown = true;
            return FTW_STOP;
        }
    }
};

void scanFiles(const std::string & path,
               OnFileFound onFileFound,
               int maxDepth)
{
    ScanFilesData data(onFileFound, maxDepth);

    scanFilesThreadData = &data;

    int res = nftw(path.c_str(),
                   &ScanFilesData::onFile,
                   maxDepth == -1 ? 100 : maxDepth + 1,
                   FTW_ACTIONRETVAL);

    if (scanFilesThreadData->isThrown) {
        auto exc = scanFilesThreadData->thrown;
        scanFilesThreadData = 0;
        rethrow_exception(exc);
    }

    scanFilesThreadData = 0;

    if (res == -1) {
        if (errno == ENOENT)
            return;
        throw ML::Exception(errno, "ftw");
    }
}

/** Call fdatasync on the file. */
void syncFile(const std::string & filename)
{
    int fd = ::open(filename.c_str(), O_RDONLY);
    if (fd == -1)
        throw ML::Exception(errno, "syncFile for " + filename);
    ML::Call_Guard guard([=] () { close(fd); });
    int res = fdatasync(fd);
    if (res == -1)
        throw ML::Exception(errno, "fdatasync for " + filename);
}

/*****************************************************************************/
/* FILE_READ_BUFFER                                                          */
/*****************************************************************************/

/** Helper class to specify and clean up a memory mapped region. */
class File_Read_Buffer::MMap_Region
    : public File_Read_Buffer::Region {

    inode_type inode;

    MMap_Region(int fd, inode_type inode)
        : inode(inode)
    {
        size = get_file_size(fd);

        if (size == 0) {
            start = 0;
        }
        else {
            start = (const char *)mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
            if (start == MAP_FAILED)
                throw Exception(errno, "mmap", "MMap_Region()");
        }

    }

    MMap_Region(const MMap_Region & other);

    MMap_Region & operator = (const MMap_Region & other);

    typedef std::map<inode_type, std::weak_ptr<MMap_Region> > cache_type;

    static cache_type & cache()
    {
        static cache_type result;
        return result;
    }

    static ML::Spinlock & lock()
    {
        static ML::Spinlock result;
        return result;
    }

public:
    static std::shared_ptr<MMap_Region> get(int fd)
    {
        std::lock_guard<ML::Spinlock> guard(lock());

        inode_type inode = get_inode(fd);
        std::weak_ptr<MMap_Region> & ptr = cache()[inode];

        std::shared_ptr<MMap_Region> result;
        result = ptr.lock();

        if (!result) {
            result.reset(new MMap_Region(fd, inode));
            ptr = result;
        }

        return result;
    }

    virtual ~MMap_Region()
    {
        if  (size) munmap((void *)start, size);

        std::lock_guard<ML::Spinlock> guard(lock());
        if (cache()[inode].expired())
            cache().erase(inode);
    }
};

/** Region that comes from a memory block. */
class File_Read_Buffer::Mem_Region : public File_Read_Buffer::Region {
public:
    Mem_Region(const char * start, size_t size,
               boost::function<void ()> onDone)
    {
        this->start = start;
        this->size = size;
        this->onDone = onDone;
    }

    boost::function<void ()> onDone;

    virtual ~Mem_Region()
    {
        if (onDone)
            onDone();
    }
};

File_Read_Buffer::Region::~Region()
{
}

/*****************************************************************************/
/* FILE_READ_BUFFER                                                          */
/*****************************************************************************/

File_Read_Buffer::File_Read_Buffer()
{
}

File_Read_Buffer::File_Read_Buffer(const std::string & filename)
{
    open(filename);
}

File_Read_Buffer::File_Read_Buffer(int fd)
{
    open(fd);
}

File_Read_Buffer::File_Read_Buffer(const char * start, size_t length,
                                   const std::string & filename,
                                   boost::function<void ()> onDone)
{
    open(start, length, filename, onDone);
}

File_Read_Buffer::File_Read_Buffer(const File_Read_Buffer & other)
    : filename_(other.filename_), region(other.region)
{
}

void File_Read_Buffer::open(const std::string & filename)
{
    int fd = ::open(filename.c_str(), O_RDONLY);

    if (fd == -1)
        throw Exception(errno, filename, "File_Read_Buffer::open()");

    try {
        region = MMap_Region::get(fd);
        filename_ = filename;
    }
    catch (...) {
        ::close(fd);
        throw;
    }
    ::close(fd);
}

void File_Read_Buffer::open(int fd)
{
    region = MMap_Region::get(fd);
    filename_ = get_name_from_fd(fd);
}

void File_Read_Buffer::open(const char * start, size_t length,
                            const std::string & filename,
                            boost::function<void ()> onDone)
{
    region.reset(new Mem_Region(start, length, onDone));
    filename_ = filename;
}

void File_Read_Buffer::close()
{
    region.reset();
    filename_ = "";
}

} // namespace ML
<|endoftext|>


<commit_before>/*
 * jcom.dataspace
 * External for Jamoma: map input to output: y=f(x)
 * Copyright © 2007
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include "Jamoma.h"

// Data Structure for this object
typedef struct _dataspace{
	t_object		ob;
	//void			*outlet_active;
	void			*outlet_native;
	DataspaceLib	*dataspace;
	long			ac;						// for return values from the dataspace conversion
	t_atom			*av;					//	...
	t_symbol		*attr_dataspace;		// name of the dataspace -- e.g. "temperature"
	t_symbol		*attr_dataspace_active;	// name of the current unit within the dataspace -- e.g. "celsius"
	t_symbol		*attr_dataspace_native;	// name of the desired native unit within the dataspace -- e.g. "celsius"
} t_dataspace;

// Prototypes for methods
void*		dataspace_new(t_symbol *name, long argc, t_atom *argv);
void		dataspace_free(t_dataspace *obj);
void		dataspace_assist(t_dataspace *obj, void *b, long m, long a, char *s);
void		dataspace_int(t_dataspace *obj, long x);
void		dataspace_float(t_dataspace *obj, double x);
void		dataspace_list(t_dataspace *obj, t_symbol *msg, long argc, t_atom *argv);
void		dataspace_getDataspaces(t_dataspace *obj);
void		dataspace_getUnits(t_dataspace *obj);
t_max_err	dataspace_setDataspace(t_dataspace *obj, void *attr, long argc, t_atom *argv);
t_max_err	dataspace_setDataspaceActive(t_dataspace *obj, void *attr, long argc, t_atom *argv);
t_max_err	dataspace_setDataspaceNative(t_dataspace *obj, void *attr, long argc, t_atom *argv);

// Globals
t_class		*dataspace_class;

#pragma mark -
#pragma mark main
/************************************************************************************/
// Main() Function

int JAMOMA_EXPORT_MAXOBJ main(void)
{
	t_class *c;

	jamoma_init();
	common_symbols_init();

	// Define our class
	c = class_new("jcom.dataspace",(method)dataspace_new, (method)dataspace_free, sizeof(t_dataspace), (method)0L, A_GIMME, 0);

	// Make methods accessible for our class:
	class_addmethod(c, (method)dataspace_int,			"int",				A_GIMME, 0);
	class_addmethod(c, (method)dataspace_float,			"float",			A_GIMME, 0);
	class_addmethod(c, (method)dataspace_list,			"list",				A_GIMME, 0);
	class_addmethod(c, (method)dataspace_getDataspaces,	"dataspaces.get",	0);
 	class_addmethod(c, (method)dataspace_getUnits,		"units.get",		A_GIMME, 0);
	class_addmethod(c, (method)dataspace_assist,		"assist",			A_CANT, 0);
    class_addmethod(c, (method)object_obex_dumpout, 	"dumpout",			A_CANT, 0);

	class_addattr(c,
		attr_offset_new("dataspace", _sym_symbol, 0,
		(method)0, (method)dataspace_setDataspace, calcoffset(t_dataspace, attr_dataspace)));
/*
	class_addattr(c,
		attr_offset_new("unit.active", _sym_symbol, 0,
		(method)0, (method)dataspace_setDataspaceActive, calcoffset(t_dataspace, attr_dataspace_active)));
	class_addattr(c,
		attr_offset_new("unit.native", _sym_symbol, 0,
		(method)0, (method)dataspace_setDataspaceNative, calcoffset(t_dataspace, attr_dataspace_native)));
*/
	CLASS_ATTR_SYM(c,		"input",	0,		t_dataspace,	attr_dataspace_active);
	CLASS_ATTR_ACCESSORS(c,	"input",	NULL,	dataspace_setDataspaceActive);

	CLASS_ATTR_SYM(c,		"output",	0,		t_dataspace,	attr_dataspace_native);
	CLASS_ATTR_ACCESSORS(c,	"output",	NULL,	dataspace_setDataspaceNative);

	// Finalize our class
	class_register(CLASS_BOX, c);
	dataspace_class = c;
	return 0;
}

#pragma mark -
#pragma mark life cycle
/************************************************************************************/
// Object Life

void *dataspace_new(t_symbol *name, long argc, t_atom *argv)
{
	t_dataspace *obj;									// Declare an object (based on our struct)

	obj = (t_dataspace *)object_alloc(dataspace_class);		// Create object, store pointer to it (get 1 inlet free)
	if (obj) {
		object_obex_store((void *)obj, _sym_dumpout, (object *)outlet_new(obj,NULL));
	    //obj->outlet_active = outlet_new(obj, 0);
	    obj->outlet_native = outlet_new(obj, 0);
		obj->dataspace = NULL;
		obj->attr_dataspace_active = _sym_nothing;
		obj->attr_dataspace_native = _sym_nothing;

		attr_args_process(obj, argc, argv);
		if (!obj->dataspace)
			object_attr_setsym(obj, gensym("dataspace"), gensym("temperature"));

		obj->av = (t_atom*)sysmem_newptr(sizeof(t_atom) * 3);	// just allocating three for now -- limited list support
	}
	return obj;										// Return pointer to our instance
}

void dataspace_free(t_dataspace *obj)
{
	sysmem_freeptr(obj->av);
	if (obj->dataspace)
		delete obj->dataspace;
}

#pragma mark -
#pragma mark methods
/************************************************************************************/
// Methods bound to input/inlets

// Method for Assistance Messages
void dataspace_assist(t_dataspace *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) 							// Inlets
		strcpy(dst, "x");
	else if (msg==2) { 					// Outlets
		switch(arg) {
			case 0: strcpy(dst, "y=f(x)"); break;
			default: strcpy(dst, "dumpout"); break;
 		}
 	}
}

void dataspace_int(t_dataspace *obj, long x)
{
	dataspace_float(obj, (double)x);
}

void dataspace_float(t_dataspace *obj, double x)
{
	t_atom	a[1];

	atom_setfloat(a, x);
	obj->dataspace->convert(1, a, &obj->ac, &obj->av);
	outlet_anything(obj->outlet_native, _sym_float, obj->ac, obj->av);
	//outlet_float(obj->outlet_active, x);
}

void dataspace_list(t_dataspace *obj, t_symbol *msg, long argc, t_atom *argv)
{
	obj->dataspace->convert(argc, argv, &obj->ac, &obj->av);
	outlet_anything(obj->outlet_native, _sym_list, obj->ac, obj->av);
	//outlet_anything(obj->outlet_active, _sym_list, argc, argv);
}

void dataspace_getDataspaces(t_dataspace *obj)
{
	t_atom		a[2];
	t_symbol	**dataspaceNames = NULL;
	long		numDataspaces = 0;
	long		i;

	atom_setsym(a+0, gensym("clear"));
	object_obex_dumpout(obj, gensym("DataspacesMenu"), 1, a);

	jamoma_getDataspaceList(&numDataspaces, &dataspaceNames);

	for (i=0; i<numDataspaces; i++) {
		atom_setsym(a+0, gensym("append"));
		atom_setsym(a+1, dataspaceNames[i]);
		object_obex_dumpout(obj, gensym("DataspacesMenu"), 2, a);
	}

	if (numDataspaces)
		sysmem_freeptr(dataspaceNames);
}

void dataspace_getUnits(t_dataspace *obj)
{
	t_atom		a[2];
	t_symbol	**unitNames = NULL;
	long		numUnits = 0;
	long		i;

	atom_setsym(a+0, gensym("clear"));
	object_obex_dumpout(obj, gensym("UnitMenu"), 1, a);

	obj->dataspace->getAvailableUnits(&numUnits, &unitNames);

	for (i=0; i<numUnits; i++) {
		atom_setsym(a+0, gensym("append"));
		atom_setsym(a+1, unitNames[i]);
		object_obex_dumpout(obj, gensym("UnitMenu"), 2, a);
	}

	if (numUnits)
		sysmem_freeptr(unitNames);
}

#pragma mark -
#pragma mark attributes
// ATTRIBUTE:
t_max_err dataspace_setDataspace(t_dataspace *obj, void *attr, long argc, t_atom *argv)
{
	obj->attr_dataspace = atom_getsym(argv);
	jamoma_getDataspace(obj->attr_dataspace, &obj->dataspace);
	obj->attr_dataspace_active = obj->dataspace->neutralUnit;
	obj->attr_dataspace_native = obj->dataspace->neutralUnit;
	return MAX_ERR_NONE;
}

// ATTRIBUTE:
t_max_err dataspace_setDataspaceActive(t_dataspace *obj, void *attr, long argc, t_atom *argv)
{
	obj->attr_dataspace_active = atom_getsym(argv);
	obj->dataspace->setInputUnit(obj->attr_dataspace_active);
	return MAX_ERR_NONE;
}

// ATTRIBUTE:
t_max_err dataspace_setDataspaceNative(t_dataspace *obj, void *attr, long argc, t_atom *argv)
{
	obj->attr_dataspace_native = atom_getsym(argv);
	obj->dataspace->setOutputUnit(obj->attr_dataspace_native);
	return MAX_ERR_NONE;
}

<commit_msg>added TODO<commit_after>/*
 * jcom.dataspace
 * External for Jamoma: map input to output: y=f(x)
 * Copyright © 2007
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include "Jamoma.h"

// Data Structure for this object
typedef struct _dataspace{
	t_object		ob;
	//void			*outlet_active;
	void			*outlet_native;
	DataspaceLib	*dataspace;
	long			ac;						// for return values from the dataspace conversion
	t_atom			*av;					//	...
	t_symbol		*attr_dataspace;		// name of the dataspace -- e.g. "temperature"
	t_symbol		*attr_dataspace_active;	// name of the current unit within the dataspace -- e.g. "celsius"
	t_symbol		*attr_dataspace_native;	// name of the desired native unit within the dataspace -- e.g. "celsius"
} t_dataspace;

// Prototypes for methods
void*		dataspace_new(t_symbol *name, long argc, t_atom *argv);
void		dataspace_free(t_dataspace *obj);
void		dataspace_assist(t_dataspace *obj, void *b, long m, long a, char *s);
void		dataspace_int(t_dataspace *obj, long x);
void		dataspace_float(t_dataspace *obj, double x);
void		dataspace_list(t_dataspace *obj, t_symbol *msg, long argc, t_atom *argv);
void		dataspace_getDataspaces(t_dataspace *obj);
void		dataspace_getUnits(t_dataspace *obj);
t_max_err	dataspace_setDataspace(t_dataspace *obj, void *attr, long argc, t_atom *argv);
t_max_err	dataspace_setDataspaceActive(t_dataspace *obj, void *attr, long argc, t_atom *argv);
t_max_err	dataspace_setDataspaceNative(t_dataspace *obj, void *attr, long argc, t_atom *argv);

// Globals
t_class		*dataspace_class;

#pragma mark -
#pragma mark main
/************************************************************************************/
// Main() Function

int JAMOMA_EXPORT_MAXOBJ main(void)
{
	t_class *c;

	jamoma_init();
	common_symbols_init();

	// Define our class
	c = class_new("jcom.dataspace",(method)dataspace_new, (method)dataspace_free, sizeof(t_dataspace), (method)0L, A_GIMME, 0);

	// Make methods accessible for our class:
	class_addmethod(c, (method)dataspace_int,			"int",				A_GIMME, 0);
	class_addmethod(c, (method)dataspace_float,			"float",			A_GIMME, 0);
	class_addmethod(c, (method)dataspace_list,			"list",				A_GIMME, 0);
	class_addmethod(c, (method)dataspace_getDataspaces,	"dataspaces.get",	0);
 	class_addmethod(c, (method)dataspace_getUnits,		"units.get",		A_GIMME, 0);
	class_addmethod(c, (method)dataspace_assist,		"assist",			A_CANT, 0);
    class_addmethod(c, (method)object_obex_dumpout, 	"dumpout",			A_CANT, 0);

	class_addattr(c,
		attr_offset_new("dataspace", _sym_symbol, 0,
		(method)0, (method)dataspace_setDataspace, calcoffset(t_dataspace, attr_dataspace)));
/*
	class_addattr(c,
		attr_offset_new("unit.active", _sym_symbol, 0,
		(method)0, (method)dataspace_setDataspaceActive, calcoffset(t_dataspace, attr_dataspace_active)));
	class_addattr(c,
		attr_offset_new("unit.native", _sym_symbol, 0,
		(method)0, (method)dataspace_setDataspaceNative, calcoffset(t_dataspace, attr_dataspace_native)));
*/
	CLASS_ATTR_SYM(c,		"input",	0,		t_dataspace,	attr_dataspace_active);
	CLASS_ATTR_ACCESSORS(c,	"input",	NULL,	dataspace_setDataspaceActive);

	CLASS_ATTR_SYM(c,		"output",	0,		t_dataspace,	attr_dataspace_native);
	CLASS_ATTR_ACCESSORS(c,	"output",	NULL,	dataspace_setDataspaceNative);

	// Finalize our class
	class_register(CLASS_BOX, c);
	dataspace_class = c;
	return 0;
}

#pragma mark -
#pragma mark life cycle
/************************************************************************************/
// Object Life

void *dataspace_new(t_symbol *name, long argc, t_atom *argv)
{
	t_dataspace *obj;									// Declare an object (based on our struct)

	obj = (t_dataspace *)object_alloc(dataspace_class);		// Create object, store pointer to it (get 1 inlet free)
	if (obj) {
		object_obex_store((void *)obj, _sym_dumpout, (object *)outlet_new(obj,NULL));
	    //obj->outlet_active = outlet_new(obj, 0);
	    obj->outlet_native = outlet_new(obj, 0);
		obj->dataspace = NULL;
		obj->attr_dataspace_active = _sym_nothing;
		obj->attr_dataspace_native = _sym_nothing;

		attr_args_process(obj, argc, argv);
		if (!obj->dataspace)
			object_attr_setsym(obj, gensym("dataspace"), gensym("temperature"));

		obj->av = (t_atom*)sysmem_newptr(sizeof(t_atom) * 3);	// just allocating three for now -- limited list support
	}
	return obj;										// Return pointer to our instance
}

void dataspace_free(t_dataspace *obj)
{
	sysmem_freeptr(obj->av);
	if (obj->dataspace)
		delete obj->dataspace;
}

#pragma mark -
#pragma mark methods
/************************************************************************************/
// Methods bound to input/inlets

// Method for Assistance Messages
void dataspace_assist(t_dataspace *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) 							// Inlets
		strcpy(dst, "x");
	else if (msg==2) { 					// Outlets
		switch(arg) {
			case 0: strcpy(dst, "y=f(x)"); break;
			default: strcpy(dst, "dumpout"); break;
 		}
 	}
}

void dataspace_int(t_dataspace *obj, long x)
{
	dataspace_float(obj, (double)x);
}

void dataspace_float(t_dataspace *obj, double x)
{
	t_atom	a[1];

	atom_setfloat(a, x);
	obj->dataspace->convert(1, a, &obj->ac, &obj->av);
	outlet_anything(obj->outlet_native, _sym_float, obj->ac, obj->av);
	//outlet_float(obj->outlet_active, x);
}

void dataspace_list(t_dataspace *obj, t_symbol *msg, long argc, t_atom *argv)
{
	//TODO: add dataspace support for lists of single dimensional data conversion
	obj->dataspace->convert(argc, argv, &obj->ac, &obj->av);
	outlet_anything(obj->outlet_native, _sym_list, obj->ac, obj->av);
	//outlet_anything(obj->outlet_active, _sym_list, argc, argv);
}

void dataspace_getDataspaces(t_dataspace *obj)
{
	t_atom		a[2];
	t_symbol	**dataspaceNames = NULL;
	long		numDataspaces = 0;
	long		i;

	atom_setsym(a+0, gensym("clear"));
	object_obex_dumpout(obj, gensym("DataspacesMenu"), 1, a);

	jamoma_getDataspaceList(&numDataspaces, &dataspaceNames);

	for (i=0; i<numDataspaces; i++) {
		atom_setsym(a+0, gensym("append"));
		atom_setsym(a+1, dataspaceNames[i]);
		object_obex_dumpout(obj, gensym("DataspacesMenu"), 2, a);
	}

	if (numDataspaces)
		sysmem_freeptr(dataspaceNames);
}

void dataspace_getUnits(t_dataspace *obj)
{
	t_atom		a[2];
	t_symbol	**unitNames = NULL;
	long		numUnits = 0;
	long		i;

	atom_setsym(a+0, gensym("clear"));
	object_obex_dumpout(obj, gensym("UnitMenu"), 1, a);

	obj->dataspace->getAvailableUnits(&numUnits, &unitNames);

	for (i=0; i<numUnits; i++) {
		atom_setsym(a+0, gensym("append"));
		atom_setsym(a+1, unitNames[i]);
		object_obex_dumpout(obj, gensym("UnitMenu"), 2, a);
	}

	if (numUnits)
		sysmem_freeptr(unitNames);
}

#pragma mark -
#pragma mark attributes
// ATTRIBUTE:
t_max_err dataspace_setDataspace(t_dataspace *obj, void *attr, long argc, t_atom *argv)
{
	obj->attr_dataspace = atom_getsym(argv);
	jamoma_getDataspace(obj->attr_dataspace, &obj->dataspace);
	obj->attr_dataspace_active = obj->dataspace->neutralUnit;
	obj->attr_dataspace_native = obj->dataspace->neutralUnit;
	return MAX_ERR_NONE;
}

// ATTRIBUTE:
t_max_err dataspace_setDataspaceActive(t_dataspace *obj, void *attr, long argc, t_atom *argv)
{
	obj->attr_dataspace_active = atom_getsym(argv);
	obj->dataspace->setInputUnit(obj->attr_dataspace_active);
	return MAX_ERR_NONE;
}

// ATTRIBUTE:
t_max_err dataspace_setDataspaceNative(t_dataspace *obj, void *attr, long argc, t_atom *argv)
{
	obj->attr_dataspace_native = atom_getsym(argv);
	obj->dataspace->setOutputUnit(obj->attr_dataspace_native);
	return MAX_ERR_NONE;
}

<|endoftext|>