<commit_before>/* Copyright 2017 https://github.com/mandreyel
 *
 * 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.
 */

#ifndef MIO_BASIC_MMAP_IMPL
#define MIO_BASIC_MMAP_IMPL

#include "basic_mmap.hpp"
#include "string_util.hpp"
#include "../page.hpp"

#include <algorithm>
#include <cstdint>

#ifndef _WIN32
# include <unistd.h>
# include <fcntl.h>
# include <sys/mman.h>
# include <sys/stat.h>
#endif

namespace mio {
namespace detail {

// Generic handle type for use by free functions.
using handle_type = basic_mmap<char>::handle_type;

#if defined(_WIN32)
inline DWORD int64_high(int64_t n) noexcept
{
    return n >> 32;
}

inline DWORD int64_low(int64_t n) noexcept
{
    return n & 0xff'ff'ff'ff;
}
#endif

inline std::error_code last_error() noexcept
{
    std::error_code error;
#ifdef _WIN32
    error.assign(GetLastError(), std::system_category());
#else
    error.assign(errno, std::system_category());
#endif
    return error;
}

template<typename Path>
handle_type open_file(const Path& path, const access_mode mode, std::error_code& error)
{
    error.clear();
    if(detail::empty(path))
    {
        error = std::make_error_code(std::errc::invalid_argument);
        return INVALID_HANDLE_VALUE;
    }
#if defined(_WIN32)
    const auto handle = ::CreateFile(c_str(path),
        mode == access_mode::read_only ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        0,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        0);
#else
    const auto handle = ::open(c_str(path),
        mode == access_mode::read_only ? O_RDONLY : O_RDWR);
#endif
    if(handle == INVALID_HANDLE_VALUE)
    {
        error = last_error();
    }
    return handle;
}

int64_t query_file_size(handle_type handle, std::error_code& error)
{
    error.clear();
#ifdef _WIN32
    LARGE_INTEGER file_size;
    if(::GetFileSizeEx(handle, &file_size) == 0)
    {
        error = last_error();
        return 0;
    }
	return static_cast<int64_t>(file_size.QuadPart);
#else
    struct stat sbuf;
    if(::fstat(handle, &sbuf) == -1)
    {
        error = last_error();
        return 0;
    }
    return sbuf.st_size;
#endif
}

// -- basic_mmap --

template<typename CharT, typename CharTraits>
basic_mmap<CharT, CharTraits>::~basic_mmap()
{
    unmap();
}

template<typename CharT, typename CharTraits>
basic_mmap<CharT, CharTraits>::basic_mmap(basic_mmap<CharT, CharTraits>&& other)
    : data_(std::move(other.data_))
    , length_(std::move(other.length_))
    , mapped_length_(std::move(other.mapped_length_))
    , file_handle_(std::move(other.file_handle_))
#ifdef _WIN32
    , file_mapping_handle_(std::move(other.file_mapping_handle_))
#endif
    , is_handle_internal_(std::move(other.is_handle_internal_))
{
    other.data_ = nullptr;
    other.length_ = other.mapped_length_ = 0;
    other.file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32
    other.file_mapping_handle_ = INVALID_HANDLE_VALUE;
#endif
}

template<typename CharT, typename CharTraits>
basic_mmap<CharT, CharTraits>& basic_mmap<CharT, CharTraits>::operator=(basic_mmap<CharT, CharTraits>&& other)
{
    if(this != &other)
    {
        // First the existing mapping needs to be removed.
        unmap();
        data_ = std::move(other.data_);
        length_ = std::move(other.length_);
        mapped_length_ = std::move(other.mapped_length_);
        file_handle_ = std::move(other.file_handle_);
#ifdef _WIN32
        file_mapping_handle_ = std::move(other.file_mapping_handle_);
#endif
        is_handle_internal_ = std::move(other.is_handle_internal_);

        // The moved from basic_mmap's fields need to be reset, because otherwise other's
        // destructor will unmap the same mapping that was just moved into this.
        other.data_ = nullptr;
        other.length_ = other.mapped_length_ = 0;
        other.file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32
        other.file_mapping_handle_ = INVALID_HANDLE_VALUE;
#endif
        other.is_handle_internal_ = false;
    }
    return *this;
}

template<typename CharT, typename CharTraits>
typename basic_mmap<CharT, CharTraits>::handle_type
basic_mmap<CharT, CharTraits>::mapping_handle() const noexcept
{
#ifdef _WIN32
    return file_mapping_handle_;
#else
    return file_handle_;
#endif
}

template<typename CharT, typename CharTraits>
template<typename String>
void basic_mmap<CharT, CharTraits>::map(String& path, size_type offset,
    size_type length, access_mode mode, std::error_code& error)
{
    error.clear();
    if(detail::empty(path))
    {
        error = std::make_error_code(std::errc::invalid_argument);
        return;
    }
    if(!is_open())
    {
        const auto handle = open_file(path, mode, error);
        if(error) { return; }
        map(handle, offset, length, mode, error);
        // MUST be after the call to map, as that sets this to true.
        is_handle_internal_ = true;
    }
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::map(handle_type handle, size_type offset,
    size_type length, access_mode mode, std::error_code& error)
{
    error.clear();
    if(handle == INVALID_HANDLE_VALUE)
    {
        error = std::make_error_code(std::errc::bad_file_descriptor);
        return;
    }

    const auto file_size = query_file_size(handle, error);
    if(error) { return; }

    if(length <= use_full_file_size)
    {
        length = file_size;
    }
    else if(offset + length > file_size)
    {
        error = std::make_error_code(std::errc::invalid_argument);
        return;
    }

    file_handle_ = handle;
    is_handle_internal_ = false;
    map(offset, length, mode, error);
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::map(const size_type offset, const size_type length,
    const access_mode mode, std::error_code& error)
{
    const size_type aligned_offset = make_offset_page_aligned(offset);
    const size_type length_to_map = offset - aligned_offset + length;
#if defined(_WIN32)
    const size_type max_file_size = offset + length;
    file_mapping_handle_ = ::CreateFileMapping(
        file_handle_,
        0,
        mode == access_mode::read_only ? PAGE_READONLY : PAGE_READWRITE,
        int64_high(max_file_size),
        int64_low(max_file_size),
        0);
    if(file_mapping_handle_ == INVALID_HANDLE_VALUE)
    {
        error = last_error();
        return;
    }

    const pointer mapping_start = static_cast<pointer>(::MapViewOfFile(
        file_mapping_handle_,
        mode == access_mode::read_only ? FILE_MAP_READ : FILE_MAP_WRITE,
        int64_high(aligned_offset),
        int64_low(aligned_offset),
        length_to_map));
    if(mapping_start == nullptr)
    {
        error = last_error();
        return;
    }
#else
    const pointer mapping_start = static_cast<pointer>(::mmap(
        0, // Don't give hint as to where to map.
        length_to_map,
        mode == access_mode::read_only ? PROT_READ : PROT_WRITE,
        MAP_SHARED, // TODO do we want to share it?
        file_handle_,
        aligned_offset));
    if(mapping_start == MAP_FAILED)
    {
        error = last_error();
        return;
    }
#endif
    data_ = mapping_start + offset - aligned_offset;
    length_ = length;
    mapped_length_ = length_to_map;
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::sync(std::error_code& error)
{
    error.clear();
    if(!is_open())
    {
        error = std::make_error_code(std::errc::bad_file_descriptor);
        return;
    }

    if(data() != nullptr)
    {
#ifdef _WIN32
        if(::FlushViewOfFile(get_mapping_start(), mapped_length_) == 0
           || ::FlushFileBuffers(file_handle_) == 0)
#else
        if(::msync(get_mapping_start(), mapped_length_, MS_SYNC) != 0)
#endif
        {
            error = last_error();
            return;
        }
    }
#ifdef _WIN32
    if(::FlushFileBuffers(file_handle_) == 0)
    {
        error = last_error();
    }
#endif
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::unmap()
{
    if(!is_open()) { return; }
    // TODO do we care about errors here?
#ifdef _WIN32
    if(is_mapped())
    {
        ::UnmapViewOfFile(get_mapping_start());
        ::CloseHandle(file_mapping_handle_);
        file_mapping_handle_ = INVALID_HANDLE_VALUE;
    }
#else
    if(data_) { ::munmap(const_cast<pointer>(get_mapping_start()), mapped_length_); }
#endif

    // If file handle was obtained by our opening it (when map is called with a path,
    // rather than an existing file handle), we need to close it, otherwise it must not
    // be closed as it may still be used outside of this basic_mmap instance.
    if(is_handle_internal_)
    {
#ifdef _WIN32
        ::CloseHandle(file_handle_);
#else
        ::close(file_handle_);
#endif
    }

    // Reset fields to their default values.
    data_ = nullptr;
    length_ = mapped_length_ = 0;
    file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32
    file_mapping_handle_ = INVALID_HANDLE_VALUE;
#endif
}

template<typename CharT, typename CharTraits>
typename basic_mmap<CharT, CharTraits>::pointer
basic_mmap<CharT, CharTraits>::get_mapping_start() noexcept
{
    if(!data_) { return nullptr; }
    const auto offset = mapped_length_ - length_;
    return data_ - offset;
}

template<typename CharT, typename CharTraits>
bool basic_mmap<CharT, CharTraits>::is_open() const noexcept
{
    return file_handle_ != INVALID_HANDLE_VALUE;
}

template<typename CharT, typename CharTraits>
bool basic_mmap<CharT, CharTraits>::is_mapped() const noexcept
{
#ifdef _WIN32
    return file_mapping_handle_ != INVALID_HANDLE_VALUE;
#else
    return is_open();
#endif
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::swap(basic_mmap<CharT, CharTraits>& other)
{
    if(this != &other)
    {
        using std::swap;
        swap(data_, other.data_);
        swap(file_handle_, other.file_handle_);
#ifdef _WIN32
        swap(file_mapping_handle_, other.file_mapping_handle_);
#endif
        swap(length_, other.length_);
        swap(mapped_length_, other.mapped_length_);
        swap(is_handle_internal_, other.is_handle_internal_);
    }
}

template<typename CharT, typename CharTraits>
bool operator==(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return a.size() == b.size()
        && CharTraits::compare(a.data(), b.data(), a.size()) == 0;
}

template<typename CharT, typename CharTraits>
bool operator!=(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return !(a == b);
}

/*
template<typename CharT, typename CharTraits>
bool operator<(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return CharTraits::compare(a.data(), b.data(), a.size()) < 0;
}

// TODO optimize
template<typename CharT, typename CharTraits>
bool operator<=(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return (a == b) || (a < b);
}

template<typename CharT, typename CharTraits>
bool operator>(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return CharTraits::compare(a.data(), b.data(), a.size()) > 0;
}

// TODO optimize
template<typename CharT, typename CharTraits>
bool operator>=(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return (a == b) || (a > b);
}
*/

} // namespace detail
} // namespace mio

#endif // MIO_BASIC_MMAP_IMPL
<commit_msg>fixed mult.def. linking error<commit_after>/* Copyright 2017 https://github.com/mandreyel
 *
 * 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.
 */

#ifndef MIO_BASIC_MMAP_IMPL
#define MIO_BASIC_MMAP_IMPL

#include "basic_mmap.hpp"
#include "string_util.hpp"
#include "../page.hpp"

#include <algorithm>
#include <cstdint>

#ifndef _WIN32
# include <unistd.h>
# include <fcntl.h>
# include <sys/mman.h>
# include <sys/stat.h>
#endif

namespace mio {
namespace detail {

// Generic handle type for use by free functions.
using handle_type = basic_mmap<char>::handle_type;

#if defined(_WIN32)
inline DWORD int64_high(int64_t n) noexcept
{
    return n >> 32;
}

inline DWORD int64_low(int64_t n) noexcept
{
    return n & 0xff'ff'ff'ff;
}
#endif

inline std::error_code last_error() noexcept
{
    std::error_code error;
#ifdef _WIN32
    error.assign(GetLastError(), std::system_category());
#else
    error.assign(errno, std::system_category());
#endif
    return error;
}

template<typename Path>
handle_type open_file(const Path& path, const access_mode mode, std::error_code& error)
{
    error.clear();
    if(detail::empty(path))
    {
        error = std::make_error_code(std::errc::invalid_argument);
        return INVALID_HANDLE_VALUE;
    }
#if defined(_WIN32)
    const auto handle = ::CreateFile(c_str(path),
        mode == access_mode::read_only ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        0,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        0);
#else
    const auto handle = ::open(c_str(path),
        mode == access_mode::read_only ? O_RDONLY : O_RDWR);
#endif
    if(handle == INVALID_HANDLE_VALUE)
    {
        error = last_error();
    }
    return handle;
}

inline int64_t query_file_size(handle_type handle, std::error_code& error)
{
    error.clear();
#ifdef _WIN32
    LARGE_INTEGER file_size;
    if(::GetFileSizeEx(handle, &file_size) == 0)
    {
        error = last_error();
        return 0;
    }
	return static_cast<int64_t>(file_size.QuadPart);
#else
    struct stat sbuf;
    if(::fstat(handle, &sbuf) == -1)
    {
        error = last_error();
        return 0;
    }
    return sbuf.st_size;
#endif
}

// -- basic_mmap --

template<typename CharT, typename CharTraits>
basic_mmap<CharT, CharTraits>::~basic_mmap()
{
    unmap();
}

template<typename CharT, typename CharTraits>
basic_mmap<CharT, CharTraits>::basic_mmap(basic_mmap<CharT, CharTraits>&& other)
    : data_(std::move(other.data_))
    , length_(std::move(other.length_))
    , mapped_length_(std::move(other.mapped_length_))
    , file_handle_(std::move(other.file_handle_))
#ifdef _WIN32
    , file_mapping_handle_(std::move(other.file_mapping_handle_))
#endif
    , is_handle_internal_(std::move(other.is_handle_internal_))
{
    other.data_ = nullptr;
    other.length_ = other.mapped_length_ = 0;
    other.file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32
    other.file_mapping_handle_ = INVALID_HANDLE_VALUE;
#endif
}

template<typename CharT, typename CharTraits>
basic_mmap<CharT, CharTraits>& basic_mmap<CharT, CharTraits>::operator=(basic_mmap<CharT, CharTraits>&& other)
{
    if(this != &other)
    {
        // First the existing mapping needs to be removed.
        unmap();
        data_ = std::move(other.data_);
        length_ = std::move(other.length_);
        mapped_length_ = std::move(other.mapped_length_);
        file_handle_ = std::move(other.file_handle_);
#ifdef _WIN32
        file_mapping_handle_ = std::move(other.file_mapping_handle_);
#endif
        is_handle_internal_ = std::move(other.is_handle_internal_);

        // The moved from basic_mmap's fields need to be reset, because otherwise other's
        // destructor will unmap the same mapping that was just moved into this.
        other.data_ = nullptr;
        other.length_ = other.mapped_length_ = 0;
        other.file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32
        other.file_mapping_handle_ = INVALID_HANDLE_VALUE;
#endif
        other.is_handle_internal_ = false;
    }
    return *this;
}

template<typename CharT, typename CharTraits>
typename basic_mmap<CharT, CharTraits>::handle_type
basic_mmap<CharT, CharTraits>::mapping_handle() const noexcept
{
#ifdef _WIN32
    return file_mapping_handle_;
#else
    return file_handle_;
#endif
}

template<typename CharT, typename CharTraits>
template<typename String>
void basic_mmap<CharT, CharTraits>::map(String& path, size_type offset,
    size_type length, access_mode mode, std::error_code& error)
{
    error.clear();
    if(detail::empty(path))
    {
        error = std::make_error_code(std::errc::invalid_argument);
        return;
    }
    if(!is_open())
    {
        const auto handle = open_file(path, mode, error);
        if(error) { return; }
        map(handle, offset, length, mode, error);
        // MUST be after the call to map, as that sets this to true.
        is_handle_internal_ = true;
    }
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::map(handle_type handle, size_type offset,
    size_type length, access_mode mode, std::error_code& error)
{
    error.clear();
    if(handle == INVALID_HANDLE_VALUE)
    {
        error = std::make_error_code(std::errc::bad_file_descriptor);
        return;
    }

    const auto file_size = query_file_size(handle, error);
    if(error) { return; }

    if(length <= use_full_file_size)
    {
        length = file_size;
    }
    else if(offset + length > file_size)
    {
        error = std::make_error_code(std::errc::invalid_argument);
        return;
    }

    file_handle_ = handle;
    is_handle_internal_ = false;
    map(offset, length, mode, error);
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::map(const size_type offset, const size_type length,
    const access_mode mode, std::error_code& error)
{
    const size_type aligned_offset = make_offset_page_aligned(offset);
    const size_type length_to_map = offset - aligned_offset + length;
#if defined(_WIN32)
    const size_type max_file_size = offset + length;
    file_mapping_handle_ = ::CreateFileMapping(
        file_handle_,
        0,
        mode == access_mode::read_only ? PAGE_READONLY : PAGE_READWRITE,
        int64_high(max_file_size),
        int64_low(max_file_size),
        0);
    if(file_mapping_handle_ == INVALID_HANDLE_VALUE)
    {
        error = last_error();
        return;
    }

    const pointer mapping_start = static_cast<pointer>(::MapViewOfFile(
        file_mapping_handle_,
        mode == access_mode::read_only ? FILE_MAP_READ : FILE_MAP_WRITE,
        int64_high(aligned_offset),
        int64_low(aligned_offset),
        length_to_map));
    if(mapping_start == nullptr)
    {
        error = last_error();
        return;
    }
#else
    const pointer mapping_start = static_cast<pointer>(::mmap(
        0, // Don't give hint as to where to map.
        length_to_map,
        mode == access_mode::read_only ? PROT_READ : PROT_WRITE,
        MAP_SHARED, // TODO do we want to share it?
        file_handle_,
        aligned_offset));
    if(mapping_start == MAP_FAILED)
    {
        error = last_error();
        return;
    }
#endif
    data_ = mapping_start + offset - aligned_offset;
    length_ = length;
    mapped_length_ = length_to_map;
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::sync(std::error_code& error)
{
    error.clear();
    if(!is_open())
    {
        error = std::make_error_code(std::errc::bad_file_descriptor);
        return;
    }

    if(data() != nullptr)
    {
#ifdef _WIN32
        if(::FlushViewOfFile(get_mapping_start(), mapped_length_) == 0
           || ::FlushFileBuffers(file_handle_) == 0)
#else
        if(::msync(get_mapping_start(), mapped_length_, MS_SYNC) != 0)
#endif
        {
            error = last_error();
            return;
        }
    }
#ifdef _WIN32
    if(::FlushFileBuffers(file_handle_) == 0)
    {
        error = last_error();
    }
#endif
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::unmap()
{
    if(!is_open()) { return; }
    // TODO do we care about errors here?
#ifdef _WIN32
    if(is_mapped())
    {
        ::UnmapViewOfFile(get_mapping_start());
        ::CloseHandle(file_mapping_handle_);
        file_mapping_handle_ = INVALID_HANDLE_VALUE;
    }
#else
    if(data_) { ::munmap(const_cast<pointer>(get_mapping_start()), mapped_length_); }
#endif

    // If file handle was obtained by our opening it (when map is called with a path,
    // rather than an existing file handle), we need to close it, otherwise it must not
    // be closed as it may still be used outside of this basic_mmap instance.
    if(is_handle_internal_)
    {
#ifdef _WIN32
        ::CloseHandle(file_handle_);
#else
        ::close(file_handle_);
#endif
    }

    // Reset fields to their default values.
    data_ = nullptr;
    length_ = mapped_length_ = 0;
    file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32
    file_mapping_handle_ = INVALID_HANDLE_VALUE;
#endif
}

template<typename CharT, typename CharTraits>
typename basic_mmap<CharT, CharTraits>::pointer
basic_mmap<CharT, CharTraits>::get_mapping_start() noexcept
{
    if(!data_) { return nullptr; }
    const auto offset = mapped_length_ - length_;
    return data_ - offset;
}

template<typename CharT, typename CharTraits>
bool basic_mmap<CharT, CharTraits>::is_open() const noexcept
{
    return file_handle_ != INVALID_HANDLE_VALUE;
}

template<typename CharT, typename CharTraits>
bool basic_mmap<CharT, CharTraits>::is_mapped() const noexcept
{
#ifdef _WIN32
    return file_mapping_handle_ != INVALID_HANDLE_VALUE;
#else
    return is_open();
#endif
}

template<typename CharT, typename CharTraits>
void basic_mmap<CharT, CharTraits>::swap(basic_mmap<CharT, CharTraits>& other)
{
    if(this != &other)
    {
        using std::swap;
        swap(data_, other.data_);
        swap(file_handle_, other.file_handle_);
#ifdef _WIN32
        swap(file_mapping_handle_, other.file_mapping_handle_);
#endif
        swap(length_, other.length_);
        swap(mapped_length_, other.mapped_length_);
        swap(is_handle_internal_, other.is_handle_internal_);
    }
}

template<typename CharT, typename CharTraits>
bool operator==(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return a.size() == b.size()
        && CharTraits::compare(a.data(), b.data(), a.size()) == 0;
}

template<typename CharT, typename CharTraits>
bool operator!=(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return !(a == b);
}

template<typename CharT, typename CharTraits>
bool operator<(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return CharTraits::compare(a.data(), b.data(), a.size()) < 0;
}

// TODO optimize
template<typename CharT, typename CharTraits>
bool operator<=(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return (a == b) || (a < b);
}

template<typename CharT, typename CharTraits>
bool operator>(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return CharTraits::compare(a.data(), b.data(), a.size()) > 0;
}

// TODO optimize
template<typename CharT, typename CharTraits>
bool operator>=(const basic_mmap<CharT, CharTraits>& a,
    const basic_mmap<CharT, CharTraits>& b)
{
    return (a == b) || (a > b);
}

} // namespace detail
} // namespace mio

#endif // MIO_BASIC_MMAP_IMPL
<|endoftext|>


<commit_before>#pragma once
#ifndef NIFTY_HDF5_HDF5_ARRAY
#define NIFTY_HDF5_HDF5_ARRAY

#include <string>
#include <vector>

#include "nifty/tools/block_access.hxx"
#include "nifty/tools/runtime_check.hxx"
#include "nifty/marray/marray_hdf5.hxx"

namespace nifty{
namespace hdf5{

    using namespace marray::hdf5;

    template<class T>
    class Hdf5Array{
    public:
        template<class SHAPE_ITER, class CHUNK_SHAPE_ITER>
        Hdf5Array(
            const hid_t& groupHandle,
            const std::string & datasetName,
            SHAPE_ITER shapeBegin,
            SHAPE_ITER shapeEnd,
            CHUNK_SHAPE_ITER chunkShapeBegin
        )
        :   groupHandle_(groupHandle),
            dataset_(),
            datatype_(),
            isChunked_(true)
        {
            datatype_ = H5Tcopy(hdf5Type<T>());
            const auto dim = std::distance(shapeBegin, shapeEnd);

            shape_.resize(dim);
            chunkShape_.resize(dim);

            std::vector<hsize_t> shape(dim);
            std::vector<hsize_t> chunkShape(dim);

            for(auto d=0; d<dim; ++d){
                const auto s = *shapeBegin;
                const auto cs = *chunkShapeBegin;
                shape[d] = s;
                shape_[d] = s;
                chunkShape[d] = cs;
                chunkShape_[d] = cs;
                ++shapeBegin;
                ++chunkShapeBegin;
            }

            // chunk properties
            hid_t dcplId = H5Pcreate(H5P_DATASET_CREATE);
            H5Pset_chunk(dcplId, hsize_t(dim), chunkShape.data());

            // dataset shape
            auto dataspace = H5Screate_simple(hsize_t(dim), shape.data(), NULL);

            // create the dataset
            dataset_ = H5Dcreate(groupHandle_, datasetName.c_str(), datatype_, dataspace,
                        H5P_DEFAULT,dcplId, H5P_DEFAULT);

            // close the dataspace and the chunk properties
            H5Sclose(dataspace);
            H5Pclose(dcplId);
        }

        Hdf5Array(
            const hid_t& groupHandle,
            const std::string & datasetName
        )
        :   groupHandle_(groupHandle),
            dataset_(),
            datatype_(),
            isChunked_(true)
        {

            dataset_ = H5Dopen(groupHandle_, datasetName.c_str(), H5P_DEFAULT);
            if(dataset_ < 0) {
                throw std::runtime_error("Marray cannot open dataset.");
            }

            // select dataspace hyperslab
            datatype_ = H5Dget_type(dataset_);
            if(!H5Tequal(datatype_, hdf5Type<T>())) {
                throw std::runtime_error("data type of stored hdf5 dataset and passed array do not match in loadHyperslab");
            }

            this->loadShape(shape_);
            this->loadChunkShape(chunkShape_);
        }

        int setCache(){
            //herr_t H5Pset_cache(hid_t plist_id, int mdc_nelmts, size_t rdcc_nslots, size_t rdcc_nbytes, double rdcc_w0)
        }

        ~Hdf5Array(){
            H5Tclose(datatype_);
            H5Dclose(dataset_);
        }

        uint64_t dimension()const{
            return shape_.size();
        }
        uint64_t shape(const size_t d)const{
            return shape_[d];
        }
        const std::vector<uint64_t> & shape()const{
            return shape_;
        }
        uint64_t chunkShape(const size_t d)const{
            return chunkShape_[d];
        }
        const std::vector<uint64_t> & chunkShape()const{
            return chunkShape_;
        }

        bool isChunked()const{
            return isChunked_;
        }

        template<class ITER>
        void readSubarray(
            ITER roiBeginIter,
            marray::View<T> & out
        )const{
            NIFTY_CHECK_OP(out.dimension(),==,this->dimension(),"out has wrong dimension");
            NIFTY_CHECK(out.coordinateOrder() == marray::FirstMajorOrder,
                "currently only views with last major order are supported"
            );
            //std::cout<<"load hyperslab\n";
            this->loadHyperslab(roiBeginIter, roiBeginIter+out.dimension(), out.shapeBegin(), out);
        }

        template<class ITER>
        void writeSubarray(
            ITER roiBeginIter,
            const marray::View<T> & in
        ){
            NIFTY_CHECK_OP(in.dimension(),==,this->dimension(),"in has wrong dimension");
            NIFTY_CHECK(in.coordinateOrder() == marray::FirstMajorOrder,
                "currently only views with last major order are supported"
            );
            this->saveHyperslab(roiBeginIter, roiBeginIter+in.dimension(), in.shapeBegin(), in);
        }

    private:
        template<class BaseIterator, class ShapeIterator>
        void loadHyperslab(
            BaseIterator baseBegin,
            BaseIterator baseEnd,
            ShapeIterator shapeBegin,
            marray::View<T> & out
        ) const {
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            // determine shape of hyperslab and array
            std::size_t size = std::distance(baseBegin, baseEnd);
            std::vector<hsize_t> offset(size);
            std::vector<hsize_t> slabShape(size);
            std::vector<hsize_t> marrayShape(size);
            marray::CoordinateOrder coordinateOrder;
            if(H5Aexists(dataset_, reverseShapeAttributeName) > 0) {
                NIFTY_CHECK(false, "currently we do not allow to load from datasets with reverseShapeAttribute")
            }
            else {
                // don't reverse base and shape
                coordinateOrder = marray::FirstMajorOrder;
                for(std::size_t j=0; j<size; ++j) {
                    offset[j] = hsize_t(*baseBegin);
                    slabShape[j] = hsize_t(*shapeBegin);
                    marrayShape[j] = slabShape[j];

                    ++baseBegin;
                    ++shapeBegin;
                }
            }

            hid_t dataspace = H5Dget_space(dataset_);
            herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
                &offset[0], NULL, &slabShape[0], NULL);
            if(status < 0) {
                H5Sclose(dataspace);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape !");
            }

            // select memspace hyperslab
            hid_t memspace = H5Screate_simple(int(size), &marrayShape[0], NULL);
            std::vector<hsize_t> offsetOut(size, 0); // no offset
            status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &offsetOut[0],
                NULL, &marrayShape[0], NULL);
            if(status < 0) {
                H5Sclose(memspace);
                H5Sclose(dataspace);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape s!");
            }

            // read from dataspace into memspace
            //out = Marray<T>(SkipInitialization, &marrayShape[0],
            //    (&marrayShape[0])+size, coordinateOrder);

            if(out.isSimple()){
                //std::cout<<"is simple\n";
                status = H5Dread(dataset_, datatype_, memspace, dataspace,
                    H5P_DEFAULT, &(out(0)));

                //std::cout<<"read status "<<status<<"\n";
            }
            else{
                //std::cout<<"is not simple\n";
                marray::Marray<T> tmpOut(marray::SkipInitialization, &marrayShape[0],
                    (&marrayShape[0])+size, coordinateOrder);

                status = H5Dread(dataset_, datatype_, memspace, dataspace,
                    H5P_DEFAULT, &(tmpOut(0)));

                //std::cout<<"read status "<<status<<"\n";

                out = tmpOut;
            }

            // clean up
            H5Sclose(memspace);
            H5Sclose(dataspace);
            if(status < 0) {
                throw std::runtime_error("Marray cannot read from dataset.");
            }
            handleCheck.check();
        }

        template<class BaseIterator, class ShapeIterator>
        void
        saveHyperslab(
            BaseIterator baseBegin,
            BaseIterator baseEnd,
            ShapeIterator shapeBegin,
            const marray::View<T> & in
        ) {
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            // determine hyperslab shape
            std::vector<hsize_t> memoryShape(in.dimension());
            for(std::size_t j=0; j<in.dimension(); ++j) {
                memoryShape[j] = in.shape(j);
            }
            std::size_t size = std::distance(baseBegin, baseEnd);
            std::vector<hsize_t> offset(size);
            std::vector<hsize_t> slabShape(size);
            bool reverseShapeAttribute = (H5Aexists(dataset_, reverseShapeAttributeName) > 0);
            if(reverseShapeAttribute || in.coordinateOrder() == marray::LastMajorOrder) {
                NIFTY_CHECK(false, "neither reverseShapeAttribute nor LastMajorOrder are currently supported");
            }
            else{
               for(std::size_t j=0; j<size; ++j) {
                   offset[j] = hsize_t(*baseBegin);
                   slabShape[j] = hsize_t(*shapeBegin);
                   ++baseBegin;
                   ++shapeBegin;
               }
            }

            // select dataspace hyperslab
            hid_t dataspace = H5Dget_space(dataset_);
            herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
                &offset[0], NULL, &slabShape[0], NULL);
            if(status < 0) {
                H5Sclose(dataspace);
                H5Dclose(dataset_);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
            }

            // select memspace hyperslab
            hid_t memspace = H5Screate_simple(int(in.dimension()), &memoryShape[0], NULL);
            std::vector<hsize_t> memoryOffset(int(in.dimension()), 0); // no offset
            status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &memoryOffset[0], NULL,
                &memoryShape[0], NULL);
            if(status < 0) {
                H5Sclose(memspace); ;
                H5Sclose(dataspace);
                H5Dclose(dataset_);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
            }

            if(in.isSimple()){
               status = H5Dwrite(dataset_, datatype_, memspace, dataspace, H5P_DEFAULT, &(in(0)));
            }
            else{
                marray::Marray<T> tmp(in);
                status = H5Dwrite(dataset_, datatype_, memspace, dataspace, H5P_DEFAULT, &(tmp(0)));
            }
            // clean up
            H5Sclose(memspace);
            H5Sclose(dataspace);
            if(status < 0) {
                throw std::runtime_error("Marray cannot write to dataset.");
            }
            handleCheck.check();
        }

        void loadShape(std::vector<uint64_t> & shapeVec){

            marray::marray_detail::Assert(marray::MARRAY_NO_ARG_TEST || groupHandle_ >= 0);
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            hid_t filespace = H5Dget_space(dataset_);
            hsize_t dimension = H5Sget_simple_extent_ndims(filespace);
            hsize_t* shape = new hsize_t[(std::size_t)(dimension)];
            herr_t status = H5Sget_simple_extent_dims(filespace, shape, NULL);
            if(status < 0) {
                H5Sclose(filespace);
                delete[] shape;
                throw std::runtime_error("MarrayNifty cannot get extension of dataset.");
            }
            // write shape to shape_
            shapeVec.resize(dimension);
            if(H5Aexists(dataset_, reverseShapeAttributeName) > 0) {
                NIFTY_CHECK(false, "currently we do not allow to load from datasets with reverseShapeAttribute")
            }
            else {
                for(std::size_t j=0; j<shapeVec.size(); ++j) {
                    shapeVec[j] = uint64_t(shape[j]);
                }
            }
            // clean up
            delete[] shape;
            H5Sclose(filespace);
            handleCheck.check();
        }

        void loadChunkShape(std::vector<uint64_t> & chunkShape){
            const auto d = this->dimension();
            std::vector<hsize_t> chunkShapeTmp(d);
            auto plist = H5Dget_create_plist(dataset_);

            bool couldBeChunked = false;
            const auto layout =  H5Pget_layout(plist);
            if(layout == H5D_CHUNKED){
                couldBeChunked = true;
            }
            if(couldBeChunked){
                herr_t status = H5Pget_chunk(plist, int(d), chunkShapeTmp.data());
                if(status < 0) {
                    isChunked_ = false;
                    chunkShape_ = shape_;
                    //H5Pclose(plist);
                    //throw std::runtime_error("Nifty cannot get chunkShape of dataset");
                }
                else{
                    isChunked_ = true;
                    chunkShape_.resize(d);
                    std::copy(chunkShapeTmp.begin(), chunkShapeTmp.end(), chunkShape_.begin());
                }
            }
            else{
                isChunked_ = false;
                chunkShape_ = shape_;
            }
            H5Pclose(plist);
        }

        hid_t groupHandle_;
        hid_t dataset_;
        hid_t datatype_;
        std::vector<uint64_t> shape_;
        std::vector<uint64_t> chunkShape_;
        bool isChunked_;
    };

    namespace tools{

}

} // namespace nifty::hdf5

namespace tools{

    template<class T, class COORD>
    inline void readSubarray(
        const hdf5::Hdf5Array<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        marray::View<T> & subarray
    ){
        array.readSubarray(beginCoord.begin(), subarray);
    }

    template<class ARRAY>
    struct BlockStorageSelector;

    template<class T>
    struct BlockStorageSelector<hdf5::Hdf5Array<T> >
    {
       typedef BlockStorage<T> type;
    };
} // namespace nifty::tools

} // namespace nifty

#endif  // NIFTY_HDF5_HDF5_ARRAY
<commit_msg>Added missing call by reference in tools::readSubarray<commit_after>#pragma once
#ifndef NIFTY_HDF5_HDF5_ARRAY
#define NIFTY_HDF5_HDF5_ARRAY

#include <string>
#include <vector>

#include "nifty/tools/block_access.hxx"
#include "nifty/tools/runtime_check.hxx"
#include "nifty/marray/marray_hdf5.hxx"

namespace nifty{
namespace hdf5{

    using namespace marray::hdf5;

    template<class T>
    class Hdf5Array{
    public:
        template<class SHAPE_ITER, class CHUNK_SHAPE_ITER>
        Hdf5Array(
            const hid_t& groupHandle,
            const std::string & datasetName,
            SHAPE_ITER shapeBegin,
            SHAPE_ITER shapeEnd,
            CHUNK_SHAPE_ITER chunkShapeBegin
        )
        :   groupHandle_(groupHandle),
            dataset_(),
            datatype_(),
            isChunked_(true)
        {
            datatype_ = H5Tcopy(hdf5Type<T>());
            const auto dim = std::distance(shapeBegin, shapeEnd);

            shape_.resize(dim);
            chunkShape_.resize(dim);

            std::vector<hsize_t> shape(dim);
            std::vector<hsize_t> chunkShape(dim);

            for(auto d=0; d<dim; ++d){
                const auto s = *shapeBegin;
                const auto cs = *chunkShapeBegin;
                shape[d] = s;
                shape_[d] = s;
                chunkShape[d] = cs;
                chunkShape_[d] = cs;
                ++shapeBegin;
                ++chunkShapeBegin;
            }

            // chunk properties
            hid_t dcplId = H5Pcreate(H5P_DATASET_CREATE);
            H5Pset_chunk(dcplId, hsize_t(dim), chunkShape.data());

            // dataset shape
            auto dataspace = H5Screate_simple(hsize_t(dim), shape.data(), NULL);

            // create the dataset
            dataset_ = H5Dcreate(groupHandle_, datasetName.c_str(), datatype_, dataspace,
                        H5P_DEFAULT,dcplId, H5P_DEFAULT);

            // close the dataspace and the chunk properties
            H5Sclose(dataspace);
            H5Pclose(dcplId);
        }

        Hdf5Array(
            const hid_t& groupHandle,
            const std::string & datasetName
        )
        :   groupHandle_(groupHandle),
            dataset_(),
            datatype_(),
            isChunked_(true)
        {

            dataset_ = H5Dopen(groupHandle_, datasetName.c_str(), H5P_DEFAULT);
            if(dataset_ < 0) {
                throw std::runtime_error("Marray cannot open dataset.");
            }

            // select dataspace hyperslab
            datatype_ = H5Dget_type(dataset_);
            if(!H5Tequal(datatype_, hdf5Type<T>())) {
                throw std::runtime_error("data type of stored hdf5 dataset and passed array do not match in loadHyperslab");
            }

            this->loadShape(shape_);
            this->loadChunkShape(chunkShape_);
        }

        int setCache(){
            //herr_t H5Pset_cache(hid_t plist_id, int mdc_nelmts, size_t rdcc_nslots, size_t rdcc_nbytes, double rdcc_w0)
        }

        ~Hdf5Array(){
            H5Tclose(datatype_);
            H5Dclose(dataset_);
        }

        uint64_t dimension()const{
            return shape_.size();
        }
        uint64_t shape(const size_t d)const{
            return shape_[d];
        }
        const std::vector<uint64_t> & shape()const{
            return shape_;
        }
        uint64_t chunkShape(const size_t d)const{
            return chunkShape_[d];
        }
        const std::vector<uint64_t> & chunkShape()const{
            return chunkShape_;
        }

        bool isChunked()const{
            return isChunked_;
        }

        template<class ITER>
        void readSubarray(
            ITER roiBeginIter,
            marray::View<T> & out
        )const{
            NIFTY_CHECK_OP(out.dimension(),==,this->dimension(),"out has wrong dimension");
            NIFTY_CHECK(out.coordinateOrder() == marray::FirstMajorOrder,
                "currently only views with last major order are supported"
            );
            //std::cout<<"load hyperslab\n";
            this->loadHyperslab(roiBeginIter, roiBeginIter+out.dimension(), out.shapeBegin(), out);
        }

        template<class ITER>
        void writeSubarray(
            ITER roiBeginIter,
            const marray::View<T> & in
        ){
            NIFTY_CHECK_OP(in.dimension(),==,this->dimension(),"in has wrong dimension");
            NIFTY_CHECK(in.coordinateOrder() == marray::FirstMajorOrder,
                "currently only views with last major order are supported"
            );
            this->saveHyperslab(roiBeginIter, roiBeginIter+in.dimension(), in.shapeBegin(), in);
        }

    private:
        template<class BaseIterator, class ShapeIterator>
        void loadHyperslab(
            BaseIterator baseBegin,
            BaseIterator baseEnd,
            ShapeIterator shapeBegin,
            marray::View<T> & out
        ) const {
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            // determine shape of hyperslab and array
            std::size_t size = std::distance(baseBegin, baseEnd);
            std::vector<hsize_t> offset(size);
            std::vector<hsize_t> slabShape(size);
            std::vector<hsize_t> marrayShape(size);
            marray::CoordinateOrder coordinateOrder;
            if(H5Aexists(dataset_, reverseShapeAttributeName) > 0) {
                NIFTY_CHECK(false, "currently we do not allow to load from datasets with reverseShapeAttribute")
            }
            else {
                // don't reverse base and shape
                coordinateOrder = marray::FirstMajorOrder;
                for(std::size_t j=0; j<size; ++j) {
                    offset[j] = hsize_t(*baseBegin);
                    slabShape[j] = hsize_t(*shapeBegin);
                    marrayShape[j] = slabShape[j];

                    ++baseBegin;
                    ++shapeBegin;
                }
            }

            hid_t dataspace = H5Dget_space(dataset_);
            herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
                &offset[0], NULL, &slabShape[0], NULL);
            if(status < 0) {
                H5Sclose(dataspace);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape !");
            }

            // select memspace hyperslab
            hid_t memspace = H5Screate_simple(int(size), &marrayShape[0], NULL);
            std::vector<hsize_t> offsetOut(size, 0); // no offset
            status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &offsetOut[0],
                NULL, &marrayShape[0], NULL);
            if(status < 0) {
                H5Sclose(memspace);
                H5Sclose(dataspace);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape s!");
            }

            // read from dataspace into memspace
            //out = Marray<T>(SkipInitialization, &marrayShape[0],
            //    (&marrayShape[0])+size, coordinateOrder);

            if(out.isSimple()){
                //std::cout<<"is simple\n";
                status = H5Dread(dataset_, datatype_, memspace, dataspace,
                    H5P_DEFAULT, &(out(0)));

                //std::cout<<"read status "<<status<<"\n";
            }
            else{
                //std::cout<<"is not simple\n";
                marray::Marray<T> tmpOut(marray::SkipInitialization, &marrayShape[0],
                    (&marrayShape[0])+size, coordinateOrder);

                status = H5Dread(dataset_, datatype_, memspace, dataspace,
                    H5P_DEFAULT, &(tmpOut(0)));

                //std::cout<<"read status "<<status<<"\n";

                out = tmpOut;
            }

            // clean up
            H5Sclose(memspace);
            H5Sclose(dataspace);
            if(status < 0) {
                throw std::runtime_error("Marray cannot read from dataset.");
            }
            handleCheck.check();
        }

        template<class BaseIterator, class ShapeIterator>
        void
        saveHyperslab(
            BaseIterator baseBegin,
            BaseIterator baseEnd,
            ShapeIterator shapeBegin,
            const marray::View<T> & in
        ) {
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            // determine hyperslab shape
            std::vector<hsize_t> memoryShape(in.dimension());
            for(std::size_t j=0; j<in.dimension(); ++j) {
                memoryShape[j] = in.shape(j);
            }
            std::size_t size = std::distance(baseBegin, baseEnd);
            std::vector<hsize_t> offset(size);
            std::vector<hsize_t> slabShape(size);
            bool reverseShapeAttribute = (H5Aexists(dataset_, reverseShapeAttributeName) > 0);
            if(reverseShapeAttribute || in.coordinateOrder() == marray::LastMajorOrder) {
                NIFTY_CHECK(false, "neither reverseShapeAttribute nor LastMajorOrder are currently supported");
            }
            else{
               for(std::size_t j=0; j<size; ++j) {
                   offset[j] = hsize_t(*baseBegin);
                   slabShape[j] = hsize_t(*shapeBegin);
                   ++baseBegin;
                   ++shapeBegin;
               }
            }

            // select dataspace hyperslab
            hid_t dataspace = H5Dget_space(dataset_);
            herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
                &offset[0], NULL, &slabShape[0], NULL);
            if(status < 0) {
                H5Sclose(dataspace);
                H5Dclose(dataset_);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
            }

            // select memspace hyperslab
            hid_t memspace = H5Screate_simple(int(in.dimension()), &memoryShape[0], NULL);
            std::vector<hsize_t> memoryOffset(int(in.dimension()), 0); // no offset
            status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &memoryOffset[0], NULL,
                &memoryShape[0], NULL);
            if(status < 0) {
                H5Sclose(memspace); ;
                H5Sclose(dataspace);
                H5Dclose(dataset_);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
            }

            if(in.isSimple()){
               status = H5Dwrite(dataset_, datatype_, memspace, dataspace, H5P_DEFAULT, &(in(0)));
            }
            else{
                marray::Marray<T> tmp(in);
                status = H5Dwrite(dataset_, datatype_, memspace, dataspace, H5P_DEFAULT, &(tmp(0)));
            }
            // clean up
            H5Sclose(memspace);
            H5Sclose(dataspace);
            if(status < 0) {
                throw std::runtime_error("Marray cannot write to dataset.");
            }
            handleCheck.check();
        }

        void loadShape(std::vector<uint64_t> & shapeVec){

            marray::marray_detail::Assert(marray::MARRAY_NO_ARG_TEST || groupHandle_ >= 0);
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            hid_t filespace = H5Dget_space(dataset_);
            hsize_t dimension = H5Sget_simple_extent_ndims(filespace);
            hsize_t* shape = new hsize_t[(std::size_t)(dimension)];
            herr_t status = H5Sget_simple_extent_dims(filespace, shape, NULL);
            if(status < 0) {
                H5Sclose(filespace);
                delete[] shape;
                throw std::runtime_error("MarrayNifty cannot get extension of dataset.");
            }
            // write shape to shape_
            shapeVec.resize(dimension);
            if(H5Aexists(dataset_, reverseShapeAttributeName) > 0) {
                NIFTY_CHECK(false, "currently we do not allow to load from datasets with reverseShapeAttribute")
            }
            else {
                for(std::size_t j=0; j<shapeVec.size(); ++j) {
                    shapeVec[j] = uint64_t(shape[j]);
                }
            }
            // clean up
            delete[] shape;
            H5Sclose(filespace);
            handleCheck.check();
        }

        void loadChunkShape(std::vector<uint64_t> & chunkShape){
            const auto d = this->dimension();
            std::vector<hsize_t> chunkShapeTmp(d);
            auto plist = H5Dget_create_plist(dataset_);

            bool couldBeChunked = false;
            const auto layout =  H5Pget_layout(plist);
            if(layout == H5D_CHUNKED){
                couldBeChunked = true;
            }
            if(couldBeChunked){
                herr_t status = H5Pget_chunk(plist, int(d), chunkShapeTmp.data());
                if(status < 0) {
                    isChunked_ = false;
                    chunkShape_ = shape_;
                    //H5Pclose(plist);
                    //throw std::runtime_error("Nifty cannot get chunkShape of dataset");
                }
                else{
                    isChunked_ = true;
                    chunkShape_.resize(d);
                    std::copy(chunkShapeTmp.begin(), chunkShapeTmp.end(), chunkShape_.begin());
                }
            }
            else{
                isChunked_ = false;
                chunkShape_ = shape_;
            }
            H5Pclose(plist);
        }

        hid_t groupHandle_;
        hid_t dataset_;
        hid_t datatype_;
        std::vector<uint64_t> shape_;
        std::vector<uint64_t> chunkShape_;
        bool isChunked_;
    };

    namespace tools{

}

} // namespace nifty::hdf5

namespace tools{

