<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "binarymeshfilereader.h"

// appleseed.foundation headers.
#include "foundation/core/exceptions/exception.h"
#include "foundation/core/exceptions/exceptionioerror.h"
#include "foundation/math/vector.h"
#include "foundation/mesh/imeshbuilder.h"
#include "foundation/platform/types.h"
#include "foundation/utility/bufferedfile.h"
#include "foundation/utility/memory.h"

// Standard headers.
#include <cstring>
#include <memory>

using namespace std;

namespace foundation
{

//
// BinaryMeshFileReader class implementation.
//

namespace
{
    struct ExceptionEOF : public Exception {};

    template <typename File>
    inline void checked_read(File& file, void* outbuf, const size_t size)
    {
        if (size == 0)
            return;

        const size_t bytes_read = file.read(outbuf, size);

        if (bytes_read == 0)
            throw ExceptionEOF();

        if (bytes_read < size)
            throw ExceptionIOError();
    }

    template <typename File, typename T>
    inline void checked_read(File& file, T& object)
    {
        checked_read(file, &object, sizeof(T));
    }
}

BinaryMeshFileReader::BinaryMeshFileReader(const string& filename)
  : m_filename(filename)
{
}

void BinaryMeshFileReader::read(IMeshBuilder& builder)
{
    BufferedFile file(
        m_filename.c_str(),
        BufferedFile::BinaryType,
        BufferedFile::ReadMode);

    if (!file.is_open())
        throw ExceptionIOError();

    read_and_check_signature(file);

    uint16 version;
    checked_read(file, version);

    auto_ptr<ReaderAdapter> reader;

    switch (version)
    {
      case 1:                       // uncompressed (deprecated)
        reader.reset(new PassthroughReaderAdapter(file));
        break;

      case 2:                       // LZO-compressed (deprecated)
        reader.reset(new LZOCompressedReaderAdapter(file));
        break;

      case 3:                       // LZ4-compressed
        reader.reset(new LZ4CompressedReaderAdapter(file));
        break;

      default:                      // unknown format
        throw ExceptionIOError();   // todo: throw better-qualified exception
    }

    read_meshes(*reader.get(), builder);
}

void BinaryMeshFileReader::read_and_check_signature(BufferedFile& file)
{
    static const char ExpectedSig[10] = { 'B', 'I', 'N', 'A', 'R', 'Y', 'M', 'E', 'S', 'H' };

    char signature[sizeof(ExpectedSig)];
    checked_read(file, signature, sizeof(signature));

    if (memcmp(signature, ExpectedSig, sizeof(ExpectedSig)))
        throw ExceptionIOError();   // todo: throw better-qualified exception
}

string BinaryMeshFileReader::read_string(ReaderAdapter& reader)
{
    uint16 length;
    checked_read(reader, length);

    string s;
    s.resize(length);
    checked_read(reader, &s[0], length);

    return s;
}

void BinaryMeshFileReader::read_meshes(ReaderAdapter& reader, IMeshBuilder& builder)
{
    try
    {
        while (true)
        {
            // Read the name of the next mesh.
            string mesh_name;
            try
            {
                mesh_name = read_string(reader);
            }
            catch (const ExceptionEOF&)
            {
                // Expected EOF.
                break;
            }

            builder.begin_mesh(mesh_name.c_str());

            read_vertices(reader, builder);
            read_vertex_normals(reader, builder);
            read_texture_coordinates(reader, builder);
            read_material_slots(reader, builder);
            read_faces(reader, builder);

            builder.end_mesh();
        }
    }
    catch (const ExceptionEOF&)
    {
        // Unexpected EOF.
        throw ExceptionIOError();
    }
}

void BinaryMeshFileReader::read_vertices(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint32 count;
    checked_read(reader, count);

    for (uint32 i = 0; i < count; ++i)
    {
        Vector3d v;
        checked_read(reader, v);
        builder.push_vertex(v);
    }
}

void BinaryMeshFileReader::read_vertex_normals(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint32 count;
    checked_read(reader, count);

    for (uint32 i = 0; i < count; ++i)
    {
        Vector3d v;
        checked_read(reader, v);
        builder.push_vertex_normal(v);
    }
}

void BinaryMeshFileReader::read_texture_coordinates(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint32 count;
    checked_read(reader, count);

    for (uint32 i = 0; i < count; ++i)
    {
        Vector2d v;
        checked_read(reader, v);
        builder.push_tex_coords(v);
    }
}

void BinaryMeshFileReader::read_material_slots(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint16 count;
    checked_read(reader, count);

    for (uint16 i = 0; i < count; ++i)
    {
        const string material_slot = read_string(reader);
        builder.push_material_slot(material_slot.c_str());
    }
}

void BinaryMeshFileReader::read_faces(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint32 count;
    checked_read(reader, count);

    for (uint32 i = 0; i < count; ++i)
        read_face(reader, builder);
}

void BinaryMeshFileReader::read_face(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint16 count;
    checked_read(reader, count);

    ensure_minimum_size(m_vertices, count);
    ensure_minimum_size(m_vertex_normals, count);
    ensure_minimum_size(m_tex_coords, count);

    for (uint16 i = 0; i < count; ++i)
    {
        uint32 face_vertex;
        checked_read(reader, face_vertex);
        m_vertices[i] = face_vertex;

        uint32 face_vertex_normal;
        checked_read(reader, face_vertex_normal);
        m_vertex_normals[i] = face_vertex_normal;

        uint32 face_tex_coords;
        checked_read(reader, face_tex_coords);
        m_tex_coords[i] = face_tex_coords;
    }

    uint16 material;
    checked_read(reader, material);

    builder.begin_face(count);
    builder.set_face_vertices(&m_vertices[0]);
    builder.set_face_vertex_normals(&m_vertex_normals[0]);
    builder.set_face_vertex_tex_coords(&m_tex_coords[0]);
    builder.set_face_material(material);
    builder.end_face();
}

}   // namespace foundation
<commit_msg>removed deprecation notice in comment.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "binarymeshfilereader.h"

// appleseed.foundation headers.
#include "foundation/core/exceptions/exception.h"
#include "foundation/core/exceptions/exceptionioerror.h"
#include "foundation/math/vector.h"
#include "foundation/mesh/imeshbuilder.h"
#include "foundation/platform/types.h"
#include "foundation/utility/bufferedfile.h"
#include "foundation/utility/memory.h"

// Standard headers.
#include <cstring>
#include <memory>

using namespace std;

namespace foundation
{

//
// BinaryMeshFileReader class implementation.
//

namespace
{
    struct ExceptionEOF : public Exception {};

    template <typename File>
    inline void checked_read(File& file, void* outbuf, const size_t size)
    {
        if (size == 0)
            return;

        const size_t bytes_read = file.read(outbuf, size);

        if (bytes_read == 0)
            throw ExceptionEOF();

        if (bytes_read < size)
            throw ExceptionIOError();
    }