    template<class T, class COORD>
    inline void readSubarray(
        const hdf5::Hdf5Array<T> & array,
        const COORD & beginCoord,
        const COORD & endCoord,
        marray::View<T> & subarray
    ){
        array.readSubarray(beginCoord.begin(), subarray);
    }

    template<class ARRAY>
    struct BlockStorageSelector;

    template<class T>
    struct BlockStorageSelector<hdf5::Hdf5Array<T> >
    {
       typedef BlockStorage<T> type;
    };
} // namespace nifty::tools

} // namespace nifty

#endif  // NIFTY_HDF5_HDF5_ARRAY
<|endoftext|>


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

  nomlib - C++11 cross-platform game engine

Copyright (c) 2013, Jeffrey Carpenter <jeffrey.carp@gmail.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. 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 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 NOMLIB_SDL2_IMAGE_HEADERS
#define NOMLIB_SDL2_IMAGE_HEADERS

#include <iostream>
#include <string>
#include <cstdlib>
#include <memory>

#include "SDL.h"
#include "SDL_image.h"

#include "nomlib/config.hpp"
#include "nomlib/math/Color.hpp"
#include "nomlib/math/Coords.hpp"
#include "nomlib/math/Rect-inl.hpp"
#include "nomlib/graphics/smart_ptr.hpp"

namespace nom {

/// \brief Bitmap storage container
class Image
{
  public:
    /// Default constructor -- initializes to sane defaults.
    Image ( void );