    template <typename File, typename T>
    inline void checked_read(File& file, T& object)
    {
        checked_read(file, &object, sizeof(T));
    }
}

BinaryMeshFileReader::BinaryMeshFileReader(const string& filename)
  : m_filename(filename)
{
}

void BinaryMeshFileReader::read(IMeshBuilder& builder)
{
    BufferedFile file(
        m_filename.c_str(),
        BufferedFile::BinaryType,
        BufferedFile::ReadMode);

    if (!file.is_open())
        throw ExceptionIOError();

    read_and_check_signature(file);

    uint16 version;
    checked_read(file, version);

    auto_ptr<ReaderAdapter> reader;

    switch (version)
    {
      case 1:                       // uncompressed
        reader.reset(new PassthroughReaderAdapter(file));
        break;

      case 2:                       // LZO-compressed (deprecated)
        reader.reset(new LZOCompressedReaderAdapter(file));
        break;

      case 3:                       // LZ4-compressed
        reader.reset(new LZ4CompressedReaderAdapter(file));
        break;

      default:                      // unknown format
        throw ExceptionIOError();   // todo: throw better-qualified exception
    }

    read_meshes(*reader.get(), builder);
}

void BinaryMeshFileReader::read_and_check_signature(BufferedFile& file)
{
    static const char ExpectedSig[10] = { 'B', 'I', 'N', 'A', 'R', 'Y', 'M', 'E', 'S', 'H' };

    char signature[sizeof(ExpectedSig)];
    checked_read(file, signature, sizeof(signature));

    if (memcmp(signature, ExpectedSig, sizeof(ExpectedSig)))
        throw ExceptionIOError();   // todo: throw better-qualified exception
}

string BinaryMeshFileReader::read_string(ReaderAdapter& reader)
{
    uint16 length;
    checked_read(reader, length);

    string s;
    s.resize(length);
    checked_read(reader, &s[0], length);

    return s;
}

void BinaryMeshFileReader::read_meshes(ReaderAdapter& reader, IMeshBuilder& builder)
{
    try
    {
        while (true)
        {
            // Read the name of the next mesh.
            string mesh_name;
            try
            {
                mesh_name = read_string(reader);
            }
            catch (const ExceptionEOF&)
            {
                // Expected EOF.
                break;
            }

            builder.begin_mesh(mesh_name.c_str());

            read_vertices(reader, builder);
            read_vertex_normals(reader, builder);
            read_texture_coordinates(reader, builder);
            read_material_slots(reader, builder);
            read_faces(reader, builder);

            builder.end_mesh();
        }
    }
    catch (const ExceptionEOF&)
    {
        // Unexpected EOF.
        throw ExceptionIOError();
    }
}

void BinaryMeshFileReader::read_vertices(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint32 count;
    checked_read(reader, count);

    for (uint32 i = 0; i < count; ++i)
    {
        Vector3d v;
        checked_read(reader, v);
        builder.push_vertex(v);
    }
}

void BinaryMeshFileReader::read_vertex_normals(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint32 count;
    checked_read(reader, count);

    for (uint32 i = 0; i < count; ++i)
    {
        Vector3d v;
        checked_read(reader, v);
        builder.push_vertex_normal(v);
    }
}

void BinaryMeshFileReader::read_texture_coordinates(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint32 count;
    checked_read(reader, count);

    for (uint32 i = 0; i < count; ++i)
    {
        Vector2d v;
        checked_read(reader, v);
        builder.push_tex_coords(v);
    }
}

void BinaryMeshFileReader::read_material_slots(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint16 count;
    checked_read(reader, count);

    for (uint16 i = 0; i < count; ++i)
    {
        const string material_slot = read_string(reader);
        builder.push_material_slot(material_slot.c_str());
    }
}

void BinaryMeshFileReader::read_faces(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint32 count;
    checked_read(reader, count);

    for (uint32 i = 0; i < count; ++i)
        read_face(reader, builder);
}

void BinaryMeshFileReader::read_face(ReaderAdapter& reader, IMeshBuilder& builder)
{
    uint16 count;
    checked_read(reader, count);

    ensure_minimum_size(m_vertices, count);
    ensure_minimum_size(m_vertex_normals, count);
    ensure_minimum_size(m_tex_coords, count);

    for (uint16 i = 0; i < count; ++i)
    {
        uint32 face_vertex;
        checked_read(reader, face_vertex);
        m_vertices[i] = face_vertex;

        uint32 face_vertex_normal;
        checked_read(reader, face_vertex_normal);
        m_vertex_normals[i] = face_vertex_normal;

        uint32 face_tex_coords;
        checked_read(reader, face_tex_coords);
        m_tex_coords[i] = face_tex_coords;
    }

    uint16 material;
    checked_read(reader, material);

    builder.begin_face(count);
    builder.set_face_vertices(&m_vertices[0]);
    builder.set_face_vertex_normals(&m_vertex_normals[0]);
    builder.set_face_vertex_tex_coords(&m_tex_coords[0]);
    builder.set_face_material(material);
    builder.end_face();
}

}   // namespace foundation
<|endoftext|>


<commit_before>//============================================================================
// vSMC/include/vsmc/utility/aligned_memory.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2015, Yan Zhou
// 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.
//
// 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 HOLDER 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 VSMC_UTILITY_ALIGNED_MEMORY
#define VSMC_UTILITY_ALIGNED_MEMORY

#include <vsmc/internal/common.hpp>

#if VSMC_HAS_POSIX
#include <stdlib.h>
#elif defined(VSMC_MSVC)
#include <malloc.h>
#endif

#if VSMC_HAS_JEMALLOC
#include <stdlib.h>
#include <jemalloc/jemalloc.h>
#endif

#if VSMC_HAS_TBB_MALLOC
#include <tbb/scalable_allocator.h>
#endif

#if VSMC_HAS_MKL
#include <mkl_service.h>
#endif

/// \brief Default AlignedMemory type
/// \ingroup Config
#ifndef VSMC_ALIGNED_MEMORY_TYPE
#if VSMC_HAS_JEMALLOC
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryJE
#elif VSMC_HAS_TBB_MALLOC
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryTBB
#elif VSMC_HAS_MKL
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryMKL
#elif VSMC_HAS_POSIX || defined(VSMC_MSVC)
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySYS
#else
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySTD
#endif
#endif

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment) \
    VSMC_STATIC_ASSERT((Alignment != 0 && (Alignment & (Alignment - 1)) == 0),\
            USE_AlignedAllocator_WITH_ALIGNEMNT_NOT_A_POWER_OF_TWO)

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignemnt) \
    VSMC_STATIC_ASSERT((Alignment >= sizeof(void *)),                        \
            USE_AlignedAllocator_WITH_ALIGNMENT_LESS_THAN_SIZEOF_VOID_POINTER)

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY \
    VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment);    \
    VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignment);

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment) \
    VSMC_RUNTIME_ASSERT((alignment != 0 && (alignment & (alignment - 1)) == 0),\
            "**aligned_malloc** USED WITH ALIGNMENT NOT A POWER OF TWO")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignemnt) \
    VSMC_RUNTIME_ASSERT((alignment >= sizeof(void *)),                        \
            "**aligned_malloc** USED WITH ALIGNMENT LESS THAN sizeof(void *)")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment);    \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignment);

namespace vsmc {

/// \brief Aligned memory using `std::malloc` and `std::free`
/// \ingroup AlignedMemory
///
/// \details
/// Memory allocated through this class is aligned but some bytes might be
/// wasted in each allocation.
class AlignedMemorySTD
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *orig_ptr = std::malloc(n + alignment + sizeof(void *));
        if (orig_ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        uintptr_t address = reinterpret_cast<uintptr_t>(orig_ptr);
        uintptr_t offset = alignment - (address + sizeof(void *)) % alignment;
        void *ptr = reinterpret_cast<void *>(address + offset + sizeof(void *));
        void **orig = reinterpret_cast<void **>(address + offset);
        *orig = orig_ptr;

        return ptr;
    }

    static void aligned_free (void *ptr)
    {
        std::free(*reinterpret_cast<void **>(
                    reinterpret_cast<uintptr_t>(ptr) - sizeof(void *)));
    }
}; // class AlignedMemmorySTD

#if VSMC_HAS_POSIX

/// \brief Aligned memory using native system aligned memory allocation
/// \ingroup AlignedMemory
///
/// \details
/// This class use `posix_memalign` and `free` on POSIX systems (Mac OS X,
/// Linux, etc.) and `_aligned_malloc` and `_aligned_free` on Windows.
class AlignedMemorySYS
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr;
        if (posix_memalign(&ptr, alignment, n) != 0)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {free(ptr);}
}; // class AlignedMallocSYS

#elif defined(VSMC_MSVC)

class AlignedMemorySYS
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = _aligned_malloc(n, alignment);
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {_aligned_free(ptr);}
}; // class AlignedMemorySYS

#endif // VSMC_HAS_POSIX

#if VSMC_HAS_JEMALLOC

/// \brief Aligned memory using jemalloc
/// \ingroup AlignedMemory
class AlignedMemoryJE
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

#if VSMC_HAS_JEMALLOC_STDAPI
        void *ptr = aligned_alloc(alignment, n);
#else
        void *ptr = je_aligned_alloc(alignment, n);
#endif
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr)
    {
#if VSMC_HAS_JEMALLOC_STDAPI
        free(ptr);
#else
        je_free(ptr);
#endif
    }
}; // AlignedMemoryJE

#endif // VSMC_HAS_JEMALLOC

#if VSMC_HAS_TBB_MALLOC

/// \brief Aligned memory using Intel TBB `scalable_aligned_malloc` and
/// `scalable_aligned_free`.
/// \ingroup AlignedMemory
class AlignedMemoryTBB
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = scalable_aligned_malloc(n, alignment);
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {scalable_aligned_free(ptr);}
}; // class AlignedMemoryTBB

#endif // VSMC_HAS_TBB_MALLOC

#if VSMC_HAS_MKL

/// \brief Aligned memory using Intel MKL `mkl_malloc` and `mkl_free`
/// \ingroup AlignedMemory
class AlignedMemoryMKL
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = mkl_malloc(n, static_cast<int>(alignment));
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {mkl_free(ptr);}
}; // class AlignedMemoryMKL

#endif // VSMC_HAS_MKL

/// \brief Default AlignedMemory type
/// \ingroup AlignedMemory
typedef VSMC_ALIGNED_MEMORY_TYPE AlignedMemory;

/// \brief Aligned allocator
/// \ingroup AlignedMemory
///
/// \tparam T The value type
/// \tparam Alignment The alignment requirement of memory, must be a power of
/// two and no less than `sizeof(void *)`.
/// \tparam Memory The memory management class. Must provides two member
/// functions, `aligned_malloc` and `aligned_free`. The member function
/// `aligned_malloc` shall behave similar to `std::malloc` but take an
/// additional arguments for alignment. The member function `aligned_free`
/// shall behave just like `std::free`.
template <typename T, std::size_t Alignment = 32,
         typename Memory = AlignedMemory>
class AlignedAllocator : public std::allocator<T>
{
    public :

    typedef typename std::allocator<T>::size_type size_type;
    typedef typename std::allocator<T>::pointer pointer;

    template <typename U> struct rebind
    {typedef AlignedAllocator<U, Alignment> other;};

    AlignedAllocator () {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    AlignedAllocator (const AlignedAllocator<T, Alignment> &other) :
        std::allocator<T>(other)
    {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    template <typename U>
    AlignedAllocator (const AlignedAllocator<U, Alignment> &other) :
        std::allocator<T>(static_cast<std::allocator<U> >(other))
    {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    ~AlignedAllocator () {}

    pointer allocate (size_type n, const void * = VSMC_NULLPTR)
    {
        if (n == 0)
            return VSMC_NULLPTR;

        return static_cast<pointer>(
                memory_.aligned_malloc(sizeof(T) * n, Alignment));
    }

    void deallocate (pointer ptr, size_type)
    {
        if (ptr != VSMC_NULLPTR)
            memory_.aligned_free(ptr);
    }

    private :

    Memory memory_;
}; // class AlignedAllocator

} // namespace vsmc

#endif // VSMC_UTILITY_ALIGNED_MEMORY
<commit_msg>prefer tbb_malloc to jemalloc<commit_after>//============================================================================
// vSMC/include/vsmc/utility/aligned_memory.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2015, Yan Zhou
// 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.
//
// 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 HOLDER 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 VSMC_UTILITY_ALIGNED_MEMORY
#define VSMC_UTILITY_ALIGNED_MEMORY

#include <vsmc/internal/common.hpp>

#if VSMC_HAS_POSIX
#include <stdlib.h>
#elif defined(VSMC_MSVC)
#include <malloc.h>
#endif

#if VSMC_HAS_JEMALLOC
#include <stdlib.h>
#include <jemalloc/jemalloc.h>
#endif

#if VSMC_HAS_TBB_MALLOC
#include <tbb/scalable_allocator.h>
#endif

#if VSMC_HAS_MKL
#include <mkl_service.h>
#endif

/// \brief Default AlignedMemory type
/// \ingroup Config
#ifndef VSMC_ALIGNED_MEMORY_TYPE
#if VSMC_HAS_TBB_MALLOC
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryTBB
#elif VSMC_HAS_JEMALLOC
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryJE
#elif VSMC_HAS_MKL
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryMKL
#elif VSMC_HAS_POSIX || defined(VSMC_MSVC)
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySYS
#else
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySTD
#endif
#endif

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment) \
    VSMC_STATIC_ASSERT((Alignment != 0 && (Alignment & (Alignment - 1)) == 0),\
            USE_AlignedAllocator_WITH_ALIGNEMNT_NOT_A_POWER_OF_TWO)

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignemnt) \
    VSMC_STATIC_ASSERT((Alignment >= sizeof(void *)),                        \
            USE_AlignedAllocator_WITH_ALIGNMENT_LESS_THAN_SIZEOF_VOID_POINTER)

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY \
    VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment);    \
    VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignment);

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment) \
    VSMC_RUNTIME_ASSERT((alignment != 0 && (alignment & (alignment - 1)) == 0),\
            "**aligned_malloc** USED WITH ALIGNMENT NOT A POWER OF TWO")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignemnt) \
    VSMC_RUNTIME_ASSERT((alignment >= sizeof(void *)),                        \
            "**aligned_malloc** USED WITH ALIGNMENT LESS THAN sizeof(void *)")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment);    \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignment);

namespace vsmc {

/// \brief Aligned memory using `std::malloc` and `std::free`
/// \ingroup AlignedMemory
///
/// \details
/// Memory allocated through this class is aligned but some bytes might be
/// wasted in each allocation.
class AlignedMemorySTD
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *orig_ptr = std::malloc(n + alignment + sizeof(void *));
        if (orig_ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        uintptr_t address = reinterpret_cast<uintptr_t>(orig_ptr);
        uintptr_t offset = alignment - (address + sizeof(void *)) % alignment;
        void *ptr = reinterpret_cast<void *>(address + offset + sizeof(void *));
        void **orig = reinterpret_cast<void **>(address + offset);
        *orig = orig_ptr;

        return ptr;
    }

    static void aligned_free (void *ptr)
    {
        std::free(*reinterpret_cast<void **>(
                    reinterpret_cast<uintptr_t>(ptr) - sizeof(void *)));
    }
}; // class AlignedMemmorySTD

#if VSMC_HAS_POSIX