    /// Destructor.
    virtual ~Image ( void );

    /// Construct an Image object with specified flags passed to the library
    /// extension(s) used in this object.
    Image ( uint32 img_flags );

    /// Copy constructor
    Image ( const Image& other );

    /// Copy assignment constructor
    Image& operator = ( const Image& other );

    /// Obtain the SDL_Surface struct used in this object instance
    SDL_Surface* get ( void ) const;

    /// Is this object initialized? Valid when *NOT* nullptr
    bool valid ( void ) const;

    /// Supports every file type that the libSDL_image extension has been
    /// compiled with
    bool load ( const std::string& filename );

    /// Uses SDL's built-in BMP file loader; no alpha channeling support ...
    /// perfect for setting window icons!
    ///
    /// (I have yet to find success using IMG_Load to load an ordinary bitmap
    /// file, whereas SDL_LoadBMP does load fine).
    bool load_bmp ( const std::string& filename );

    /// Saves as an uncompressed RGB Windows Bitmap (BMP)
    ///
    /// NOTE: AFAIK, no existing file handling / overwriting checks are done
    /// whatsoever
    bool save ( const std::string& filename, SDL_Surface* video_buffer );

    /// Obtain the width and height (in pixels) of the stored bitmap buffer
    const Coords getSize ( void ) const;

  private:
    std::shared_ptr<SDL_Surface> image_buffer;
};

} // namespace nom

#endif // NOMLIB_SDL_IMAGE_HEADERS defined
<commit_msg>Introduce a type definition 'SharedPtr'<commit_after>/******************************************************************************

  nomlib - C++11 cross-platform game engine

Copyright (c) 2013, Jeffrey Carpenter <jeffrey.carp@gmail.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. 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 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 NOMLIB_SDL2_IMAGE_HEADERS
#define NOMLIB_SDL2_IMAGE_HEADERS

#include <iostream>
#include <string>
#include <cstdlib>
#include <memory>

#include "SDL.h"
#include "SDL_image.h"

#include "nomlib/config.hpp"
#include "nomlib/math/Color.hpp"
#include "nomlib/math/Coords.hpp"
#include "nomlib/math/Rect-inl.hpp"
#include "nomlib/graphics/smart_ptr.hpp"

namespace nom {

/// \brief Bitmap storage container
class Image
{
  public:
    /// Convenience definition type for the std::unique_ptr variant
    typedef std::shared_ptr<SDL_Surface> SharedPtr;

    /// Default constructor -- initializes to sane defaults.
    Image ( void );

    /// Destructor.
    virtual ~Image ( void );

    /// Construct an Image object with specified flags passed to the library
    /// extension(s) used in this object.
    Image ( uint32 img_flags );

    /// Copy constructor
    Image ( const Image& other );

    /// Copy assignment constructor
    Image& operator = ( const Image& other );

    /// Obtain the SDL_Surface struct used in this object instance
    SDL_Surface* get ( void ) const;

    /// Is this object initialized? Valid when *NOT* nullptr
    bool valid ( void ) const;

    /// Supports every file type that the libSDL_image extension has been
    /// compiled with
    bool load ( const std::string& filename );

    /// Uses SDL's built-in BMP file loader; no alpha channeling support ...
    /// perfect for setting window icons!
    ///
    /// (I have yet to find success using IMG_Load to load an ordinary bitmap
    /// file, whereas SDL_LoadBMP does load fine).
    bool load_bmp ( const std::string& filename );

    /// Saves as an uncompressed RGB Windows Bitmap (BMP)
    ///
    /// NOTE: AFAIK, no existing file handling / overwriting checks are done
    /// whatsoever
    bool save ( const std::string& filename, SDL_Surface* video_buffer );

    /// Obtain the width and height (in pixels) of the stored bitmap buffer
    const Coords getSize ( void ) const;

  private:
    Image::SharedPtr image_buffer;
};

} // namespace nom

#endif // NOMLIB_SDL_IMAGE_HEADERS defined
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: providerhelper.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 16:29:47 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _UCBHELPER_PROVIDERHELPER_HXX
#define _UCBHELPER_PROVIDERHELPER_HXX

#ifndef __LIST__
#include <list>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDER_HPP_
#include <com/sun/star/ucb/XContentProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif
#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif
#ifndef _VOS_MUTEX_HXX_
#include <vos/mutex.hxx>
#endif
#ifndef _VOS_REF_HXX_
#include <vos/ref.hxx>
#endif
#ifndef _UCBHELPER_MACROS_HXX
#include <ucbhelper/macros.hxx>
#endif
#ifndef INCLUDED_UCBHELPERDLLAPI_H
#include "ucbhelper/ucbhelperdllapi.h"
#endif

//=========================================================================

namespace com { namespace sun { namespace star { namespace ucb {
    class XPropertySetRegistry;
    class XPersistentPropertySet;
} } } }

namespace ucb_impl { struct ContentProviderImplHelper_Impl; }

namespace ucb {

//=========================================================================

class ContentImplHelper;
typedef vos::ORef< ContentImplHelper >ContentImplHelperRef;
typedef std::list< ContentImplHelperRef > ContentRefList;

/**
  * This is an abstract base class for implementations of the service
  * com.sun.star.ucb.ContentProvider. It provides contents derived from
  * class ucb::ContentImplHelper.
  *
  * Features of the base class implementation:
  * - standard interfaces ( XInterface, XTypeProvider, XServiceInfo )
  * - maintains a set of ContentImplHelper objects, which were created by
  *   the provider implementation. So there will be exactly one object for
  *   one Content Identifier.
  * - Provides access to the Additional Core PropertySet of a content.
  *   ( These set contains the properties added to a content using its
  *   XPropertyContainer interface )
  */
class UCBHELPER_DLLPUBLIC ContentProviderImplHelper : public cppu::OWeakObject,
                                    public com::sun::star::lang::XTypeProvider,
                                    public com::sun::star::lang::XServiceInfo,
                                    public com::sun::star::ucb::XContentProvider
{
    friend class ContentImplHelper;

    ucb_impl::ContentProviderImplHelper_Impl* m_pImpl;

protected:
    vos::OMutex m_aMutex;
    ::com::sun::star::uno::Reference<
            ::com::sun::star::lang::XMultiServiceFactory >  m_xSMgr;

private:
    UCBHELPER_DLLPRIVATE void addContent      ( ContentImplHelper* pContent );
    UCBHELPER_DLLPRIVATE void removeContent( ContentImplHelper* pContent );
    UCBHELPER_DLLPRIVATE void removeContent( const ::rtl::OUString& rURL );

    UCBHELPER_DLLPRIVATE ::com::sun::star::uno::Reference<
        ::com::sun::star::ucb::XPropertySetRegistry >
    getAdditionalPropertySetRegistry();

protected:
    /**
      * This method returns a content with the given id, if it already exists.
      * Use this method in your "queryContent" implementation to ensure unique
      * objects.
      *
      * @param  Identifier is the content identifier, for that an existing
      *         content object is requested.
      * @return the content with the given identifier, if it exists or 0, if it
      *         does not exist.
      */
    vos::ORef< ContentImplHelper >
    queryExistingContent( const ::com::sun::star::uno::Reference<
                   ::com::sun::star::ucb::XContentIdentifier >& Identifier );

    /**
      * This method returns a content with the given URL, if it already exists.
      *
      * @param  rURL is the URL ( content identifier string ), for that an
      *         existing content object is requested.
      * @return the content with the given URL, if it exists or 0, if it
      *         does not exist.
      */
    vos::ORef< ContentImplHelper >
    queryExistingContent( const ::rtl::OUString& rURL );

public:

    //////////////////////////////////////////////////////////////////////
    // Contsruction/Destruction
    //////////////////////////////////////////////////////////////////////

    ContentProviderImplHelper(
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::lang::XMultiServiceFactory >& rXSMgr );
    virtual ~ContentProviderImplHelper();

    //////////////////////////////////////////////////////////////////////
    // XInterface
    //////////////////////////////////////////////////////////////////////

    XINTERFACE_DECL()

    //////////////////////////////////////////////////////////////////////
    // XTypeProvider
    //////////////////////////////////////////////////////////////////////

    XTYPEPROVIDER_DECL()

    //////////////////////////////////////////////////////////////////////
    // XServiceInfo
    //////////////////////////////////////////////////////////////////////

    virtual ::rtl::OUString SAL_CALL
    getImplementationName()
        throw( ::com::sun::star::uno::RuntimeException ) = 0;
    virtual sal_Bool SAL_CALL
    supportsService( const ::rtl::OUString& ServiceName )
        throw( ::com::sun::star::uno::RuntimeException );
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
    getSupportedServiceNames()
        throw( ::com::sun::star::uno::RuntimeException ) = 0;

    //////////////////////////////////////////////////////////////////////
    // XContentProvider
    //////////////////////////////////////////////////////////////////////

    /**
      * This method returns a content with the requested id.
      *
      * The implementation should:
      *
      * - Check, whether the Identifier is valid ( URL syntax ).
      * - Use queryExistingContent(...) to determine, whether there exists
      *   already a content with the given id.
      * - Return the possibly existing content.Create and return a new
      *   content, otherwise
      */
    virtual ::com::sun::star::uno::Reference<
                ::com::sun::star::ucb::XContent > SAL_CALL
    queryContent( const ::com::sun::star::uno::Reference<
                    ::com::sun::star::ucb::XContentIdentifier >& Identifier )
        throw( ::com::sun::star::ucb::IllegalIdentifierException,
               ::com::sun::star::uno::RuntimeException ) = 0;
    virtual sal_Int32 SAL_CALL
    compareContentIds( const ::com::sun::star::uno::Reference<
                            ::com::sun::star::ucb::XContentIdentifier >& Id1,
                       const ::com::sun::star::uno::Reference<
                               ::com::sun::star::ucb::XContentIdentifier >& Id2 )
        throw( ::com::sun::star::uno::RuntimeException );

    //////////////////////////////////////////////////////////////////////
    // Non-interface methods.
    //////////////////////////////////////////////////////////////////////

    /**
      * This method returns a mutex, which protects the content list of the
      * provider. So you can prevent modifications of that list easyly.
      *
      * @return the mutex.
      */
    vos::OMutex& getContentListMutex() { return m_aMutex; }

    /**
      * This method fills a list with all contents existing at calling time.
      * Note: You may prevent modifications of the content list at any time
      * by acquiring the content list mutex of the provider.
      *
      * @param  rContents is the list to fill with the children.
      */
    void queryExistingContents( ContentRefList& rContents );

    /**
      * This method returns the propertyset containing the Additional Core
      * Properties of a content.
      *
      * @param  rKey is the key for the propertyset.
      * @param  bCreate is a flag indicating whether the propertyset shall
      *         be created in case it does not exist.
      * @return the propertyset containing the Additional Core Properties.
      */
    ::com::sun::star::uno::Reference<
        com::sun::star::ucb::XPersistentPropertySet >
    getAdditionalPropertySet( const ::rtl::OUString& rKey, sal_Bool bCreate );

    /**
      * This method renames the propertyset containing the Additional Core
      * Properties of a content.
      *
      * @param  rOldKey is the old key of the propertyset.
      * @param  rNewKey is the new key for the propertyset.
      * @param  bRecursive is a flag indicating whether propertysets for
      *         children described by rOldKey shall be renamed, too.
      * @return True, if the operation succeeded - False, otherwise.
      */
    sal_Bool renameAdditionalPropertySet( const ::rtl::OUString& rOldKey,
                                          const ::rtl::OUString& rNewKey,
                                          sal_Bool bRecursive );

    /**
      * This method copies the propertyset containing the Additional Core
      * Properties of a content.
      *
      * @param  rSourceKey is the key of the source propertyset.
      * @param  rTargetKey is the key of the target propertyset.
      * @param  bRecursive is a flag indicating whether propertysets for
      *         children described by rSourceKey shall be copied, too.
      * @return True, if the operation succeeded - False, otherwise.
      */
    sal_Bool copyAdditionalPropertySet( const ::rtl::OUString& rSourceKey,
                                        const ::rtl::OUString& rTargetKey,
                                        sal_Bool bRecursive );

    /**
      * This method removes the propertyset containing the Additional Core
      * Properties of a content.
      *
      * @param  rKey is the key of the propertyset.
      * @param  bRecursive is a flag indicating whether propertysets for
      *         children described by rOldKey shall be removed, too.
      * @return True, if the operation succeeded - False, otherwise.
      */
    sal_Bool removeAdditionalPropertySet( const ::rtl::OUString& rKey,
                                          sal_Bool bRecursive );
};

} // namespace ucb