/// \brief Aligned memory using native system aligned memory allocation
/// \ingroup AlignedMemory
///
/// \details
/// This class use `posix_memalign` and `free` on POSIX systems (Mac OS X,
/// Linux, etc.) and `_aligned_malloc` and `_aligned_free` on Windows.
class AlignedMemorySYS
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr;
        if (posix_memalign(&ptr, alignment, n) != 0)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {free(ptr);}
}; // class AlignedMallocSYS

#elif defined(VSMC_MSVC)

class AlignedMemorySYS
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = _aligned_malloc(n, alignment);
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {_aligned_free(ptr);}
}; // class AlignedMemorySYS

#endif // VSMC_HAS_POSIX

#if VSMC_HAS_JEMALLOC

/// \brief Aligned memory using jemalloc
/// \ingroup AlignedMemory
class AlignedMemoryJE
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

#if VSMC_HAS_JEMALLOC_STDAPI
        void *ptr = aligned_alloc(alignment, n);
#else
        void *ptr = je_aligned_alloc(alignment, n);
#endif
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr)
    {
#if VSMC_HAS_JEMALLOC_STDAPI
        free(ptr);
#else
        je_free(ptr);
#endif
    }
}; // AlignedMemoryJE

#endif // VSMC_HAS_JEMALLOC

#if VSMC_HAS_TBB_MALLOC

/// \brief Aligned memory using Intel TBB `scalable_aligned_malloc` and
/// `scalable_aligned_free`.
/// \ingroup AlignedMemory
class AlignedMemoryTBB
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = scalable_aligned_malloc(n, alignment);
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {scalable_aligned_free(ptr);}
}; // class AlignedMemoryTBB

#endif // VSMC_HAS_TBB_MALLOC

#if VSMC_HAS_MKL

/// \brief Aligned memory using Intel MKL `mkl_malloc` and `mkl_free`
/// \ingroup AlignedMemory
class AlignedMemoryMKL
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = mkl_malloc(n, static_cast<int>(alignment));
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {mkl_free(ptr);}
}; // class AlignedMemoryMKL

#endif // VSMC_HAS_MKL

/// \brief Default AlignedMemory type
/// \ingroup AlignedMemory
typedef VSMC_ALIGNED_MEMORY_TYPE AlignedMemory;

/// \brief Aligned allocator
/// \ingroup AlignedMemory
///
/// \tparam T The value type
/// \tparam Alignment The alignment requirement of memory, must be a power of
/// two and no less than `sizeof(void *)`.
/// \tparam Memory The memory management class. Must provides two member
/// functions, `aligned_malloc` and `aligned_free`. The member function
/// `aligned_malloc` shall behave similar to `std::malloc` but take an
/// additional arguments for alignment. The member function `aligned_free`
/// shall behave just like `std::free`.
template <typename T, std::size_t Alignment = 32,
         typename Memory = AlignedMemory>
class AlignedAllocator : public std::allocator<T>
{
    public :

    typedef typename std::allocator<T>::size_type size_type;
    typedef typename std::allocator<T>::pointer pointer;

    template <typename U> struct rebind
    {typedef AlignedAllocator<U, Alignment> other;};