#endif /* !_UCBHELPER_PROVIDERHELPER_HXX */
<commit_msg>INTEGRATION: CWS bgdlremove (1.5.64); FILE MERGED 2007/05/18 11:38:09 kso 1.5.64.2: #i77419# - cleanup of ucbhelper namespaces. 2007/05/11 12:54:06 kso 1.5.64.1: #i76911# - ucbhelper no longer uses VOS<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: providerhelper.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: ihi $ $Date: 2007-06-05 14:50:14 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _UCBHELPER_PROVIDERHELPER_HXX
#define _UCBHELPER_PROVIDERHELPER_HXX

#ifndef __LIST__
#include <list>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDER_HPP_
#include <com/sun/star/ucb/XContentProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif
#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#include "osl/mutex.hxx"
#include "rtl/ref.hxx"

#ifndef _UCBHELPER_MACROS_HXX
#include <ucbhelper/macros.hxx>
#endif
#ifndef INCLUDED_UCBHELPERDLLAPI_H
#include "ucbhelper/ucbhelperdllapi.h"
#endif

//=========================================================================

namespace com { namespace sun { namespace star { namespace ucb {
    class XPropertySetRegistry;
    class XPersistentPropertySet;
} } } }

namespace ucbhelper_impl { struct ContentProviderImplHelper_Impl; }

namespace ucbhelper {

//=========================================================================

class ContentImplHelper;
typedef rtl::Reference< ContentImplHelper > ContentImplHelperRef;
typedef std::list< ContentImplHelperRef > ContentRefList;

/**
  * This is an abstract base class for implementations of the service
  * com.sun.star.ucb.ContentProvider. It provides contents derived from
  * class ucb::ContentImplHelper.
  *
  * Features of the base class implementation:
  * - standard interfaces ( XInterface, XTypeProvider, XServiceInfo )
  * - maintains a set of ContentImplHelper objects, which were created by
  *   the provider implementation. So there will be exactly one object for
  *   one Content Identifier.
  * - Provides access to the Additional Core PropertySet of a content.
  *   ( These set contains the properties added to a content using its
  *   XPropertyContainer interface )
  */
class UCBHELPER_DLLPUBLIC ContentProviderImplHelper : public cppu::OWeakObject,
                                    public com::sun::star::lang::XTypeProvider,
                                    public com::sun::star::lang::XServiceInfo,
                                    public com::sun::star::ucb::XContentProvider
{
    friend class ContentImplHelper;

    ucbhelper_impl::ContentProviderImplHelper_Impl* m_pImpl;

protected:
    osl::Mutex m_aMutex;
    ::com::sun::star::uno::Reference<
            ::com::sun::star::lang::XMultiServiceFactory >  m_xSMgr;

private:
    UCBHELPER_DLLPRIVATE void addContent      ( ContentImplHelper* pContent );
    UCBHELPER_DLLPRIVATE void removeContent( ContentImplHelper* pContent );
    UCBHELPER_DLLPRIVATE void removeContent( const ::rtl::OUString& rURL );

    UCBHELPER_DLLPRIVATE ::com::sun::star::uno::Reference<
        ::com::sun::star::ucb::XPropertySetRegistry >
    getAdditionalPropertySetRegistry();

protected:
    /**
      * This method returns a content with the given id, if it already exists.
      * Use this method in your "queryContent" implementation to ensure unique
      * objects.
      *
      * @param  Identifier is the content identifier, for that an existing
      *         content object is requested.
      * @return the content with the given identifier, if it exists or 0, if it
      *         does not exist.
      */
    rtl::Reference< ContentImplHelper >
    queryExistingContent( const ::com::sun::star::uno::Reference<
                   ::com::sun::star::ucb::XContentIdentifier >& Identifier );

    /**
      * This method returns a content with the given URL, if it already exists.
      *
      * @param  rURL is the URL ( content identifier string ), for that an
      *         existing content object is requested.
      * @return the content with the given URL, if it exists or 0, if it
      *         does not exist.
      */
    rtl::Reference< ContentImplHelper >
    queryExistingContent( const ::rtl::OUString& rURL );

public:

    //////////////////////////////////////////////////////////////////////
    // Contsruction/Destruction
    //////////////////////////////////////////////////////////////////////

    ContentProviderImplHelper(
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::lang::XMultiServiceFactory >& rXSMgr );
    virtual ~ContentProviderImplHelper();

    //////////////////////////////////////////////////////////////////////
    // XInterface
    //////////////////////////////////////////////////////////////////////

    XINTERFACE_DECL()

    //////////////////////////////////////////////////////////////////////
    // XTypeProvider
    //////////////////////////////////////////////////////////////////////

    XTYPEPROVIDER_DECL()

    //////////////////////////////////////////////////////////////////////
    // XServiceInfo
    //////////////////////////////////////////////////////////////////////

    virtual ::rtl::OUString SAL_CALL
    getImplementationName()
        throw( ::com::sun::star::uno::RuntimeException ) = 0;
    virtual sal_Bool SAL_CALL
    supportsService( const ::rtl::OUString& ServiceName )
        throw( ::com::sun::star::uno::RuntimeException );
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
    getSupportedServiceNames()
        throw( ::com::sun::star::uno::RuntimeException ) = 0;

    //////////////////////////////////////////////////////////////////////
    // XContentProvider
    //////////////////////////////////////////////////////////////////////

    /**
      * This method returns a content with the requested id.
      *
      * The implementation should:
      *
      * - Check, whether the Identifier is valid ( URL syntax ).
      * - Use queryExistingContent(...) to determine, whether there exists
      *   already a content with the given id.
      * - Return the possibly existing content.Create and return a new
      *   content, otherwise
      */
    virtual ::com::sun::star::uno::Reference<
                ::com::sun::star::ucb::XContent > SAL_CALL
    queryContent( const ::com::sun::star::uno::Reference<
                    ::com::sun::star::ucb::XContentIdentifier >& Identifier )
        throw( ::com::sun::star::ucb::IllegalIdentifierException,
               ::com::sun::star::uno::RuntimeException ) = 0;
    virtual sal_Int32 SAL_CALL
    compareContentIds( const ::com::sun::star::uno::Reference<
                            ::com::sun::star::ucb::XContentIdentifier >& Id1,
                       const ::com::sun::star::uno::Reference<
                               ::com::sun::star::ucb::XContentIdentifier >& Id2 )
        throw( ::com::sun::star::uno::RuntimeException );

    //////////////////////////////////////////////////////////////////////
    // Non-interface methods.
    //////////////////////////////////////////////////////////////////////

    /**
      * This method returns a mutex, which protects the content list of the
      * provider. So you can prevent modifications of that list easyly.
      *
      * @return the mutex.
      */
    osl::Mutex& getContentListMutex() { return m_aMutex; }

    /**
      * This method fills a list with all contents existing at calling time.
      * Note: You may prevent modifications of the content list at any time
      * by acquiring the content list mutex of the provider.
      *
      * @param  rContents is the list to fill with the children.
      */
    void queryExistingContents( ContentRefList& rContents );

    /**
      * This method returns the propertyset containing the Additional Core
      * Properties of a content.
      *
      * @param  rKey is the key for the propertyset.
      * @param  bCreate is a flag indicating whether the propertyset shall
      *         be created in case it does not exist.
      * @return the propertyset containing the Additional Core Properties.
      */
    ::com::sun::star::uno::Reference<
        com::sun::star::ucb::XPersistentPropertySet >
    getAdditionalPropertySet( const ::rtl::OUString& rKey, sal_Bool bCreate );

    /**
      * This method renames the propertyset containing the Additional Core
      * Properties of a content.
      *
      * @param  rOldKey is the old key of the propertyset.
      * @param  rNewKey is the new key for the propertyset.
      * @param  bRecursive is a flag indicating whether propertysets for
      *         children described by rOldKey shall be renamed, too.
      * @return True, if the operation succeeded - False, otherwise.
      */
    sal_Bool renameAdditionalPropertySet( const ::rtl::OUString& rOldKey,
                                          const ::rtl::OUString& rNewKey,
                                          sal_Bool bRecursive );

    /**
      * This method copies the propertyset containing the Additional Core
      * Properties of a content.
      *
      * @param  rSourceKey is the key of the source propertyset.
      * @param  rTargetKey is the key of the target propertyset.
      * @param  bRecursive is a flag indicating whether propertysets for
      *         children described by rSourceKey shall be copied, too.
      * @return True, if the operation succeeded - False, otherwise.
      */
    sal_Bool copyAdditionalPropertySet( const ::rtl::OUString& rSourceKey,
                                        const ::rtl::OUString& rTargetKey,
                                        sal_Bool bRecursive );

    /**
      * This method removes the propertyset containing the Additional Core
      * Properties of a content.
      *
      * @param  rKey is the key of the propertyset.
      * @param  bRecursive is a flag indicating whether propertysets for
      *         children described by rOldKey shall be removed, too.
      * @return True, if the operation succeeded - False, otherwise.
      */
    sal_Bool removeAdditionalPropertySet( const ::rtl::OUString& rKey,
                                          sal_Bool bRecursive );
};

} // namespace ucbhelper