    AlignedAllocator () {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    AlignedAllocator (const AlignedAllocator<T, Alignment> &other) :
        std::allocator<T>(other)
    {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    template <typename U>
    AlignedAllocator (const AlignedAllocator<U, Alignment> &other) :
        std::allocator<T>(static_cast<std::allocator<U> >(other))
    {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    ~AlignedAllocator () {}

    pointer allocate (size_type n, const void * = VSMC_NULLPTR)
    {
        if (n == 0)
            return VSMC_NULLPTR;

        return static_cast<pointer>(
                memory_.aligned_malloc(sizeof(T) * n, Alignment));
    }

    void deallocate (pointer ptr, size_type)
    {
        if (ptr != VSMC_NULLPTR)
            memory_.aligned_free(ptr);
    }

    private :

    Memory memory_;
}; // class AlignedAllocator

} // namespace vsmc

#endif // VSMC_UTILITY_ALIGNED_MEMORY
<|endoftext|>


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

#include <cstdlib>
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>

#include <fc/filesystem.hpp>
#include <fc/smart_ref_impl.hpp>   // required for gcc in release mode
#include <fc/string.hpp>
#include <fc/io/fstream.hpp>
#include <fc/io/json.hpp>
#include <graphene/chain/genesis_state.hpp>
#include <graphene/chain/protocol/types.hpp>

// we need to include the world in order to serialize fee_parameters
#include <graphene/chain/protocol/fee_schedule.hpp>

using namespace graphene::chain;

static const char generated_file_banner[] =
"//                                   _           _    __ _ _        //\n"
"//                                  | |         | |  / _(_) |       //\n"
"//    __ _  ___ _ __   ___ _ __ __ _| |_ ___  __| | | |_ _| | ___   //\n"
"//   / _` |/ _ \\ '_ \\ / _ \\ '__/ _` | __/ _ \\/ _` | |  _| | |/ _ \\  //\n"
"//  | (_| |  __/ | | |  __/ | | (_| | ||  __/ (_| | | | | | |  __/  //\n"
"//   \\__, |\\___|_| |_|\\___|_|  \\__,_|\\__\\___|\\__,_| |_| |_|_|\\___|  //\n"
"//    __/ |                                                         //\n"
"//   |___/                                                          //\n"
"//                                                                  //\n"
"// Generated by:  libraries/chain_id/identify_chain.cpp             //\n"
"//                                                                  //\n"
"// Warning: This is a generated file, any changes made here will be //\n"
"// overwritten by the build process.  If you need to change what    //\n"
"// is generated here, you should use the CMake variable             //\n"
"// GRAPHENE_EGENESIS_JSON to specify an embedded genesis state.     //\n"
"//                                                                  //\n"
;

// hack:  import create_example_genesis() even though it's a way, way
// specific internal detail
namespace graphene { namespace app { namespace detail {
genesis_state_type create_example_genesis();
} } } // graphene::app::detail

fc::path get_path(
   const boost::program_options::variables_map& options,
   const std::string& name )
{
   fc::path result = options[name].as<boost::filesystem::path>();
   if( result.is_relative() )
      result = fc::current_path() / result;
   return result;
}

void convert_to_c_array(
   const std::string& src,
   std::string& dest,
   int width = 40 )
{
   dest.reserve( src.length() * 6 / 5 );
   bool needs_comma = false;
   int row = 0;
   for( std::string::size_type i=0; i<src.length(); i+=width )
   {
      std::string::size_type j = std::min( i+width, src.length() );
      if( needs_comma )
         dest.append(",\n");
      dest.append("\"");
      for( std::string::size_type k=i; k<j; k++ )
      {
         char c = src[k];
         switch(c)
         {
            // use most short escape sequences
            case '\"': dest.append("\\\""); break;
            case '\?': dest.append("\\\?"); break;
            case '\\': dest.append("\\\\"); break;
            case '\a': dest.append( "\\a"); break;
            case '\b': dest.append( "\\b"); break;
            case '\f': dest.append( "\\f"); break;
            case '\n': dest.append( "\\n"); break;
            case '\r': dest.append( "\\r"); break;
            case '\t': dest.append( "\\t"); break;
            case '\v': dest.append( "\\v"); break;

            // single quote and misc. ASCII is OK
            case '\'':
            case ' ': case '!': case '#': case '$': case '%': case '&': case '(': case ')':
            case '*': case '+': case ',': case '-': case '.': case '/':
            case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
            case ':': case ';': case '<': case '=': case '>': case '@':
            case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
            case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
            case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
            case '[': case ']': case '^': case '_': case '`':
            case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
            case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
            case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
            case '{': case '|': case '}': case '~':
               dest.append(&c, 1);
               break;

            // use shortest octal escape for everything else
            default:
               dest.append("\\");
               char dg[3];
               dg[0] = '0' + ((c >> 6) & 3);
               dg[1] = '0' + ((c >> 3) & 7);
               dg[2] = '0' + ((c     ) & 7);
               int start = (dg[0] == '0' ? (dg[1] == '0' ? 2 : 1) : 0);
               dest.append( dg+start, 3-start );
         }
      }
      dest.append("\"");
      needs_comma = true;
      row++;
   }
   std::cerr << "\n";
   return;
}

struct egenesis_info
{
   fc::optional< genesis_state_type > genesis;
   fc::optional< chain_id_type > chain_id;
   fc::optional< std::string > genesis_json;
   fc::optional< fc::sha256 > genesis_json_hash;
   fc::optional< std::string > genesis_json_array;
   int genesis_json_array_width,
       genesis_json_array_height;

   void fillin()
   {
      // must specify either genesis_json or genesis
      if( genesis.valid() )
      {
         if( !genesis_json.valid() )
            // If genesis_json not exist, generate from genesis
            genesis_json = fc::json::to_string( *genesis );
      }
      else if( genesis_json.valid() )
      {
         // If genesis not exist, generate from genesis_json
         genesis = fc::json::from_string( *genesis_json ).as< genesis_state_type >();
      }
      else
      {
         // Neither genesis nor genesis_json exists, crippled
         std::cerr << "embed_genesis:  Need genesis or genesis_json\n";
         exit(1);
      }
      // init genesis_json_hash from genesis_json
      if( !genesis_json_hash.valid() )
         genesis_json_hash = fc::sha256::hash( *genesis_json );
      // init chain_id from genesis_json_hash
      if( !chain_id.valid() )
         chain_id = genesis_json_hash;
      // init genesis_json_array from genesis_json
      if( !genesis_json_array.valid() )
      {
         genesis_json_array = std::string();
         // TODO: gzip
         int width = 40;
         convert_to_c_array( *genesis_json, *genesis_json_array, width );
         int height = (genesis_json->length() + width-1) / width;
         genesis_json_array_width = width;
         genesis_json_array_height = height;
      }
   }
};

void load_genesis(
   const boost::program_options::variables_map& options,
   egenesis_info& info
   )
{
   if( options.count("genesis-json") )
   {
      fc::path genesis_json_filename = get_path( options, "genesis-json" );
      std::cerr << "embed_genesis:  Reading genesis from file " << genesis_json_filename.preferred_string() << "\n";
      info.genesis_json = std::string();
      read_file_contents( genesis_json_filename, *info.genesis_json );
   }
   else
      info.genesis = graphene::app::detail::create_example_genesis();

   if( options.count("chain-id") )
   {
      std::string chain_id_str = options["chain-id"].as<std::string>();
      std::cerr << "embed_genesis:  Genesis ID from argument is " << chain_id_str << "\n";
      info.chain_id = chain_id_str;
   }
   return;
}

int main( int argc, char** argv )
{
   int main_return = 0;
   boost::program_options::options_description cli_options("Graphene Chain Identifier");
   cli_options.add_options()
      ("help,h", "Print this help message and exit.")
      ("genesis-json,g", boost::program_options::value<boost::filesystem::path>(), "File to read genesis state from")
      ("tmplsub,t", boost::program_options::value<std::vector< std::string > >()->composing(),
       "Given argument of form src.cpp.tmpl---dest.cpp, write dest.cpp expanding template invocations in src")
      ;

   boost::program_options::variables_map options;
   try
   {
      boost::program_options::store( boost::program_options::parse_command_line(argc, argv, cli_options), options );
   }
   catch (const boost::program_options::error& e)
   {
      std::cerr << "embed_genesis:  error parsing command line: " << e.what() << "\n";
      return 1;
   }

   if( options.count("help") )
   {
      std::cout << cli_options << "\n";
      return 0;
   }

   egenesis_info info;

   load_genesis( options, info );
   info.fillin();

   fc::mutable_variant_object template_context = fc::mutable_variant_object()
      ( "generated_file_banner", generated_file_banner )
      ( "chain_id", (*info.chain_id).str() )
      ;
   if( info.genesis_json.valid() )
   {
      template_context["genesis_json_length"] = info.genesis_json->length();
      template_context["genesis_json_array"] = (*info.genesis_json_array);
      template_context["genesis_json_hash"] = (*info.genesis_json_hash).str();
      template_context["genesis_json_array_width"] = info.genesis_json_array_width;
      template_context["genesis_json_array_height"] = info.genesis_json_array_height;
   }

   for( const std::string& src_dest : options["tmplsub"].as< std::vector< std::string > >() )
   {
      std::cerr << "embed_genesis:  parsing tmplsub parameter \"" << src_dest << "\"\n";
      size_t pos = src_dest.find( "---" );
      if( pos == std::string::npos )
      {
         std::cerr << "embed_genesis:  could not parse tmplsub parameter:  '---' not found\n";
         main_return = 1;
         continue;
      }
      std::string src = src_dest.substr( 0, pos );
      std::string dest = src_dest.substr( pos+3 );

      std::string tmpl;
      read_file_contents( fc::path( src ), tmpl );
      std::string out_str = fc::format_string( tmpl, template_context );
      fc::path dest_filename = fc::path( dest );
      fc::ofstream outfile( dest_filename );
      outfile.write( out_str.c_str(), out_str.size() );
      outfile.close();
   }

   return main_return;
}
<commit_msg>If there is an error parsing the genesis file in embed_genesis, print the exception before exiting.<commit_after>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <cstdlib>
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>

#include <fc/filesystem.hpp>
#include <fc/smart_ref_impl.hpp>   // required for gcc in release mode
#include <fc/string.hpp>
#include <fc/io/fstream.hpp>
#include <fc/io/json.hpp>
#include <graphene/chain/genesis_state.hpp>
#include <graphene/chain/protocol/types.hpp>

// we need to include the world in order to serialize fee_parameters
#include <graphene/chain/protocol/fee_schedule.hpp>

using namespace graphene::chain;

static const char generated_file_banner[] =
"//                                   _           _    __ _ _        //\n"
"//                                  | |         | |  / _(_) |       //\n"
"//    __ _  ___ _ __   ___ _ __ __ _| |_ ___  __| | | |_ _| | ___   //\n"
"//   / _` |/ _ \\ '_ \\ / _ \\ '__/ _` | __/ _ \\/ _` | |  _| | |/ _ \\  //\n"
"//  | (_| |  __/ | | |  __/ | | (_| | ||  __/ (_| | | | | | |  __/  //\n"
"//   \\__, |\\___|_| |_|\\___|_|  \\__,_|\\__\\___|\\__,_| |_| |_|_|\\___|  //\n"
"//    __/ |                                                         //\n"
"//   |___/                                                          //\n"
"//                                                                  //\n"
"// Generated by:  libraries/chain_id/identify_chain.cpp             //\n"
"//                                                                  //\n"
"// Warning: This is a generated file, any changes made here will be //\n"
"// overwritten by the build process.  If you need to change what    //\n"
"// is generated here, you should use the CMake variable             //\n"
"// GRAPHENE_EGENESIS_JSON to specify an embedded genesis state.     //\n"
"//                                                                  //\n"
;

// hack:  import create_example_genesis() even though it's a way, way
// specific internal detail
namespace graphene { namespace app { namespace detail {
genesis_state_type create_example_genesis();
} } } // graphene::app::detail

fc::path get_path(
   const boost::program_options::variables_map& options,
   const std::string& name )
{
   fc::path result = options[name].as<boost::filesystem::path>();
   if( result.is_relative() )
      result = fc::current_path() / result;
   return result;
}

void convert_to_c_array(
   const std::string& src,
   std::string& dest,
   int width = 40 )
{
   dest.reserve( src.length() * 6 / 5 );
   bool needs_comma = false;
   int row = 0;
   for( std::string::size_type i=0; i<src.length(); i+=width )
   {
      std::string::size_type j = std::min( i+width, src.length() );
      if( needs_comma )
         dest.append(",\n");
      dest.append("\"");
      for( std::string::size_type k=i; k<j; k++ )
      {
         char c = src[k];
         switch(c)
         {
            // use most short escape sequences
            case '\"': dest.append("\\\""); break;
            case '\?': dest.append("\\\?"); break;
            case '\\': dest.append("\\\\"); break;
            case '\a': dest.append( "\\a"); break;
            case '\b': dest.append( "\\b"); break;
            case '\f': dest.append( "\\f"); break;
            case '\n': dest.append( "\\n"); break;
            case '\r': dest.append( "\\r"); break;
            case '\t': dest.append( "\\t"); break;
            case '\v': dest.append( "\\v"); break;

            // single quote and misc. ASCII is OK
            case '\'':
            case ' ': case '!': case '#': case '$': case '%': case '&': case '(': case ')':
            case '*': case '+': case ',': case '-': case '.': case '/':
            case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
            case ':': case ';': case '<': case '=': case '>': case '@':
            case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
            case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
            case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
            case '[': case ']': case '^': case '_': case '`':
            case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
            case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
            case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
            case '{': case '|': case '}': case '~':
               dest.append(&c, 1);
               break;

            // use shortest octal escape for everything else
            default:
               dest.append("\\");
               char dg[3];
               dg[0] = '0' + ((c >> 6) & 3);
               dg[1] = '0' + ((c >> 3) & 7);
               dg[2] = '0' + ((c     ) & 7);
               int start = (dg[0] == '0' ? (dg[1] == '0' ? 2 : 1) : 0);
               dest.append( dg+start, 3-start );
         }
      }
      dest.append("\"");
      needs_comma = true;
      row++;
   }
   std::cerr << "\n";
   return;
}

struct egenesis_info
{
   fc::optional< genesis_state_type > genesis;
   fc::optional< chain_id_type > chain_id;
   fc::optional< std::string > genesis_json;
   fc::optional< fc::sha256 > genesis_json_hash;
   fc::optional< std::string > genesis_json_array;
   int genesis_json_array_width,
       genesis_json_array_height;

   void fillin()
   {
      // must specify either genesis_json or genesis
      if( genesis.valid() )
      {
         if( !genesis_json.valid() )
            // If genesis_json not exist, generate from genesis
            genesis_json = fc::json::to_string( *genesis );
      }
      else if( genesis_json.valid() )
      {
         // If genesis not exist, generate from genesis_json
         try
         {
            genesis = fc::json::from_string( *genesis_json ).as< genesis_state_type >();
         }
         catch (const fc::exception& e)
         {
            edump((e));
            throw;
         }
      }
      else
      {
         // Neither genesis nor genesis_json exists, crippled
         std::cerr << "embed_genesis:  Need genesis or genesis_json\n";
         exit(1);
      }
      // init genesis_json_hash from genesis_json
      if( !genesis_json_hash.valid() )
         genesis_json_hash = fc::sha256::hash( *genesis_json );
      // init chain_id from genesis_json_hash
      if( !chain_id.valid() )
         chain_id = genesis_json_hash;
      // init genesis_json_array from genesis_json
      if( !genesis_json_array.valid() )
      {
         genesis_json_array = std::string();
         // TODO: gzip
         int width = 40;
         convert_to_c_array( *genesis_json, *genesis_json_array, width );
         int height = (genesis_json->length() + width-1) / width;
         genesis_json_array_width = width;
         genesis_json_array_height = height;
      }
   }
};

void load_genesis(
   const boost::program_options::variables_map& options,
   egenesis_info& info
   )
{
   if( options.count("genesis-json") )
   {
      fc::path genesis_json_filename = get_path( options, "genesis-json" );
      std::cerr << "embed_genesis:  Reading genesis from file " << genesis_json_filename.preferred_string() << "\n";
      info.genesis_json = std::string();
      read_file_contents( genesis_json_filename, *info.genesis_json );
   }
   else
      info.genesis = graphene::app::detail::create_example_genesis();

   if( options.count("chain-id") )
   {
      std::string chain_id_str = options["chain-id"].as<std::string>();
      std::cerr << "embed_genesis:  Genesis ID from argument is " << chain_id_str << "\n";
      info.chain_id = chain_id_str;
   }
   return;
}

int main( int argc, char** argv )
{
   int main_return = 0;
   boost::program_options::options_description cli_options("Graphene Chain Identifier");
   cli_options.add_options()
      ("help,h", "Print this help message and exit.")
      ("genesis-json,g", boost::program_options::value<boost::filesystem::path>(), "File to read genesis state from")
      ("tmplsub,t", boost::program_options::value<std::vector< std::string > >()->composing(),
       "Given argument of form src.cpp.tmpl---dest.cpp, write dest.cpp expanding template invocations in src")
      ;

   boost::program_options::variables_map options;
   try
   {
      boost::program_options::store( boost::program_options::parse_command_line(argc, argv, cli_options), options );
   }
   catch (const boost::program_options::error& e)
   {
      std::cerr << "embed_genesis:  error parsing command line: " << e.what() << "\n";
      return 1;
   }

   if( options.count("help") )
   {
      std::cout << cli_options << "\n";
      return 0;
   }

   egenesis_info info;

   load_genesis( options, info );
   info.fillin();

   fc::mutable_variant_object template_context = fc::mutable_variant_object()
      ( "generated_file_banner", generated_file_banner )
      ( "chain_id", (*info.chain_id).str() )
      ;
   if( info.genesis_json.valid() )
   {
      template_context["genesis_json_length"] = info.genesis_json->length();
      template_context["genesis_json_array"] = (*info.genesis_json_array);
      template_context["genesis_json_hash"] = (*info.genesis_json_hash).str();
      template_context["genesis_json_array_width"] = info.genesis_json_array_width;
      template_context["genesis_json_array_height"] = info.genesis_json_array_height;
   }

   for( const std::string& src_dest : options["tmplsub"].as< std::vector< std::string > >() )
   {
      std::cerr << "embed_genesis:  parsing tmplsub parameter \"" << src_dest << "\"\n";
      size_t pos = src_dest.find( "---" );
      if( pos == std::string::npos )
      {
         std::cerr << "embed_genesis:  could not parse tmplsub parameter:  '---' not found\n";
         main_return = 1;
         continue;
      }
      std::string src = src_dest.substr( 0, pos );
      std::string dest = src_dest.substr( pos+3 );

      std::string tmpl;
      read_file_contents( fc::path( src ), tmpl );
      std::string out_str = fc::format_string( tmpl, template_context );
      fc::path dest_filename = fc::path( dest );
      fc::ofstream outfile( dest_filename );
      outfile.write( out_str.c_str(), out_str.size() );
      outfile.close();
   }

   return main_return;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef otbWrapperInputImageParameter_hxx
#define otbWrapperInputImageParameter_hxx

#include "otbWrapperInputImageParameter.h"

#include "otbClampImageFilter.h"

namespace otb
{
namespace Wrapper
{

#define CLAMP_IMAGE_IF( Out, In, image_base )	\
  {							\
    In * in_image = dynamic_cast< In * >( image_base );	\
							\
    if( in_image )						\
      return Cast< Out, In >( in_image );			\
  }

#define CLAMP_IMAGE_BASE( T, image_base )				\
  {									\
    CLAMP_IMAGE_IF( T, UInt8VectorImageType, image_base );		\
    CLAMP_IMAGE_IF( T, Int16VectorImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt16VectorImageType, image_base );	\
    CLAMP_IMAGE_IF( T, Int32VectorImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt32VectorImageType, image_base );	\
									\
    CLAMP_IMAGE_IF( T, FloatVectorImageType, image_base );		\
    CLAMP_IMAGE_IF( T, DoubleVectorImageType, image_base );	\
									\
    CLAMP_IMAGE_IF( T, ComplexInt16VectorImageType, image_base );	\
    CLAMP_IMAGE_IF( T, ComplexInt32VectorImageType, image_base );	\
									\
    CLAMP_IMAGE_IF( T, ComplexFloatVectorImageType, image_base );	\
    CLAMP_IMAGE_IF( T, ComplexDoubleVectorImageType, image_base );	\
    									\
    CLAMP_IMAGE_IF( T, UInt8RGBImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt8RGBAImageType, image_base );		\
									\
    CLAMP_IMAGE_IF( T, UInt8ImageType, image_base );		\
    CLAMP_IMAGE_IF( T, Int16ImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt16ImageType, image_base );		\
    CLAMP_IMAGE_IF( T, Int32ImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt32ImageType, image_base );		\
									\
    CLAMP_IMAGE_IF( T, FloatImageType, image_base );		\
    CLAMP_IMAGE_IF( T, DoubleImageType, image_base );		\
									\
    CLAMP_IMAGE_IF( T, ComplexInt16ImageType, image_base );	\
    CLAMP_IMAGE_IF( T, ComplexInt32ImageType, image_base );	\
									\
    CLAMP_IMAGE_IF( T, ComplexFloatImageType, image_base );	\
    CLAMP_IMAGE_IF( T, ComplexDoubleImageType, image_base );	\
									\
    return nullptr;							\
  }

template< typename TOutputImage,
	  typename TInputImage >
TOutputImage *
InputImageParameter
::Cast( TInputImage * image )
{
  // Optimize pipeline if input-image can be directly cast into
  // output-image.
  CLAMP_IMAGE_IF( TOutputImage, TInputImage, image );

  // Allocate and link pipeline in local scope before overwriting
  // member attributes in order to ensure exception safety.

  auto icif = InputClampImageFilter< TInputImage >::New();

  auto ocif = OutputClampImageFilter< TOutputImage >::New();

  icif->SetInput( image );

  ocif->SetInput( icif->GetOutput() );

  ocif->UpdateOutputInformation();

  m_InputCaster = icif;
  m_OutputCaster = ocif;

  return ocif->GetOutput();
}

template <class TImageType>
TImageType*
InputImageParameter::GetImage()
{
  // Used m_PreviousFileName because if not, when the user call twice GetImage,
  // it without changing the filename, it returns 2 different
  // image pointers
  // Only one image type can be used

  // 2 cases : the user set a filename vs. the user set an image
  if( m_UseFilename )
    {
    if( m_PreviousFileName!=m_FileName &&
	!m_FileName.empty() )
      {
      //////////////////////// Filename case:
      // A new valid filename has been given : a reader is created
      typedef otb::ImageFileReader<TImageType> ReaderType;

      typename ReaderType::Pointer reader = ReaderType::New();

      reader->SetFileName( m_FileName );

      reader->UpdateOutputInformation();

      m_Image = reader->GetOutput();
      m_Reader = reader;

      m_PreviousFileName = m_FileName;

      // Pay attention, don't return m_Image because it is a ImageBase...
      return reader->GetOutput();
      }
    else
      {
      // In this case, the reader and the image should already be there
      if (m_Image.IsNull())
        {
        itkExceptionMacro("No input image or filename detected...");
        }
      else
        {
        // Check if the image type asked here is the same as the one used for the reader
        if (dynamic_cast<TImageType*> (m_Image.GetPointer()))
          {
          return dynamic_cast<TImageType*> (m_Image.GetPointer());
          }
        else
          {
          itkExceptionMacro("Cannot ask a different image type");
          }
        }
      }
    }

  else
    {
    //////////////////////// Image case:
    if (m_Image.IsNull())
      {
      return nullptr;
      }
    else
      CLAMP_IMAGE_BASE( TImageType, m_Image.GetPointer() );

#if 0
    {
      if (dynamic_cast<UInt8ImageType*> (m_Image.GetPointer()))
        {
        return CastImage<UInt8ImageType, TImageType> ();
        }
      else if (dynamic_cast<Int16ImageType*> (m_Image.GetPointer()))
        {
        return CastImage<Int16ImageType, TImageType> ();
        }
      else if (dynamic_cast<UInt16ImageType*> (m_Image.GetPointer()))
        {
        return CastImage<UInt16ImageType, TImageType> ();
        }
      else if (dynamic_cast<Int32ImageType*> (m_Image.GetPointer()))
        {
        return CastImage<Int32ImageType, TImageType> ();
        }
      else if (dynamic_cast<UInt32ImageType*> (m_Image.GetPointer()))
        {
        return CastImage<UInt32ImageType, TImageType> ();
        }
      else if (dynamic_cast<FloatImageType*> (m_Image.GetPointer()))
        {
        return CastImage<FloatImageType, TImageType> ();
        }
      else if (dynamic_cast<DoubleImageType*> (m_Image.GetPointer()))
        {
        return CastImage<DoubleImageType, TImageType> ();
        }
      else if (dynamic_cast<ComplexInt16ImageType*>(m_Image.GetPointer()))
        {
        return CastImage<ComplexInt16ImageType, TImageType>();
        }
      else if (dynamic_cast<ComplexInt32ImageType*>(m_Image.GetPointer()))
        {
        return CastImage<ComplexInt32ImageType, TImageType>();
        }
      else if (dynamic_cast<ComplexFloatImageType*>(m_Image.GetPointer()))
        {
        return CastImage<ComplexFloatImageType, TImageType>();
        }
      else if (dynamic_cast<ComplexDoubleImageType*>(m_Image.GetPointer()))
        {
        return CastImage<ComplexDoubleImageType, TImageType>();
        }
      else if (dynamic_cast<UInt8VectorImageType*> (m_Image.GetPointer()))
        {
        return CastImage<UInt8VectorImageType, TImageType> ();
        }
      else if (dynamic_cast<Int16VectorImageType*> (m_Image.GetPointer()))
        {
        return CastImage<Int16VectorImageType, TImageType> ();
        }
      else if (dynamic_cast<UInt16VectorImageType*> (m_Image.GetPointer()))
        {
        return CastImage<UInt16VectorImageType, TImageType> ();
        }
      else if (dynamic_cast<Int32VectorImageType*> (m_Image.GetPointer()))
        {
        return CastImage<Int32VectorImageType, TImageType> ();
        }
      else if (dynamic_cast<UInt32VectorImageType*> (m_Image.GetPointer()))
        {
        return CastImage<UInt32VectorImageType, TImageType> ();
        }
      else if (dynamic_cast<FloatVectorImageType*> (m_Image.GetPointer()))
        {
        return CastImage<FloatVectorImageType, TImageType> ();
        }
      else if (dynamic_cast<DoubleVectorImageType*> (m_Image.GetPointer()))
        {
        return CastImage<DoubleVectorImageType, TImageType> ();
        }
      else if (dynamic_cast<UInt8RGBAImageType*> (m_Image.GetPointer()))
        {
        return CastImage<UInt8RGBAImageType, TImageType> ();
        }
      else if (dynamic_cast<UInt8RGBImageType*> (m_Image.GetPointer()))
        {
        return CastImage<UInt8RGBImageType, TImageType> ();
        }
      else if (dynamic_cast<ComplexInt16VectorImageType*>(m_Image.GetPointer()))
        {
        return CastImage<ComplexInt16VectorImageType, TImageType>();
        }
      else if (dynamic_cast<ComplexInt32VectorImageType*>(m_Image.GetPointer()))
        {
        return CastImage<ComplexInt32VectorImageType, TImageType>();
        }
      else if (dynamic_cast<ComplexFloatVectorImageType*>(m_Image.GetPointer()))
        {
        return CastImage<ComplexFloatVectorImageType, TImageType>();
        }
      else if (dynamic_cast<ComplexDoubleVectorImageType*>(m_Image.GetPointer()))
        {
        return CastImage<ComplexDoubleVectorImageType, TImageType>();
        }
      else
        {
	return nullptr;
        }
      }
#endif
    }
}

/** declare a specialization for ImageBaseType */
template <>
OTBApplicationEngine_EXPORT
ImageBaseType*
InputImageParameter::GetImage<ImageBaseType>();

#if 0

template <class TInputImage, class TOutputImage>
TOutputImage*
InputImageParameter::CastImage()
{
  if ( dynamic_cast<TOutputImage*> (m_Image.GetPointer()) )
    {
    return dynamic_cast<TOutputImage*> (m_Image.GetPointer());
    }
  else
    {
    TInputImage* realInputImage = dynamic_cast<TInputImage*>(m_Image.GetPointer());

    typedef ClampImageFilter<TInputImage, TOutputImage> CasterType;
    typename CasterType::Pointer caster = CasterType::New();

    caster->SetInput(realInputImage);
    caster->UpdateOutputInformation();

    m_Image = caster->GetOutput();
    m_Caster = caster;

    return caster->GetOutput();
    }
  // itkExceptionMacro("Cast from "<<typeid(TInputImage).name()<<" to "<<typeid(TOutputImage).name()<<" not authorized.");
}

#endif

} // End namespace Wrapper
} // End namespace otb

#endif
<commit_msg>REFAC: 1649: Removed dead-code.<commit_after>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef otbWrapperInputImageParameter_hxx
#define otbWrapperInputImageParameter_hxx

#include "otbWrapperInputImageParameter.h"

#include "otbClampImageFilter.h"

namespace otb
{
namespace Wrapper
{

#define CLAMP_IMAGE_IF( Out, In, image_base )	\
  {							\
    In * in_image = dynamic_cast< In * >( image_base );	\
							\
    if( in_image )						\
      return Cast< Out, In >( in_image );			\
  }

#define CLAMP_IMAGE_BASE( T, image_base )				\
  {									\
    CLAMP_IMAGE_IF( T, UInt8VectorImageType, image_base );		\
    CLAMP_IMAGE_IF( T, Int16VectorImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt16VectorImageType, image_base );	\
    CLAMP_IMAGE_IF( T, Int32VectorImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt32VectorImageType, image_base );	\
									\
    CLAMP_IMAGE_IF( T, FloatVectorImageType, image_base );		\
    CLAMP_IMAGE_IF( T, DoubleVectorImageType, image_base );	\
									\
    CLAMP_IMAGE_IF( T, ComplexInt16VectorImageType, image_base );	\
    CLAMP_IMAGE_IF( T, ComplexInt32VectorImageType, image_base );	\
									\
    CLAMP_IMAGE_IF( T, ComplexFloatVectorImageType, image_base );	\
    CLAMP_IMAGE_IF( T, ComplexDoubleVectorImageType, image_base );	\
    									\
    CLAMP_IMAGE_IF( T, UInt8RGBImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt8RGBAImageType, image_base );		\
									\
    CLAMP_IMAGE_IF( T, UInt8ImageType, image_base );		\
    CLAMP_IMAGE_IF( T, Int16ImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt16ImageType, image_base );		\
    CLAMP_IMAGE_IF( T, Int32ImageType, image_base );		\
    CLAMP_IMAGE_IF( T, UInt32ImageType, image_base );		\
									\
    CLAMP_IMAGE_IF( T, FloatImageType, image_base );		\
    CLAMP_IMAGE_IF( T, DoubleImageType, image_base );		\
									\
    CLAMP_IMAGE_IF( T, ComplexInt16ImageType, image_base );	\
    CLAMP_IMAGE_IF( T, ComplexInt32ImageType, image_base );	\
									\
    CLAMP_IMAGE_IF( T, ComplexFloatImageType, image_base );	\
    CLAMP_IMAGE_IF( T, ComplexDoubleImageType, image_base );	\
									\
    return nullptr;							\
  }

template< typename TOutputImage,
	  typename TInputImage >
TOutputImage *
InputImageParameter
::Cast( TInputImage * image )
{
  // Optimize pipeline if input-image can be directly cast into
  // output-image.
  CLAMP_IMAGE_IF( TOutputImage, TInputImage, image );

  // Allocate and link pipeline in local scope before overwriting
  // member attributes in order to ensure exception safety.

  auto icif = InputClampImageFilter< TInputImage >::New();

  auto ocif = OutputClampImageFilter< TOutputImage >::New();

  icif->SetInput( image );

  ocif->SetInput( icif->GetOutput() );

  ocif->UpdateOutputInformation();

  m_InputCaster = icif;
  m_OutputCaster = ocif;

  return ocif->GetOutput();
}

template <class TImageType>
TImageType*
InputImageParameter::GetImage()
{
  // Used m_PreviousFileName because if not, when the user call twice GetImage,
  // it without changing the filename, it returns 2 different
  // image pointers
  // Only one image type can be used

  // 2 cases : the user set a filename vs. the user set an image
  if( m_UseFilename )
    {
    if( m_PreviousFileName!=m_FileName &&
	!m_FileName.empty() )
      {
      //////////////////////// Filename case:
      // A new valid filename has been given : a reader is created
      typedef otb::ImageFileReader<TImageType> ReaderType;

      typename ReaderType::Pointer reader = ReaderType::New();

      reader->SetFileName( m_FileName );

      reader->UpdateOutputInformation();

      m_Image = reader->GetOutput();
      m_Reader = reader;

      m_PreviousFileName = m_FileName;

      // Pay attention, don't return m_Image because it is a ImageBase...
      return reader->GetOutput();
      }
    else
      {
      // In this case, the reader and the image should already be there
      if (m_Image.IsNull())
        {
        itkExceptionMacro("No input image or filename detected...");
        }
      else
        {
        // Check if the image type asked here is the same as the one used for the reader
        if (dynamic_cast<TImageType*> (m_Image.GetPointer()))
          {
          return dynamic_cast<TImageType*> (m_Image.GetPointer());
          }
        else
          {
          itkExceptionMacro("Cannot ask a different image type");
          }
        }
      }
    }

  else
    {
    //////////////////////// Image case:
    if (m_Image.IsNull())
      {
      return nullptr;
      }
    else
      CLAMP_IMAGE_BASE( TImageType, m_Image.GetPointer() );
    }
}

/** declare a specialization for ImageBaseType */
template <>
OTBApplicationEngine_EXPORT
ImageBaseType*
InputImageParameter::GetImage<ImageBaseType>();

} // End namespace Wrapper
} // End namespace otb

#endif
<|endoftext|>