#endif /* !_UCBHELPER_PROVIDERHELPER_HXX */
<|endoftext|>


<commit_before>// Used for testing, do not use it as an example
#include <iostream>

#include "qpp.h"

int main() {
    /////////// testing ///////////
    using namespace qpp;
}
<commit_msg>Update _test.cpp<commit_after>// Used for testing, do not use it as an example
#include <iostream>

#include "qpp.h"

int main() {
    /////////// testing ///////////
    using namespace qpp;

    // Quantum coin flip
    QCircuit qc{1, 1};
    qc.gate(gt.H, 0).measureZ(0, 0);

    QEngine q_engine{qc};
    q_engine.execute();
    std::cout << q_engine << '\n';
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * examples/bench.cpp
 *

/*******************************************************************************
 * examples/bench.cpp
 *
 * Part of Project c7a.
 *
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#include <c7a/api/dia.hpp>
#include <c7a/core/reduce_pre_table.hpp>

int main(int argc, char* argv[]) {
    auto emit = [](int in) {
                    in = in;
                    //std::cout << in << std::endl;
                };

    auto key_ex = [](int in) {
                      return in;
                  };

    auto red_fn = [](int in1, int in2) {
                      return in1 + in2;
                  };

    srand(time(NULL));
    int workers = std::stoi(argv[2]);
    int modulo = std::stoi(argv[3]);

    c7a::core::ReducePreTable<decltype(key_ex), decltype(red_fn), decltype(emit)>
    table(workers, key_ex, red_fn, { emit });

    int end = std::stoi(argv[1]);

    clock_t time = std::clock();

    for (int i = 0; i < end; i++) {
        table.Insert(rand() % modulo);
    }

    table.Flush();

    time = std::clock() - time;

    printf("%f", ((double)(time * 1000000) / (double)CLOCKS_PER_SEC));
    //printf(std::endl);

    //std::cout << (time * 1000000) / (double) CLOCKS_PER_SEC << std::endl;

    return 0;
}

/******************************************************************************/
<commit_msg>fix compiler warning<commit_after>/*******************************************************************************
 * examples/bench.cpp
 *
 * Part of Project c7a.
 *
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#include <c7a/api/dia.hpp>
#include <c7a/core/reduce_pre_table.hpp>

int main(int argc, char* argv[]) {
    auto emit = [](int in) {
                    in = in;
                    //std::cout << in << std::endl;
                };

    auto key_ex = [](int in) {
                      return in;
                  };

    auto red_fn = [](int in1, int in2) {
                      return in1 + in2;
                  };

    srand(time(NULL));
    int workers = std::stoi(argv[2]);
    int modulo = std::stoi(argv[3]);

    c7a::core::ReducePreTable<decltype(key_ex), decltype(red_fn), decltype(emit)>
    table(workers, key_ex, red_fn, { emit });

    int end = std::stoi(argv[1]);

    clock_t time = std::clock();

    for (int i = 0; i < end; i++) {
        table.Insert(rand() % modulo);
    }

    table.Flush();

    time = std::clock() - time;

    printf("%f", ((double)(time * 1000000) / (double)CLOCKS_PER_SEC));
    //printf(std::endl);

    //std::cout << (time * 1000000) / (double) CLOCKS_PER_SEC << std::endl;

    return 0;
}

/******************************************************************************/
<|endoftext|>


<commit_before>#include "ludii.h"
#include <iostream>
#include <string>
#include <vector>

Ludii::Ludii(const std::string jar_location){
	initJVM(jar_location);
}

Ludii::~Ludii(){
	closeJVM();
}

std::vector<std::string> Ludii::listGames(){

	std::vector<std::string> gamesVector;

	jclass gameLoader = env->FindClass("player/GameLoader");

    //find the listGames method
    jmethodID mid = env->GetStaticMethodID(gameLoader,"listGames","()[Ljava/lang/String;");

    //execute the listGames method
    jobjectArray stringArray = (jobjectArray) env->CallStaticObjectMethod(gameLoader,mid);

    //put list of games in vector
    int stringCount = env->GetArrayLength(stringArray);

	for (int i=0; i<stringCount; i++) {
		//get array element and convert it from jstrng
        jstring string = (jstring) (env->GetObjectArrayElement(stringArray, i));
        const char *rawString = env->GetStringUTFChars(string, 0);

       	std::string cppString(rawString);
        gamesVector.push_back(cppString);

        env->ReleaseStringUTFChars(string, rawString);
    }

	return gamesVector;
}

void Ludii::loadGameAndDoStuff(std::string game_name){

	//create game object i.e. `Game game = GameLoader.loadGameFromName`
	jclass gameLoader = env->FindClass("player/GameLoader");
    jmethodID mid = env->GetStaticMethodID(gameLoader,"loadGameFromName","(Ljava/lang/String;)Lgame/Game;");

	//convert game name to java string
	char game_name_char[1024];
	strcpy(game_name_char, game_name.c_str());
	jstring j_game_name = env->NewStringUTF(game_name_char);

	jobject game_obj = env->CallStaticObjectMethod(gameLoader,mid,j_game_name);

	//call the `name()` method on the game object we just created
	jclass gameClass = env->FindClass("game/Game");
	jmethodID name_id = env->GetMethodID(gameClass,"name","()Ljava/lang/String;");
	jstring stringArray =(jstring) env->CallObjectMethod(game_obj,name_id);

	//convert jstring game name to char array and print
	const char *strReturn = env->GetStringUTFChars(stringArray, 0);
	std::cout<< "name() result: "<<strReturn<<std::endl;

    env->ReleaseStringUTFChars(stringArray, strReturn);
}

int main(){

	std::string jar_location = "/home/alex/Downloads/Ludii-0.3.0.jar";

	Ludii test_ludii = Ludii(jar_location);

	std::vector<std::string> games = test_ludii.listGames();

	test_ludii.loadGameAndDoStuff("board/space/blocking/Amazons.lud");
}<commit_msg>for some reason the indentation in sublime is different than what is showing in github<commit_after>#include "ludii.h"
#include <iostream>
#include <string>
#include <vector>

Ludii::Ludii(const std::string jar_location){
	initJVM(jar_location);
}

Ludii::~Ludii(){
	closeJVM();
}

std::vector<std::string> Ludii::listGames(){

	std::vector<std::string> gamesVector;

	jclass gameLoader = env->FindClass("player/GameLoader");

    	//find the listGames method
    	jmethodID mid = env->GetStaticMethodID(gameLoader,"listGames","()[Ljava/lang/String;");

    	//execute the listGames method
    	jobjectArray stringArray = (jobjectArray) env->CallStaticObjectMethod(gameLoader,mid);

    	//put list of games in vector
    	int stringCount = env->GetArrayLength(stringArray);

	for (int i=0; i<stringCount; i++) {
		//get array element and convert it from jstrng
        	jstring string = (jstring) (env->GetObjectArrayElement(stringArray, i));
        	const char *rawString = env->GetStringUTFChars(string, 0);

       		std::string cppString(rawString);
        	gamesVector.push_back(cppString);

        	env->ReleaseStringUTFChars(string, rawString);
    	}

	return gamesVector;
}

void Ludii::loadGameAndDoStuff(std::string game_name){

	//create game object i.e. `Game game = GameLoader.loadGameFromName()`
	jclass gameLoader = env->FindClass("player/GameLoader");
    	jmethodID mid = env->GetStaticMethodID(gameLoader,"loadGameFromName","(Ljava/lang/String;)Lgame/Game;");

	//convert game name to java string
	char game_name_char[1024];
	strcpy(game_name_char, game_name.c_str());
	jstring j_game_name = env->NewStringUTF(game_name_char);

	jobject game_obj = env->CallStaticObjectMethod(gameLoader,mid,j_game_name);

	//call the `name()` method on the game object we just created
	jclass gameClass = env->FindClass("game/Game");
	jmethodID name_id = env->GetMethodID(gameClass,"name","()Ljava/lang/String;");
	jstring stringArray =(jstring) env->CallObjectMethod(game_obj,name_id);

	//convert jstring game name to char array and print
	const char *strReturn = env->GetStringUTFChars(stringArray, 0);
	std::cout<< "name() result: "<<strReturn<<std::endl;

    	env->ReleaseStringUTFChars(stringArray, strReturn);
}

int main(){

	std::string jar_location = "/home/alex/Downloads/Ludii-0.3.0.jar";

	Ludii test_ludii = Ludii(jar_location);

	std::vector<std::string> games = test_ludii.listGames();

	test_ludii.loadGameAndDoStuff("board/space/blocking/Amazons.lud");
}
<|endoftext|>