<commit_before>#ifndef LIBICS3_ICS3_CHECK_INVALID_H_
#define LIBICS3_ICS3_CHECK_INVALID_H_

#include<stdexcept>

namespace ics {
  template<typename T> constexpr T checkInvalidRange(T input, T min, T max) {
    return input < min ? throw std::invalid_argument {"Too small argument"} :
      max < input ? throw std::invalid_argument {"Too big argument"} :
      input;
  }
}

#endif // LIBICS3_ICS3_CHECK_INVALID_H_
<commit_msg>Reformat indent of checkInvalidRange<commit_after>#ifndef LIBICS3_ICS3_CHECK_INVALID_H_
#define LIBICS3_ICS3_CHECK_INVALID_H_

#include<stdexcept>

namespace ics {
  template<typename T> constexpr T checkInvalidRange(T input, T min, T max) {
    return input < min ? throw std::invalid_argument {"Too small argument"} :
           max < input ? throw std::invalid_argument {"Too big argument"} :
           input;
  }
}

#endif // LIBICS3_ICS3_CHECK_INVALID_H_
<|endoftext|>


<commit_before>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ADDRESS_HPP_INCLUDED
#define TORRENT_ADDRESS_HPP_INCLUDED

#include <boost/version.hpp>

#ifdef __OBJC__
#define Protocol Protocol_
#endif

#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif

#if BOOST_VERSION < 103500
#include <asio/ip/address.hpp>
#else
#include <boost/asio/ip/address.hpp>
#endif

#ifdef __OBJC__
#undef Protocol
#endif

namespace libtorrent
{

#if BOOST_VERSION < 103500
	typedef ::asio::ip::address address;
	typedef ::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef ::asio::ip::address_v6 address_v6;
#endif
#else
	typedef boost::asio::ip::address address;
	typedef boost::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef boost::asio::ip::address_v6 address_v6;
#endif
#endif
}

#endif

<commit_msg>include config.hpp<commit_after>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ADDRESS_HPP_INCLUDED
#define TORRENT_ADDRESS_HPP_INCLUDED

#include <boost/version.hpp>
#include "libtorrent/config.hpp"

#ifdef __OBJC__
#define Protocol Protocol_
#endif

#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif

#if BOOST_VERSION < 103500
#include <asio/ip/address.hpp>
#else
#include <boost/asio/ip/address.hpp>
#endif

#ifdef __OBJC__
#undef Protocol
#endif

namespace libtorrent
{

#if BOOST_VERSION < 103500
	typedef ::asio::ip::address address;
	typedef ::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef ::asio::ip::address_v6 address_v6;
#endif
#else
	typedef boost::asio::ip::address address;
	typedef boost::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef boost::asio::ip::address_v6 address_v6;
#endif
#endif
}

#endif

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_ENUMERATION_HPP
#define MAPNIK_ENUMERATION_HPP

// mapnik
#include <mapnik/config.hpp>
#include <mapnik/debug.hpp>

// stl
#include <iostream>
#include <cstdlib>
#include <algorithm>

namespace mapnik {

class illegal_enum_value : public std::exception
{
public:
    illegal_enum_value():
        what_() {}

    illegal_enum_value( std::string const& _what ) :
        what_( _what )
    {
    }
    virtual ~illegal_enum_value() {}

    virtual const char * what() const noexcept
    {
        return what_.c_str();
    }

protected:
    std::string what_;
};

/** Slim wrapper for enumerations. It creates a new type from a native enum and
 * a char pointer array. It almost exactly behaves like a native enumeration
 * type. It supports string conversion through stream operators. This is useful
 * for debugging, serialization/deserialization and also helps with implementing
 * language bindings. The two convenient macros DEFINE_ENUM() and IMPLEMENT_ENUM()
 * are provided to help with instanciation.
 *
 * @par Limitations:
 *    - The enum must start at zero.
 *    - The enum must be consecutive.
 *    - The enum must be terminated with a special token consisting of the enum's
 *      name plus "_MAX".
 *    - The corresponding char pointer array must be terminated with an empty string.
 *    - The names must only consist of characters and digits (a-z, A-Z, 0-9),
 *      underscores (_) and dashes (-).
 *
 *
 * @warning At the moment the verify_mapnik_enum() method is called during static initialization.
 * It quits the application with exit code 1 if any error is detected. The other solution
 * i thought of is to do the checks at compile time (using boost::mpl).
 *
 * @par Example:
 * The following code goes into the header file:
 * @code
 * enum fruit_enum {
 *      APPLE,
 *      CHERRY,
 *      BANANA,
 *      PASSION_FRUIT,
 *      fruit_enum_MAX
 * };
 *
 * static const char * fruit_strings[] = {
 *      "apple",
 *      "cherry",
 *      "banana",
 *      "passion_fruit",
 *      ""
 * };
 *
 * DEFINE_ENUM( fruit, fruit_enum);
 * @endcode
 * In the corresponding cpp file do:
 * @code
 * IMPLEMENT_ENUM( fruit, fruit_strings );
 * @endcode
 * And here is how to use the resulting type Fruit
 * @code
 *
 * int
 * main(int argc, char * argv[]) {
 *      fruit f(APPLE);
 *      switch ( f ) {
 *          case BANANA:
 *          case APPLE:
 *              cerr << "No thanks. I hate " << f << "s" << endl;
 *              break;
 *          default:
 *              cerr << "Hmmm ... yummy " << f << endl;
 *              break;
 *      }
 *
 *      f = CHERRY;
 *
 *      fruit_enum native_enum = f;
 *
 *      f.from_string("passion_fruit");
 *
 *      for (unsigned i = 0; i < fruit::MAX; ++i) {
 *          cerr << i << " = " << fruit::get_string(i) << endl;
 *      }
 *
 *      f.from_string("elephant"); // throws illegal_enum_value
 *
 *      return 0;
 * }
 * @endcode
 */

template <typename ENUM, int THE_MAX>
class MAPNIK_DECL enumeration {
public:
    using native_type = ENUM;

    enumeration()
        :  value_() {}

    enumeration( ENUM v )
        :  value_(v) {}

    enumeration( enumeration const& other )
        : value_(other.value_) {}

    /** Assignment operator for native enum values. */
    void operator=(ENUM v)
    {
        value_ = v;
    }

    /** Assignment operator. */
    void operator=(enumeration const& other)
    {
        value_ = other.value_;
    }

    /** Conversion operator for native enum values. */
    operator ENUM() const
    {
        return value_;
    }

    enum Max
    {
        MAX = THE_MAX
    };

    /** Converts @p str to an enum.
     * @throw illegal_enum_value @p str is not a legal identifier.
     * */
    void from_string(std::string const& str)
    {
        // TODO: Enum value strings with underscore are deprecated in Mapnik 3.x
        // and support will be removed in Mapnik 4.x.
        bool deprecated = false;
        std::string str_copy(str);
        if (str_copy.find('_') != std::string::npos)
        {
            std::replace(str_copy.begin(), str_copy.end(), '_', '-');
            deprecated = true;
        }
        for (unsigned i = 0; i < THE_MAX; ++i)
        {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template"
            if (str_copy == our_strings_[i])
#pragma GCC diagnostic pop
            {
                value_ = static_cast<ENUM>(i);
                if (deprecated)
                {
                    MAPNIK_LOG_ERROR(enumerations) << "enumeration value (" << str << ") using \"_\" is deprecated and will be removed in Mapnik 4.x, use '" << str_copy << "' instead";
                }
                return;
            }
        }
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template"
        throw illegal_enum_value(std::string("Illegal enumeration value '") +
                                 str + "' for enum " + our_name_);
#pragma GCC diagnostic pop
    }

    /** Returns the current value as a string identifier. */
    std::string as_string() const
    {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template"
        return our_strings_[value_];
#pragma GCC diagnostic pop
    }

    /** Static helper function to iterate over valid identifiers. */
    static const char * get_string(unsigned i)
    {
        return our_strings_[i];
    }

    /** Performs some simple checks and quits the application if
     * any error is detected. Tries to print helpful error messages.
     */
    static bool verify_mapnik_enum(const char * filename, unsigned line_no)
    {
        for (unsigned i = 0; i < THE_MAX; ++i)
        {
            if (our_strings_[i] == 0 )
            {
                std::cerr << "### FATAL: Not enough strings for enum "
                          << our_name_ << " defined in file '" << filename
                          << "' at line " << line_no;
            }
        }
        if ( std::string("") != our_strings_[THE_MAX])
        {
            std::cerr << "### FATAL: The string array for enum " << our_name_
                      << " defined in file '" << filename << "' at line " << line_no
                      << " has too many items or is not terminated with an "
                      << "empty string";
        }
        return true;
    }

private:
    ENUM value_;
    static const char ** our_strings_ ;
    static std::string our_name_ ;
    static bool  our_verified_flag_;
};

/** ostream operator for enumeration
 * @relates mapnik::enumeration
 */
template <class ENUM, int THE_MAX>
std::ostream &
operator<<(std::ostream & os, const mapnik::enumeration<ENUM, THE_MAX> & e)
{
    return os << e.as_string();
}

} // end of namespace

/** Helper macro.
 * @relates mapnik::enumeration
 */
#ifdef _MSC_VER
#define DEFINE_ENUM( name, e)                   \
    template enumeration<e, e ## _MAX>;         \
    using name = enumeration<e, e ## _MAX>;
#else
#define DEFINE_ENUM( name, e)                   \
    using name = enumeration<e, e ## _MAX>;
#endif

/** Helper macro. Runs the verify_mapnik_enum() method during static initialization.
 * @relates mapnik::enumeration
 */

#define IMPLEMENT_ENUM( name, strings )                                 \
    template <> MAPNIK_DECL const char ** name ::our_strings_ = strings;            \
    template <> MAPNIK_DECL std::string name ::our_name_ = #name;                   \
    template <> MAPNIK_DECL bool name ::our_verified_flag_( name ::verify_mapnik_enum(__FILE__, __LINE__));

#endif // MAPNIK_ENUMERATION_HPP
<commit_msg>add explicit instantiation declarations to DEFINE_ENUM macro to fix -Wundefined-var-template warnings.<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_ENUMERATION_HPP
#define MAPNIK_ENUMERATION_HPP

// mapnik
#include <mapnik/config.hpp>
#include <mapnik/debug.hpp>

// stl
#include <iostream>
#include <cstdlib>
#include <algorithm>

namespace mapnik {

class illegal_enum_value : public std::exception
{
public:
    illegal_enum_value():
        what_() {}

    illegal_enum_value( std::string const& _what ) :
        what_( _what )
    {
    }
    virtual ~illegal_enum_value() {}

    virtual const char * what() const noexcept
    {
        return what_.c_str();
    }

protected:
    std::string what_;
};

/** Slim wrapper for enumerations. It creates a new type from a native enum and
 * a char pointer array. It almost exactly behaves like a native enumeration
 * type. It supports string conversion through stream operators. This is useful
 * for debugging, serialization/deserialization and also helps with implementing
 * language bindings. The two convenient macros DEFINE_ENUM() and IMPLEMENT_ENUM()
 * are provided to help with instanciation.
 *
 * @par Limitations:
 *    - The enum must start at zero.
 *    - The enum must be consecutive.
 *    - The enum must be terminated with a special token consisting of the enum's
 *      name plus "_MAX".
 *    - The corresponding char pointer array must be terminated with an empty string.
 *    - The names must only consist of characters and digits (a-z, A-Z, 0-9),
 *      underscores (_) and dashes (-).
 *
 *
 * @warning At the moment the verify_mapnik_enum() method is called during static initialization.
 * It quits the application with exit code 1 if any error is detected. The other solution
 * i thought of is to do the checks at compile time (using boost::mpl).
 *
 * @par Example:
 * The following code goes into the header file:
 * @code
 * enum fruit_enum {
 *      APPLE,
 *      CHERRY,
 *      BANANA,
 *      PASSION_FRUIT,
 *      fruit_enum_MAX
 * };
 *
 * static const char * fruit_strings[] = {
 *      "apple",
 *      "cherry",
 *      "banana",
 *      "passion_fruit",
 *      ""
 * };
 *
 * DEFINE_ENUM( fruit, fruit_enum);
 * @endcode
 * In the corresponding cpp file do:
 * @code
 * IMPLEMENT_ENUM( fruit, fruit_strings );
 * @endcode
 * And here is how to use the resulting type Fruit
 * @code
 *
 * int
 * main(int argc, char * argv[]) {
 *      fruit f(APPLE);
 *      switch ( f ) {
 *          case BANANA:
 *          case APPLE:
 *              cerr << "No thanks. I hate " << f << "s" << endl;
 *              break;
 *          default:
 *              cerr << "Hmmm ... yummy " << f << endl;
 *              break;
 *      }
 *
 *      f = CHERRY;
 *
 *      fruit_enum native_enum = f;
 *
 *      f.from_string("passion_fruit");
 *
 *      for (unsigned i = 0; i < fruit::MAX; ++i) {
 *          cerr << i << " = " << fruit::get_string(i) << endl;
 *      }
 *
 *      f.from_string("elephant"); // throws illegal_enum_value
 *
 *      return 0;
 * }
 * @endcode
 */

template <typename ENUM, int THE_MAX>
class MAPNIK_DECL enumeration {
public:
    using native_type = ENUM;

    enumeration()
        :  value_() {}

    enumeration( ENUM v )
        :  value_(v) {}

    enumeration( enumeration const& other )
        : value_(other.value_) {}

    /** Assignment operator for native enum values. */
    void operator=(ENUM v)
    {
        value_ = v;
    }

    /** Assignment operator. */
    void operator=(enumeration const& other)
    {
        value_ = other.value_;
    }

    /** Conversion operator for native enum values. */
    operator ENUM() const
    {
        return value_;
    }

    enum Max
    {
        MAX = THE_MAX
    };

    /** Converts @p str to an enum.
     * @throw illegal_enum_value @p str is not a legal identifier.
     * */
    void from_string(std::string const& str)
    {
        // TODO: Enum value strings with underscore are deprecated in Mapnik 3.x
        // and support will be removed in Mapnik 4.x.
        bool deprecated = false;
        std::string str_copy(str);
        if (str_copy.find('_') != std::string::npos)
        {
            std::replace(str_copy.begin(), str_copy.end(), '_', '-');
            deprecated = true;
        }
        for (unsigned i = 0; i < THE_MAX; ++i)
        {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template"
            if (str_copy == our_strings_[i])
#pragma GCC diagnostic pop
            {
                value_ = static_cast<ENUM>(i);
                if (deprecated)
                {
                    MAPNIK_LOG_ERROR(enumerations) << "enumeration value (" << str << ") using \"_\" is deprecated and will be removed in Mapnik 4.x, use '" << str_copy << "' instead";
                }
                return;
            }
        }
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template"
        throw illegal_enum_value(std::string("Illegal enumeration value '") +
                                 str + "' for enum " + our_name_);
#pragma GCC diagnostic pop
    }

    /** Returns the current value as a string identifier. */
    std::string as_string() const
    {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template"
        return our_strings_[value_];
#pragma GCC diagnostic pop
    }

    /** Static helper function to iterate over valid identifiers. */
    static const char * get_string(unsigned i)
    {
        return our_strings_[i];
    }

    /** Performs some simple checks and quits the application if
     * any error is detected. Tries to print helpful error messages.
     */
    static bool verify_mapnik_enum(const char * filename, unsigned line_no)
    {
        for (unsigned i = 0; i < THE_MAX; ++i)
        {
            if (our_strings_[i] == 0 )
            {
                std::cerr << "### FATAL: Not enough strings for enum "
                          << our_name_ << " defined in file '" << filename
                          << "' at line " << line_no;
            }
        }
        if ( std::string("") != our_strings_[THE_MAX])
        {
            std::cerr << "### FATAL: The string array for enum " << our_name_
                      << " defined in file '" << filename << "' at line " << line_no
                      << " has too many items or is not terminated with an "
                      << "empty string";
        }
        return true;
    }

private:
    ENUM value_;
    static const char ** our_strings_ ;
    static std::string our_name_ ;
    static bool  our_verified_flag_;
};

/** ostream operator for enumeration
 * @relates mapnik::enumeration
 */
template <class ENUM, int THE_MAX>
std::ostream &
operator<<(std::ostream & os, const mapnik::enumeration<ENUM, THE_MAX> & e)
{
    return os << e.as_string();
}

} // end of namespace

/** Helper macro.
 * @relates mapnik::enumeration
 */
#ifdef _MSC_VER
#define DEFINE_ENUM( name, e)                   \
    template enumeration<e, e ## _MAX>;         \
    using name = enumeration<e, e ## _MAX>;
#else
#define DEFINE_ENUM( name, e)                   \
    using name = enumeration<e, e ## _MAX>; \
    template <> MAPNIK_DECL const char ** name ::our_strings_; \
    template <> MAPNIK_DECL std::string name ::our_name_; \
    template <> MAPNIK_DECL bool name ::our_verified_flag_;
#endif

/** Helper macro. Runs the verify_mapnik_enum() method during static initialization.
 * @relates mapnik::enumeration
 */

#define IMPLEMENT_ENUM( name, strings )                                 \
    template <> MAPNIK_DECL const char ** name ::our_strings_ = strings;            \
    template <> MAPNIK_DECL std::string name ::our_name_ = #name;                   \
    template <> MAPNIK_DECL bool name ::our_verified_flag_( name ::verify_mapnik_enum(__FILE__, __LINE__));

#endif // MAPNIK_ENUMERATION_HPP
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/core/resource.hh>
#include <seastar/core/bitops.hh>
#include <new>
#include <functional>
#include <vector>

namespace seastar {

/// \defgroup memory-module Memory management
///
/// Functions and classes for managing memory.
///
/// Memory management in seastar consists of the following:
///
///   - Low-level memory management in the \ref memory namespace.
///   - Various smart pointers: \ref shared_ptr, \ref lw_shared_ptr,
///     and \ref foreign_ptr.
///   - zero-copy support: \ref temporary_buffer and \ref deleter.

/// Low-level memory management support
///
/// The \c memory namespace provides functions and classes for interfacing
/// with the seastar memory allocator.
///
/// The seastar memory allocator splits system memory into a pool per
/// logical core (lcore).  Memory allocated one an lcore should be freed
/// on the same lcore; failing to do so carries a severe performance
/// penalty.  It is possible to share memory with another core, but this
/// should be limited to avoid cache coherency traffic.
namespace memory {

/// \cond internal

#ifdef SEASTAR_OVERRIDE_ALLOCATOR_PAGE_SIZE
#define SEASTAR_INTERNAL_ALLOCATOR_PAGE_SIZE (SEASTAR_OVERRIDE_ALLOCATOR_PAGE_SIZE)
#else
#define SEASTAR_INTERNAL_ALLOCATOR_PAGE_SIZE 4096
#endif

static constexpr size_t page_size = SEASTAR_INTERNAL_ALLOCATOR_PAGE_SIZE;
static constexpr size_t page_bits = log2ceil(page_size);
static constexpr size_t huge_page_size =
#if defined(__x86_64__) || defined(__i386__) || defined(__s390x__) || defined(__zarch__)
    1 << 21; // 2M
#elif defined(__aarch64__)
    1 << 21; // 2M
#elif defined(__PPC__)
    1 << 24; // 16M
#else
#error "Huge page size is not defined for this architecture"
#endif

void configure(std::vector<resource::memory> m, bool mbind,
        std::optional<std::string> hugetlbfs_path = {});

void enable_abort_on_allocation_failure();

class disable_abort_on_alloc_failure_temporarily {
public:
    disable_abort_on_alloc_failure_temporarily();
    ~disable_abort_on_alloc_failure_temporarily() noexcept;
};

// Disables heap profiling as long as this object is alive.
// Can be nested, in which case the profiling is re-enabled when all
// the objects go out of scope.
class disable_backtrace_temporarily {
    bool _old;
public:
    disable_backtrace_temporarily();
    ~disable_backtrace_temporarily();
};

enum class reclaiming_result {
    reclaimed_nothing,
    reclaimed_something
};

// Determines when reclaimer can be invoked
enum class reclaimer_scope {
    //
    // Reclaimer is only invoked in its own fiber. That fiber will be
    // given higher priority than regular application fibers.
    //
    async,

    //
    // Reclaimer may be invoked synchronously with allocation.
    // It may also be invoked in async scope.
    //
    // Reclaimer may invoke allocation, though it is discouraged because
    // the system may be low on memory and such allocations may fail.
    // Reclaimers which allocate should be prepared for re-entry.
    //
    sync
};

class reclaimer {
public:
    struct request {
        // The number of bytes which is needed to be released.
        // The reclaimer can release a different amount.
        // If less is released then the reclaimer may be invoked again.
        size_t bytes_to_reclaim;
    };
    using reclaim_fn = std::function<reclaiming_result ()>;
private:
    std::function<reclaiming_result (request)> _reclaim;
    reclaimer_scope _scope;
public:
    // Installs new reclaimer which will be invoked when system is falling
    // low on memory. 'scope' determines when reclaimer can be executed.
    reclaimer(std::function<reclaiming_result ()> reclaim, reclaimer_scope scope = reclaimer_scope::async);
    reclaimer(std::function<reclaiming_result (request)> reclaim, reclaimer_scope scope = reclaimer_scope::async);
    ~reclaimer();
    reclaiming_result do_reclaim(size_t bytes_to_reclaim) { return _reclaim(request{bytes_to_reclaim}); }
    reclaimer_scope scope() const { return _scope; }
};

extern std::pmr::polymorphic_allocator<char>* malloc_allocator;

// Call periodically to recycle objects that were freed
// on cpu other than the one they were allocated on.
//
// Returns @true if any work was actually performed.
bool drain_cross_cpu_freelist();

// We don't want the memory code calling back into the rest of
// the system, so allow the rest of the system to tell the memory
// code how to initiate reclaim.
//
// When memory is low, calling \c hook(fn) will result in fn being called
// in a safe place wrt. allocations.
void set_reclaim_hook(
        std::function<void (std::function<void ()>)> hook);

/// \endcond

class statistics;

/// Capture a snapshot of memory allocation statistics for this lcore.
statistics stats();

/// Memory allocation statistics.
class statistics {
    uint64_t _mallocs;
    uint64_t _frees;
    uint64_t _cross_cpu_frees;
    size_t _total_memory;
    size_t _free_memory;
    uint64_t _reclaims;
    uint64_t _large_allocs;

    uint64_t _foreign_mallocs;
    uint64_t _foreign_frees;
    uint64_t _foreign_cross_frees;
private:
    statistics(uint64_t mallocs, uint64_t frees, uint64_t cross_cpu_frees,
            uint64_t total_memory, uint64_t free_memory, uint64_t reclaims, uint64_t large_allocs,
            uint64_t foreign_mallocs, uint64_t foreign_frees, uint64_t foreign_cross_frees)
        : _mallocs(mallocs), _frees(frees), _cross_cpu_frees(cross_cpu_frees)
        , _total_memory(total_memory), _free_memory(free_memory), _reclaims(reclaims), _large_allocs(large_allocs)
        , _foreign_mallocs(foreign_mallocs), _foreign_frees(foreign_frees)
        , _foreign_cross_frees(foreign_cross_frees) {}
public:
    /// Total number of memory allocations calls since the system was started.
    uint64_t mallocs() const { return _mallocs; }
    /// Total number of memory deallocations calls since the system was started.
    uint64_t frees() const { return _frees; }
    /// Total number of memory deallocations that occured on a different lcore
    /// than the one on which they were allocated.
    uint64_t cross_cpu_frees() const { return _cross_cpu_frees; }
    /// Total number of objects which were allocated but not freed.
    size_t live_objects() const { return mallocs() - frees(); }
    /// Total free memory (in bytes)
    size_t free_memory() const { return _free_memory; }
    /// Total allocated memory (in bytes)
    size_t allocated_memory() const { return _total_memory - _free_memory; }
    /// Total memory (in bytes)
    size_t total_memory() const { return _total_memory; }
    /// Number of reclaims performed due to low memory
    uint64_t reclaims() const { return _reclaims; }
    /// Number of allocations which violated the large allocation threshold
    uint64_t large_allocations() const { return _large_allocs; }
    /// Number of foreign allocations
    uint64_t foreign_mallocs() const { return _foreign_mallocs; }
    /// Number of foreign frees
    uint64_t foreign_frees() const { return _foreign_frees; }
    /// Number of foreign frees on reactor threads
    uint64_t foreign_cross_frees() const { return _foreign_cross_frees; }
    friend statistics stats();
};

struct memory_layout {
    uintptr_t start;
    uintptr_t end;
};

// Discover virtual address range used by the allocator on current shard.
// Supported only when seastar allocator is enabled.
memory::memory_layout get_memory_layout();

/// Returns the value of free memory low water mark in bytes.
/// When free memory is below this value, reclaimers are invoked until it goes above again.
size_t min_free_memory();

/// Sets the value of free memory low water mark in memory::page_size units.
void set_min_free_pages(size_t pages);

/// Enable the large allocation warning threshold.
///
/// Warn when allocation above a given threshold are performed.
///
/// \param threshold size (in bytes) above which an allocation will be logged
void set_large_allocation_warning_threshold(size_t threshold);

/// Gets the current large allocation warning threshold.
size_t get_large_allocation_warning_threshold();

/// Disable large allocation warnings.
void disable_large_allocation_warning();

/// Set a different large allocation warning threshold for a scope.
class scoped_large_allocation_warning_threshold {
    size_t _old_threshold;
public:
    explicit scoped_large_allocation_warning_threshold(size_t threshold)
            : _old_threshold(get_large_allocation_warning_threshold()) {
        set_large_allocation_warning_threshold(threshold);
    }
    scoped_large_allocation_warning_threshold(const scoped_large_allocation_warning_threshold&) = delete;
    scoped_large_allocation_warning_threshold(scoped_large_allocation_warning_threshold&& x) = delete;
    ~scoped_large_allocation_warning_threshold() {
        if (_old_threshold) {
            set_large_allocation_warning_threshold(_old_threshold);
        }
    }
    void operator=(const scoped_large_allocation_warning_threshold&) const = delete;
    void operator=(scoped_large_allocation_warning_threshold&&) = delete;
};

/// Disable large allocation warnings for a scope.
class scoped_large_allocation_warning_disable {
    size_t _old_threshold;
public:
    scoped_large_allocation_warning_disable()
            : _old_threshold(get_large_allocation_warning_threshold()) {
        disable_large_allocation_warning();
    }
    scoped_large_allocation_warning_disable(const scoped_large_allocation_warning_disable&) = delete;
    scoped_large_allocation_warning_disable(scoped_large_allocation_warning_disable&& x) = delete;
    ~scoped_large_allocation_warning_disable() {
        if (_old_threshold) {
            set_large_allocation_warning_threshold(_old_threshold);
        }
    }
    void operator=(const scoped_large_allocation_warning_disable&) const = delete;
    void operator=(scoped_large_allocation_warning_disable&&) = delete;
};

/// Enable/disable heap profiling.
///
/// In order to use heap profiling you have to define
/// `SEASTAR_HEAPPROF`.
/// Heap profiling data is not currently exposed via an API for
/// inspection, instead it was designed to be inspected from a
/// debugger.
/// For an example script that makes use of the heap profiling data
/// see [scylla-gdb.py] (https://github.com/scylladb/scylla/blob/e1b22b6a4c56b4f1d0adf65d1a11db4bcb51fe7d/scylla-gdb.py#L1439)
/// This script can generate either textual representation of the data,
/// or a zoomable flame graph ([flame graph generation instructions](https://github.com/scylladb/scylla/wiki/Seastar-heap-profiler),
/// [example flame graph](https://user-images.githubusercontent.com/1389273/72920437-f0cf8a80-3d51-11ea-92f0-f3dbeb698871.png)).
void set_heap_profiling_enabled(bool);

/// Enable heap profiling for the duration of the scope.
///
/// For more information about heap profiling see
/// \ref set_heap_profiling_enabled().
class scoped_heap_profiling {
public:
    scoped_heap_profiling() noexcept;
    ~scoped_heap_profiling();
};

}
}
<commit_msg>memory: document existing diagnostics and debugging features<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/core/resource.hh>
#include <seastar/core/bitops.hh>
#include <new>
#include <functional>
#include <vector>

namespace seastar {

/// \defgroup memory-module Memory management
///
/// Functions and classes for managing memory.
///
/// Memory management in seastar consists of the following:
///
///   - Low-level memory management in the \ref memory namespace.
///   - Various smart pointers: \ref shared_ptr, \ref lw_shared_ptr,
///     and \ref foreign_ptr.
///   - zero-copy support: \ref temporary_buffer and \ref deleter.

/// Low-level memory management support
///
/// The \c memory namespace provides functions and classes for interfacing
/// with the seastar memory allocator.
///
/// The seastar memory allocator splits system memory into a pool per
/// logical core (lcore).  Memory allocated one an lcore should be freed
/// on the same lcore; failing to do so carries a severe performance
/// penalty.  It is possible to share memory with another core, but this
/// should be limited to avoid cache coherency traffic.
/// You can obtain the memory layout of the current shard with
/// \ref get_memory_layout().
///
/// ## Diagnostics and debugging features
///
/// ### Allocation failure injector
///
/// Allows injecting allocation failures for testing resiliency against
/// allocation failures, or exceptions in general. See:
/// * \ref alloc_failure_injector
/// * \ref with_allocation_failures()
///
/// ### Large allocation warning
///
/// Large allocations put great pressure on the allocator which might be unable
/// to serve them even if there is enough memory available, due to memory
/// fragmentation. This is especially relevant for long-running applications,
/// the kind of applications that are typically built with seastar. This feature
/// allows finding these large by logging a warning on large allocations, with
/// the stacktrace of the. See:
/// * \ref set_large_allocation_warning_threshold()
/// * \ref get_large_allocation_warning_threshold()
/// * \ref scoped_large_allocation_warning_threshold
/// * \ref scoped_large_allocation_warning_disable
///
/// ### Heap profiling
///
/// Heap profiling allows finding out how memory is used by your application, by
/// recording the stacktrace of all allocations. See:
/// * \ref set_heap_profiling_enabled()
/// * \ref scoped_heap_profiling
///
/// ### Abort on allocation failure
///
/// Often, the best way to debug an allocation failure is a coredump. This
/// feature allows dumping core on allocation failures, containing the stack of
/// the failed allocation, by means of aborting. To enable set the
/// `abort_on_seastar_bad_alloc` configuration option or the respective command
/// line flag.
///
/// ### Dump diagnostics report
///
/// Dump a diagnostic report of the state of the seastar allocator upon allocation
/// failure. The report is dumped with the `seastar_memory` logger, with debug
/// level.
namespace memory {

/// \cond internal

#ifdef SEASTAR_OVERRIDE_ALLOCATOR_PAGE_SIZE
#define SEASTAR_INTERNAL_ALLOCATOR_PAGE_SIZE (SEASTAR_OVERRIDE_ALLOCATOR_PAGE_SIZE)
#else
#define SEASTAR_INTERNAL_ALLOCATOR_PAGE_SIZE 4096
#endif

static constexpr size_t page_size = SEASTAR_INTERNAL_ALLOCATOR_PAGE_SIZE;
static constexpr size_t page_bits = log2ceil(page_size);
static constexpr size_t huge_page_size =
#if defined(__x86_64__) || defined(__i386__) || defined(__s390x__) || defined(__zarch__)
    1 << 21; // 2M
#elif defined(__aarch64__)
    1 << 21; // 2M
#elif defined(__PPC__)
    1 << 24; // 16M
#else
#error "Huge page size is not defined for this architecture"
#endif

void configure(std::vector<resource::memory> m, bool mbind,
        std::optional<std::string> hugetlbfs_path = {});

void enable_abort_on_allocation_failure();

class disable_abort_on_alloc_failure_temporarily {
public:
    disable_abort_on_alloc_failure_temporarily();
    ~disable_abort_on_alloc_failure_temporarily() noexcept;
};

// Disables heap profiling as long as this object is alive.
// Can be nested, in which case the profiling is re-enabled when all
// the objects go out of scope.
class disable_backtrace_temporarily {
    bool _old;
public:
    disable_backtrace_temporarily();
    ~disable_backtrace_temporarily();
};

enum class reclaiming_result {
    reclaimed_nothing,
    reclaimed_something
};

// Determines when reclaimer can be invoked
enum class reclaimer_scope {
    //
    // Reclaimer is only invoked in its own fiber. That fiber will be
    // given higher priority than regular application fibers.
    //
    async,

    //
    // Reclaimer may be invoked synchronously with allocation.
    // It may also be invoked in async scope.
    //
    // Reclaimer may invoke allocation, though it is discouraged because
    // the system may be low on memory and such allocations may fail.
    // Reclaimers which allocate should be prepared for re-entry.
    //
    sync
};

class reclaimer {
public:
    struct request {
        // The number of bytes which is needed to be released.
        // The reclaimer can release a different amount.
        // If less is released then the reclaimer may be invoked again.
        size_t bytes_to_reclaim;
    };
    using reclaim_fn = std::function<reclaiming_result ()>;
private:
    std::function<reclaiming_result (request)> _reclaim;
    reclaimer_scope _scope;
public:
    // Installs new reclaimer which will be invoked when system is falling
    // low on memory. 'scope' determines when reclaimer can be executed.
    reclaimer(std::function<reclaiming_result ()> reclaim, reclaimer_scope scope = reclaimer_scope::async);
    reclaimer(std::function<reclaiming_result (request)> reclaim, reclaimer_scope scope = reclaimer_scope::async);
    ~reclaimer();
    reclaiming_result do_reclaim(size_t bytes_to_reclaim) { return _reclaim(request{bytes_to_reclaim}); }
    reclaimer_scope scope() const { return _scope; }
};

extern std::pmr::polymorphic_allocator<char>* malloc_allocator;

// Call periodically to recycle objects that were freed
// on cpu other than the one they were allocated on.
//
// Returns @true if any work was actually performed.
bool drain_cross_cpu_freelist();

// We don't want the memory code calling back into the rest of
// the system, so allow the rest of the system to tell the memory
// code how to initiate reclaim.
//
// When memory is low, calling \c hook(fn) will result in fn being called
// in a safe place wrt. allocations.
void set_reclaim_hook(
        std::function<void (std::function<void ()>)> hook);

/// \endcond

class statistics;

/// Capture a snapshot of memory allocation statistics for this lcore.
statistics stats();

/// Memory allocation statistics.
class statistics {
    uint64_t _mallocs;
    uint64_t _frees;
    uint64_t _cross_cpu_frees;
    size_t _total_memory;
    size_t _free_memory;
    uint64_t _reclaims;
    uint64_t _large_allocs;

    uint64_t _foreign_mallocs;
    uint64_t _foreign_frees;
    uint64_t _foreign_cross_frees;
private:
    statistics(uint64_t mallocs, uint64_t frees, uint64_t cross_cpu_frees,
            uint64_t total_memory, uint64_t free_memory, uint64_t reclaims, uint64_t large_allocs,
            uint64_t foreign_mallocs, uint64_t foreign_frees, uint64_t foreign_cross_frees)
        : _mallocs(mallocs), _frees(frees), _cross_cpu_frees(cross_cpu_frees)
        , _total_memory(total_memory), _free_memory(free_memory), _reclaims(reclaims), _large_allocs(large_allocs)
        , _foreign_mallocs(foreign_mallocs), _foreign_frees(foreign_frees)
        , _foreign_cross_frees(foreign_cross_frees) {}
public:
    /// Total number of memory allocations calls since the system was started.
    uint64_t mallocs() const { return _mallocs; }
    /// Total number of memory deallocations calls since the system was started.
    uint64_t frees() const { return _frees; }
    /// Total number of memory deallocations that occured on a different lcore
    /// than the one on which they were allocated.
    uint64_t cross_cpu_frees() const { return _cross_cpu_frees; }
    /// Total number of objects which were allocated but not freed.
    size_t live_objects() const { return mallocs() - frees(); }
    /// Total free memory (in bytes)
    size_t free_memory() const { return _free_memory; }
    /// Total allocated memory (in bytes)
    size_t allocated_memory() const { return _total_memory - _free_memory; }
    /// Total memory (in bytes)
    size_t total_memory() const { return _total_memory; }
    /// Number of reclaims performed due to low memory
    uint64_t reclaims() const { return _reclaims; }
    /// Number of allocations which violated the large allocation threshold
    uint64_t large_allocations() const { return _large_allocs; }
    /// Number of foreign allocations
    uint64_t foreign_mallocs() const { return _foreign_mallocs; }
    /// Number of foreign frees
    uint64_t foreign_frees() const { return _foreign_frees; }
    /// Number of foreign frees on reactor threads
    uint64_t foreign_cross_frees() const { return _foreign_cross_frees; }
    friend statistics stats();
};

struct memory_layout {
    uintptr_t start;
    uintptr_t end;
};

// Discover virtual address range used by the allocator on current shard.
// Supported only when seastar allocator is enabled.
memory::memory_layout get_memory_layout();

/// Returns the value of free memory low water mark in bytes.
/// When free memory is below this value, reclaimers are invoked until it goes above again.
size_t min_free_memory();

/// Sets the value of free memory low water mark in memory::page_size units.
void set_min_free_pages(size_t pages);

/// Enable the large allocation warning threshold.
///
/// Warn when allocation above a given threshold are performed.
///
/// \param threshold size (in bytes) above which an allocation will be logged
void set_large_allocation_warning_threshold(size_t threshold);

/// Gets the current large allocation warning threshold.
size_t get_large_allocation_warning_threshold();

/// Disable large allocation warnings.
void disable_large_allocation_warning();

/// Set a different large allocation warning threshold for a scope.
class scoped_large_allocation_warning_threshold {
    size_t _old_threshold;
public:
    explicit scoped_large_allocation_warning_threshold(size_t threshold)
            : _old_threshold(get_large_allocation_warning_threshold()) {
        set_large_allocation_warning_threshold(threshold);
    }
    scoped_large_allocation_warning_threshold(const scoped_large_allocation_warning_threshold&) = delete;
    scoped_large_allocation_warning_threshold(scoped_large_allocation_warning_threshold&& x) = delete;
    ~scoped_large_allocation_warning_threshold() {
        if (_old_threshold) {
            set_large_allocation_warning_threshold(_old_threshold);
        }
    }
    void operator=(const scoped_large_allocation_warning_threshold&) const = delete;
    void operator=(scoped_large_allocation_warning_threshold&&) = delete;
};

/// Disable large allocation warnings for a scope.
class scoped_large_allocation_warning_disable {
    size_t _old_threshold;
public:
    scoped_large_allocation_warning_disable()
            : _old_threshold(get_large_allocation_warning_threshold()) {
        disable_large_allocation_warning();
    }
    scoped_large_allocation_warning_disable(const scoped_large_allocation_warning_disable&) = delete;
    scoped_large_allocation_warning_disable(scoped_large_allocation_warning_disable&& x) = delete;
    ~scoped_large_allocation_warning_disable() {
        if (_old_threshold) {
            set_large_allocation_warning_threshold(_old_threshold);
        }
    }
    void operator=(const scoped_large_allocation_warning_disable&) const = delete;
    void operator=(scoped_large_allocation_warning_disable&&) = delete;
};

/// Enable/disable heap profiling.
///
/// In order to use heap profiling you have to define
/// `SEASTAR_HEAPPROF`.
/// Heap profiling data is not currently exposed via an API for
/// inspection, instead it was designed to be inspected from a
/// debugger.
/// For an example script that makes use of the heap profiling data
/// see [scylla-gdb.py] (https://github.com/scylladb/scylla/blob/e1b22b6a4c56b4f1d0adf65d1a11db4bcb51fe7d/scylla-gdb.py#L1439)
/// This script can generate either textual representation of the data,
/// or a zoomable flame graph ([flame graph generation instructions](https://github.com/scylladb/scylla/wiki/Seastar-heap-profiler),
/// [example flame graph](https://user-images.githubusercontent.com/1389273/72920437-f0cf8a80-3d51-11ea-92f0-f3dbeb698871.png)).
void set_heap_profiling_enabled(bool);

/// Enable heap profiling for the duration of the scope.
///
/// For more information about heap profiling see
/// \ref set_heap_profiling_enabled().
class scoped_heap_profiling {
public:
    scoped_heap_profiling() noexcept;
    ~scoped_heap_profiling();
};

}
}
<|endoftext|>


<commit_before>#ifndef _INCLUDED_DS_TEXTDS_HPP
#define _INCLUDED_DS_TEXTDS_HPP

#include <cmath>
#include <ostream>

#include <sdsl/int_vector.hpp>

#include <tudocomp/io.hpp>
#include "forward.hpp"

#include <tudocomp/Literal.hpp>

namespace tdc {

using io::InputView;

/// Manages text related data structures.
template<
    class lcp_tt = LCPArray,
    template<typename> class isa_tt = InverseSuffixArray>
class TextDS {

public:
    typedef uint8_t value_type;
    static const uint64_t SA = 0x01;
    static const uint64_t ISA = 0x02;
    static const uint64_t Phi = 0x04;
    static const uint64_t LCP = 0x08;
    typedef TextDS<lcp_tt,isa_tt> this_t;
    typedef typename lcp_tt::template construct_t<this_t> lcp_t;
    typedef isa_tt<this_t> isa_t;
    typedef SuffixArray<this_t> sa_t;
    typedef PhiArray<this_t> phi_t;

private:
    size_t m_size;
    const value_type* m_text;

    std::unique_ptr<sa_t>  m_sa;
    std::unique_ptr<isa_t> m_isa;
    std::unique_ptr<phi_t> m_phi;
    std::unique_ptr<lcp_t> m_lcp;

    class Literals {
    protected:
        const this_t* m_text;
        size_t m_pos;

    public:
        inline Literals(const this_t& text) : m_text(&text), m_pos(0) {}

        inline bool has_next() const {
            return m_pos < m_text->size();
        }

        inline Literal next() {
            assert(has_next());

            auto i = m_pos++;
            return {(*m_text)[i], i};
        }
    };

public:
    inline TextDS(const InputView& input)
        : m_size(input.size()), m_text((const value_type*)input.data())
    {
        if(!input.is_terminal_null_ensured())
             throw std::logic_error("Terminal Null is not ensured. Please invoke the method ensure_null_terminator() on your input before creating TextDS");
    }

    inline TextDS(const InputView& input, uint64_t flags) : TextDS(input)
    {
        if(!input.is_terminal_null_ensured())
             throw std::logic_error("Terminal Null is not ensured. Please invoke the method ensure_null_terminator() on your input before creating TextDS");
        require(flags);
    }

    /// Constructs the required data structures as denoted by the given flags
    /// and releases all unwanted ones in a second step.
    inline void require(uint64_t flags) {
        //Step 1: construct
        if(flags & SA) require_sa();
        if(flags & ISA) require_isa();
        if(flags & Phi) require_phi();
        if(flags & LCP) require_lcp();

        //Step 2: release unwanted (may have been constructed beforehand)
        if(!(flags & SA)) release_sa();
        if(!(flags & ISA)) release_isa();
        if(!(flags & Phi)) release_phi();
        if(!(flags & LCP)) release_lcp();
    }

    /// Requires the Suffix Array to be constructed if not already present.
    inline const sa_t& require_sa();

    /// Requires the Phi Array to be constructed if not already present.
    inline const phi_t& require_phi();

    /// Requires the Inverse Suffix Array to be constructed if not already present.
    inline const isa_t& require_isa();

    /// Requires the LCP Array to be constructed if not already present.
    inline const lcp_t& require_lcp();

    /// Releases the suffix array if present.
    inline std::unique_ptr<sa_t> release_sa() {
        return std::move(m_sa);
    }

    /// Releases the inverse suffix array array if present.
    inline std::unique_ptr<isa_t> release_isa() {
        return std::move(m_isa);
    }

    /// Releases the Phi array if present.
    inline std::unique_ptr<phi_t> release_phi() {
        return std::move(m_phi);
    }

    /// Releases the LCP array if present.
    inline std::unique_ptr<lcp_t> release_lcp() {
        return std::move(m_lcp);
    }

    /// Accesses the input text at position i.
    inline value_type operator[](size_t i) const {
        return m_text[i];
    }

    /// Provides access to the input text.
    inline const value_type* text() const {
        return m_text;
    }

    /// Returns the size of the input text.
    inline size_t size() const {
        return m_size;
    }

    /// Prints the constructed tables.
    inline void print(std::ostream& out, size_t base = 0);

    inline Literals literals() const {
        return iterator(*this, 0);
    }
};

}//ns

#include <tudocomp/ds/SuffixArray.hpp>
#include <tudocomp/ds/InverseSuffixArray.hpp>
#include <tudocomp/ds/PhiArray.hpp>
#include <tudocomp/ds/LCPArray.hpp>

namespace tdc {

template<
    class lcp_tt,
    template<typename> class isa_tt>
inline void TextDS<lcp_tt,isa_tt>::print(std::ostream& out, size_t base) {
    size_t w = std::max(6UL, (size_t)std::log10((double)m_size) + 1);
    out << std::setfill(' ');

    //Heading
    out << std::setw(w) << "i" << " | ";
    if(m_sa) out << std::setw(w) << "SA[i]" << " | ";
    if(m_isa) out << std::setw(w) << "ISA[i]" << " | ";
    if(m_phi) out << std::setw(w) << "Phi[i]" << " | ";
    if(m_lcp) out << std::setw(w) << "LCP[i]" << " | ";
    out << std::endl;

    //Separator
    out << std::setfill('-');
    out << std::setw(w) << "" << "-|-";
    if(m_sa) out << std::setw(w) << "" << "-|-";
    if(m_isa) out << std::setw(w) << "" << "-|-";
    if(m_phi) out << std::setw(w) << "" << "-|-";
    if(m_lcp) out << std::setw(w) << "" << "-|-";
    out << std::endl;

    //Body
    out << std::setfill(' ');
    for(size_t i = 0; i < m_size + 1; i++) {
        out << std::setw(w) << (i + base) << " | ";
        if(m_sa) out << std::setw(w) << ((*m_sa)[i] + base) << " | ";
        if(m_isa) out << std::setw(w) << ((*m_isa)[i] + base) << " | ";
        if(m_phi) out << std::setw(w) << ((*m_phi)[i] + base) << " | ";
        if(m_lcp) out << std::setw(w) << (*m_lcp)[i] << " | ";
        out << std::endl;
    }
}

template<
    class lcp_tt,
    template<typename> class isa_tt>
const SuffixArray<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_sa() {
    if(!m_sa) {
        m_sa = std::unique_ptr<sa_t>(new sa_t());
        m_sa->construct(*this);
    }
    return *m_sa;
}

template<
    class lcp_tt,
    template<typename> class isa_tt>
const PhiArray<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_phi() {
    if(!m_phi) {
        m_phi = std::unique_ptr<phi_t>(new phi_t());
        m_phi->construct(*this);
    }

    return *m_phi;
}

template<
    class lcp_tt,
    template<typename> class isa_tt>
const isa_tt<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_isa() {
    if(!m_isa) {
        m_isa = std::unique_ptr<isa_t>(new isa_t());
        m_isa->construct(*this);
    }

    return *m_isa;
}

template<class lcp_tt,
    template<typename> class isa_tt>
const typename TextDS<lcp_tt,isa_tt>::lcp_t& TextDS<lcp_tt,isa_tt>::require_lcp() {
    if(!m_lcp) {
        m_lcp = std::unique_ptr<lcp_t>(new lcp_t());
        m_lcp->construct(*this);
    }
    return *m_lcp;
}

//typedef TextDS<lcp_sada<TextDS<lcp_sada,InverseSuffixArray>, InverseSuffixArray<TextDS<lcp_sada,InverseSuffixArray>> TextDSI;
typedef TextDS<LCPArray, InverseSuffixArray> TextDSI;
}//ns

#endif

<commit_msg>Fix TextDS<commit_after>#ifndef _INCLUDED_DS_TEXTDS_HPP
#define _INCLUDED_DS_TEXTDS_HPP

#include <cmath>
#include <ostream>

#include <sdsl/int_vector.hpp>

#include <tudocomp/io.hpp>
#include "forward.hpp"

#include <tudocomp/Literal.hpp>

namespace tdc {

using io::InputView;

/// Manages text related data structures.
template<
    class lcp_tt = LCPArray,
    template<typename> class isa_tt = InverseSuffixArray>
class TextDS {

public:
    typedef uint8_t value_type;
    static const uint64_t SA = 0x01;
    static const uint64_t ISA = 0x02;
    static const uint64_t Phi = 0x04;
    static const uint64_t LCP = 0x08;
    typedef TextDS<lcp_tt,isa_tt> this_t;
    typedef typename lcp_tt::template construct_t<this_t> lcp_t;
    typedef isa_tt<this_t> isa_t;
    typedef SuffixArray<this_t> sa_t;
    typedef PhiArray<this_t> phi_t;

private:
    size_t m_size;
    const value_type* m_text;

    std::unique_ptr<sa_t>  m_sa;
    std::unique_ptr<isa_t> m_isa;
    std::unique_ptr<phi_t> m_phi;
    std::unique_ptr<lcp_t> m_lcp;

    class Literals {
    protected:
        const this_t* m_text;
        size_t m_pos;

    public:
        inline Literals(const this_t& text) : m_text(&text), m_pos(0) {}

        inline bool has_next() const {
            return m_pos < m_text->size();
        }

        inline Literal next() {
            assert(has_next());

            auto i = m_pos++;
            return {(*m_text)[i], i};
        }
    };
private:
    inline static void null_check(View view) {
        if(!view.ends_with(uint8_t(0))){
             throw std::logic_error(
                 "Input is not 0 terminated! Please make sure you declare "
                 "the compressor calling this with "
                 "`m.needs_sentinel_terminator()` in its `meta()` function."
            );
        }
    }

public:
    inline TextDS(const View& input)
        : m_size(input.size()), m_text((const value_type*)input.data())
    {
        null_check(input);
    }

    inline TextDS(const InputView& input, uint64_t flags) : TextDS(input)
    {
        null_check(input);
        require(flags);
    }

    /// Constructs the required data structures as denoted by the given flags
    /// and releases all unwanted ones in a second step.
    inline void require(uint64_t flags) {
        //Step 1: construct
        if(flags & SA) require_sa();
        if(flags & ISA) require_isa();
        if(flags & Phi) require_phi();
        if(flags & LCP) require_lcp();

        //Step 2: release unwanted (may have been constructed beforehand)
        if(!(flags & SA)) release_sa();
        if(!(flags & ISA)) release_isa();
        if(!(flags & Phi)) release_phi();
        if(!(flags & LCP)) release_lcp();
    }

    /// Requires the Suffix Array to be constructed if not already present.
    inline const sa_t& require_sa();

    /// Requires the Phi Array to be constructed if not already present.
    inline const phi_t& require_phi();

    /// Requires the Inverse Suffix Array to be constructed if not already present.
    inline const isa_t& require_isa();

    /// Requires the LCP Array to be constructed if not already present.
    inline const lcp_t& require_lcp();

    /// Releases the suffix array if present.
    inline std::unique_ptr<sa_t> release_sa() {
        return std::move(m_sa);
    }

    /// Releases the inverse suffix array array if present.
    inline std::unique_ptr<isa_t> release_isa() {
        return std::move(m_isa);
    }

    /// Releases the Phi array if present.
    inline std::unique_ptr<phi_t> release_phi() {
        return std::move(m_phi);
    }

    /// Releases the LCP array if present.
    inline std::unique_ptr<lcp_t> release_lcp() {
        return std::move(m_lcp);
    }

    /// Accesses the input text at position i.
    inline value_type operator[](size_t i) const {
        return m_text[i];
    }

    /// Provides access to the input text.
    inline const value_type* text() const {
        return m_text;
    }

    /// Returns the size of the input text.
    inline size_t size() const {
        return m_size;
    }

    /// Prints the constructed tables.
    inline void print(std::ostream& out, size_t base = 0);

    inline Literals literals() const {
        return iterator(*this, 0);
    }
};

}//ns

#include <tudocomp/ds/SuffixArray.hpp>
#include <tudocomp/ds/InverseSuffixArray.hpp>
#include <tudocomp/ds/PhiArray.hpp>
#include <tudocomp/ds/LCPArray.hpp>

namespace tdc {

template<
    class lcp_tt,
    template<typename> class isa_tt>
inline void TextDS<lcp_tt,isa_tt>::print(std::ostream& out, size_t base) {
    size_t w = std::max(6UL, (size_t)std::log10((double)m_size) + 1);
    out << std::setfill(' ');

    //Heading
    out << std::setw(w) << "i" << " | ";
    if(m_sa) out << std::setw(w) << "SA[i]" << " | ";
    if(m_isa) out << std::setw(w) << "ISA[i]" << " | ";
    if(m_phi) out << std::setw(w) << "Phi[i]" << " | ";
    if(m_lcp) out << std::setw(w) << "LCP[i]" << " | ";
    out << std::endl;

    //Separator
    out << std::setfill('-');
    out << std::setw(w) << "" << "-|-";
    if(m_sa) out << std::setw(w) << "" << "-|-";
    if(m_isa) out << std::setw(w) << "" << "-|-";
    if(m_phi) out << std::setw(w) << "" << "-|-";
    if(m_lcp) out << std::setw(w) << "" << "-|-";
    out << std::endl;

    //Body
    out << std::setfill(' ');
    for(size_t i = 0; i < m_size + 1; i++) {
        out << std::setw(w) << (i + base) << " | ";
        if(m_sa) out << std::setw(w) << ((*m_sa)[i] + base) << " | ";
        if(m_isa) out << std::setw(w) << ((*m_isa)[i] + base) << " | ";
        if(m_phi) out << std::setw(w) << ((*m_phi)[i] + base) << " | ";
        if(m_lcp) out << std::setw(w) << (*m_lcp)[i] << " | ";
        out << std::endl;
    }
}

template<
    class lcp_tt,
    template<typename> class isa_tt>
const SuffixArray<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_sa() {
    if(!m_sa) {
        m_sa = std::unique_ptr<sa_t>(new sa_t());
        m_sa->construct(*this);
    }
    return *m_sa;
}

template<
    class lcp_tt,
    template<typename> class isa_tt>
const PhiArray<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_phi() {
    if(!m_phi) {
        m_phi = std::unique_ptr<phi_t>(new phi_t());
        m_phi->construct(*this);
    }

    return *m_phi;
}

template<
    class lcp_tt,
    template<typename> class isa_tt>
const isa_tt<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_isa() {
    if(!m_isa) {
        m_isa = std::unique_ptr<isa_t>(new isa_t());
        m_isa->construct(*this);
    }

    return *m_isa;
}

template<class lcp_tt,
    template<typename> class isa_tt>
const typename TextDS<lcp_tt,isa_tt>::lcp_t& TextDS<lcp_tt,isa_tt>::require_lcp() {
    if(!m_lcp) {
        m_lcp = std::unique_ptr<lcp_t>(new lcp_t());
        m_lcp->construct(*this);
    }
    return *m_lcp;
}

//typedef TextDS<lcp_sada<TextDS<lcp_sada,InverseSuffixArray>, InverseSuffixArray<TextDS<lcp_sada,InverseSuffixArray>> TextDSI;
typedef TextDS<LCPArray, InverseSuffixArray> TextDSI;
}//ns

#endif

<|endoftext|>


<commit_before>#ifndef FOR_EACH_PAIR_HPP
#define FOR_EACH_PAIR_HPP

#include <iterator>
#include <numeric>

namespace osrm
{
namespace util
{

// TODO: check why this is not an option here:
// std::adjacent_find(begin, end, [=](const auto& l, const auto& r){ return function(), false; });
template <typename ForwardIterator, typename Function>
Function for_each_pair(ForwardIterator begin, ForwardIterator end, Function function)
{
    if (begin == end)
    {
        return function;
    }

    auto next = begin;
    next = std::next(next);

    while (next != end)
    {
        function(*begin, *next);
        begin = std::next(begin);
        next = std::next(next);
    }
    return function;
}

template <class ContainerT, typename Function>
Function for_each_pair(ContainerT &container, Function function)
{
    using std::begin;
    using std::end;
    return for_each_pair(begin(container), end(container), function);
}

} // namespace util
} // namespace osrm

#endif /* FOR_EACH_PAIR_HPP */
<commit_msg>Takes fn by forwarding ref. in for_each_pair, resolves #4148<commit_after>#ifndef FOR_EACH_PAIR_HPP
#define FOR_EACH_PAIR_HPP

#include <iterator>
#include <numeric>
#include <utility>

namespace osrm
{
namespace util
{

// TODO: check why this is not an option here:
// std::adjacent_find(begin, end, [=](const auto& l, const auto& r){ return function(), false; });
template <typename ForwardIterator, typename Function>
void for_each_pair(ForwardIterator begin, ForwardIterator end, Function &&function)
{
    if (begin == end)
    {
        return;
    }

    auto next = begin;
    next = std::next(next);

    while (next != end)
    {
        std::forward<Function>(function)(*begin, *next);
        begin = std::next(begin);
        next = std::next(next);
    }
}

template <class ContainerT, typename Function>
void for_each_pair(ContainerT &container, Function &&function)
{
    using std::begin;
    using std::end;
    for_each_pair(begin(container), end(container), std::forward<Function>(function));
}

} // namespace util
} // namespace osrm

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


<commit_before>#line 12 "network.nw"
#include "network.h"

#include <QAbstractSocket>
#include <QTcpSocket>
#include <QTcpServer>
#include <QWebSocket>
#line 22 "network.nw"
// TcpClient functions/*{{{*/
int network_tcp_client(lua_State *L) {/*{{{*/
  QTcpSocket  *tcpSocket = new QTcpSocket();
  QTcpSocket **p = static_cast<QTcpSocket**>(lua_newuserdata(L, sizeof(QTcpServer*)));
  *p = tcpSocket;
  luaL_getmetatable(L, "network.TcpSocket");
  lua_setmetatable(L, -2);
  return 1;
}/*}}}*/
int tcp_socket_connect(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 33 "network.nw"
  const char* ip   = luaL_checkstring(L, 2);
  int         port = luaL_checkinteger(L, 3);
  tcpSocket->connectToHost(ip, port);
  return 0;
}/*}}}*/
int tcp_socket_read(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 40 "network.nw"
  int maxSize = luaL_checkinteger(L, 2);
  if(tcpSocket->isOpen()){
    QByteArray result = tcpSocket->read(maxSize);
    lua_pushlstring(L, result.data(), result.count());
  }
  return 1;
}/*}}}*/

int tcp_socket_read_all(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 40 "network.nw"
  QByteArray result = tcpSocket->readAll();
  lua_pushlstring(L, result.data(), result.count());
  return 1;
}/*}}}*/

int tcp_socket_write(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 47 "network.nw"
  size_t size;
  const char* data = luaL_checklstring(L, 2, &size);
  if(tcpSocket->isOpen()) {
    int result = tcpSocket->write(data, size);
    lua_pushinteger(L, result);
  }
  return 1;
}/*}}}*/
int tcp_socket_close(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 55 "network.nw"
  tcpSocket->close();
  return 0;
}/*}}}*/
int tcp_socket_delete(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 60 "network.nw"
  delete tcpSocket;
  return 0;
}/*}}}*/
/*}}}*/
#line 69 "network.nw"
// TcpServer functions/*{{{*/
int network_tcp_server(lua_State *L) {/*{{{*/
  QTcpServer *tcpServer = new QTcpServer();
  QTcpServer **p = static_cast<QTcpServer**>(lua_newuserdata(L, sizeof(QTcpServer*)));
  *p = tcpServer;
  luaL_getmetatable(L, "network.TcpServer");
  lua_setmetatable(L, -2);
  return 1;
}/*}}}*/
int tcp_server_listen(lua_State *L)/*{{{*/
{

#line 111 "network.nw"
QTcpServer *tcpServer =
  *static_cast<QTcpServer**>(luaL_checkudata(L, 1, "network.TcpServer"));
#line 81 "network.nw"
  const char * ip = luaL_checkstring(L, 2);
  QHostAddress addr(ip);
  int port = luaL_checkinteger(L, 3);
  lua_pushboolean(L, tcpServer->listen(QHostAddress::Any, port));

  return 1;
}/*}}}*/
int tcp_server_get_connection(lua_State *L)/*{{{*/
{

#line 111 "network.nw"
QTcpServer *tcpServer =
  *static_cast<QTcpServer**>(luaL_checkudata(L, 1, "network.TcpServer"));
#line 91 "network.nw"
  QTcpSocket *tcpSocket = tcpServer->nextPendingConnection();
  if (tcpSocket) {
    QTcpSocket **p = static_cast<QTcpSocket**>(lua_newuserdata(L, sizeof(QTcpServer*)));
    *p = tcpSocket;
    luaL_getmetatable(L, "network.TcpSocket");
    lua_setmetatable(L, -2);
  } else {
    lua_pushnil(L);
  }

  return 1;
}/*}}}*/
int tcp_server_delete(lua_State *L) {/*{{{*/

#line 111 "network.nw"
QTcpServer *tcpServer =
  *static_cast<QTcpServer**>(luaL_checkudata(L, 1, "network.TcpServer"));
#line 105 "network.nw"
  delete tcpServer;
  return 0;
}/*}}}*/

/*}}}*/
#line 115 "network.nw"
// WebSocket functions/*{{{*/
int network_web_socket(lua_State *L) {/*{{{*/
  QWebSocket *webSocket = new QWebSocket();
  QWebSocket **p = static_cast<QWebSocket**>(lua_newuserdata(L, sizeof(QWebSocket*)));
  *p = webSocket;
  luaL_getmetatable(L, "network.WebSocket");
  lua_setmetatable(L, -2);
  return 1;
}/*}}}*/
int web_socket_open(lua_State *L) {/*{{{*/

#line 153 "network.nw"
QWebSocket *webSocket =
  *static_cast<QWebSocket**>(luaL_checkudata(L, 1, "network.WebSocket"));
#line 126 "network.nw"
  QUrl url(luaL_checkstring(L, 2));
  url.setPort(lua_tointegerx(L, 3, NULL));
  webSocket->open(url);
  return 0;
}/*}}}*/
int web_socket_close(lua_State *L) {/*{{{*/

#line 153 "network.nw"
QWebSocket *webSocket =
  *static_cast<QWebSocket**>(luaL_checkudata(L, 1, "network.WebSocket"));
#line 133 "network.nw"
  webSocket->close();
  return 0;
}/*}}}*/
int web_socket_write(lua_State *L) {/*{{{*/

#line 153 "network.nw"
QWebSocket *webSocket =
  *static_cast<QWebSocket**>(luaL_checkudata(L, 1, "network.WebSocket"));
#line 138 "network.nw"
  size_t size;
  const char* data = luaL_checklstring(L, 2, &size);
  QByteArray b(data, size);
  int res = webSocket->sendTextMessage(b);
  lua_pushinteger(L, res);
  return 1;
}/*}}}*/

int web_socket_delete(lua_State *L) {/*{{{*/

#line 153 "network.nw"
QWebSocket *webSocket =
  *static_cast<QWebSocket**>(luaL_checkudata(L, 1, "network.WebSocket"));
#line 148 "network.nw"
  delete webSocket;
  return 0;
}/*}}}*/
/*}}}*/
#line 158 "network.nw"
int luaopen_network(lua_State *L) {
  lua_newtable(L);

  // TcpServer metatable/*{{{*/
  luaL_newmetatable(L, "network.TcpServer");

  lua_newtable(L);
  luaL_Reg tcp_server_functions[] = {
    { "listen", &tcp_server_listen },
    { "get_connection", &tcp_server_get_connection },
    { NULL, NULL }
  };
  luaL_setfuncs(L, tcp_server_functions, 0);
  lua_setfield(L, -2, "__index");
  lua_pushcfunction(L, tcp_server_delete);
  lua_setfield(L, -2, "__gc");/*}}}*/
  // TcpSocket metatable/*{{{*/
  luaL_newmetatable(L, "network.TcpSocket");

  lua_newtable(L);
  luaL_Reg tcp_socket_functions[] = {
    { "connect", &tcp_socket_connect },
    { "read", &tcp_socket_read },
    { "read_all", &tcp_socket_read_all },
    { "write", &tcp_socket_write },
    { "close", &tcp_socket_close },
    { NULL, NULL }
  };
  luaL_setfuncs(L, tcp_socket_functions, 0);

  lua_setfield(L, -2, "__index");
  lua_pushcfunction(L, tcp_socket_delete);
  lua_setfield(L, -2, "__gc");/*}}}*/
  // WebSocket metatable/*{{{*/
  luaL_newmetatable(L, "network.WebSocket");
  lua_newtable(L);
  luaL_Reg web_socket_functions[] = {
    { "open", &web_socket_open },
    { "close", &web_socket_close },
    { "write", &web_socket_write },
    { NULL, NULL }
  };
  luaL_setfuncs(L, web_socket_functions, 0);
  lua_setfield(L, -2, "__index");
  lua_pushcfunction(L, web_socket_delete);
  lua_setfield(L, -2, "__gc");/*}}}*/

  luaL_Reg network_functions[] = {
    { "TcpClient", &network_tcp_client },
    { "TcpServer", &network_tcp_server },
    { "WebSocket", &network_web_socket },
    { NULL, NULL }
  };
  luaL_newlib(L, network_functions);
  return 1;
}
<commit_msg>Add log in case not opened socket<commit_after>#line 12 "network.nw"
#include "network.h"

#include <QAbstractSocket>
#include <QTcpSocket>
#include <QTcpServer>
#include <QWebSocket>
#line 22 "network.nw"
// TcpClient functions/*{{{*/
int network_tcp_client(lua_State *L) {/*{{{*/
  QTcpSocket  *tcpSocket = new QTcpSocket();
  QTcpSocket **p = static_cast<QTcpSocket**>(lua_newuserdata(L, sizeof(QTcpServer*)));
  *p = tcpSocket;
  luaL_getmetatable(L, "network.TcpSocket");
  lua_setmetatable(L, -2);
  return 1;
}/*}}}*/
int tcp_socket_connect(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 33 "network.nw"
  const char* ip   = luaL_checkstring(L, 2);
  int         port = luaL_checkinteger(L, 3);
  tcpSocket->connectToHost(ip, port);
  return 0;
}/*}}}*/
int tcp_socket_read(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 40 "network.nw"
  int maxSize = luaL_checkinteger(L, 2);
  if(tcpSocket->isOpen()){
    QByteArray result = tcpSocket->read(maxSize);
    lua_pushlstring(L, result.data(), result.count());
  } else {
    fprintf(stderr, "Error: Socket not opened");
  }
  return 1;
}/*}}}*/

int tcp_socket_read_all(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 40 "network.nw"
  QByteArray result = tcpSocket->readAll();
  lua_pushlstring(L, result.data(), result.count());
  return 1;
}/*}}}*/

int tcp_socket_write(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 47 "network.nw"
  size_t size;
  const char* data = luaL_checklstring(L, 2, &size);
  if(tcpSocket->isOpen()) {
    int result = tcpSocket->write(data, size);
    lua_pushinteger(L, result);
  } else {
    fprintf(stderr, "Error: Socket not opened");
  }
  return 1;
}/*}}}*/
int tcp_socket_close(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 55 "network.nw"
  tcpSocket->close();
  return 0;
}/*}}}*/
int tcp_socket_delete(lua_State *L) {/*{{{*/

#line 65 "network.nw"
QTcpSocket *tcpSocket =
  *static_cast<QTcpSocket**>(luaL_checkudata(L, 1, "network.TcpSocket"));
#line 60 "network.nw"
  delete tcpSocket;
  return 0;
}/*}}}*/
/*}}}*/
#line 69 "network.nw"
// TcpServer functions/*{{{*/
int network_tcp_server(lua_State *L) {/*{{{*/
  QTcpServer *tcpServer = new QTcpServer();
  QTcpServer **p = static_cast<QTcpServer**>(lua_newuserdata(L, sizeof(QTcpServer*)));
  *p = tcpServer;
  luaL_getmetatable(L, "network.TcpServer");
  lua_setmetatable(L, -2);
  return 1;
}/*}}}*/
int tcp_server_listen(lua_State *L)/*{{{*/
{

#line 111 "network.nw"
QTcpServer *tcpServer =
  *static_cast<QTcpServer**>(luaL_checkudata(L, 1, "network.TcpServer"));
#line 81 "network.nw"
  const char * ip = luaL_checkstring(L, 2);
  QHostAddress addr(ip);
  int port = luaL_checkinteger(L, 3);
  lua_pushboolean(L, tcpServer->listen(QHostAddress::Any, port));

  return 1;
}/*}}}*/
int tcp_server_get_connection(lua_State *L)/*{{{*/
{

#line 111 "network.nw"
QTcpServer *tcpServer =
  *static_cast<QTcpServer**>(luaL_checkudata(L, 1, "network.TcpServer"));
#line 91 "network.nw"
  QTcpSocket *tcpSocket = tcpServer->nextPendingConnection();
  if (tcpSocket) {
    QTcpSocket **p = static_cast<QTcpSocket**>(lua_newuserdata(L, sizeof(QTcpServer*)));
    *p = tcpSocket;
    luaL_getmetatable(L, "network.TcpSocket");
    lua_setmetatable(L, -2);
  } else {
    lua_pushnil(L);
  }

  return 1;
}/*}}}*/
int tcp_server_delete(lua_State *L) {/*{{{*/

#line 111 "network.nw"
QTcpServer *tcpServer =
  *static_cast<QTcpServer**>(luaL_checkudata(L, 1, "network.TcpServer"));
#line 105 "network.nw"
  delete tcpServer;
  return 0;
}/*}}}*/

/*}}}*/
#line 115 "network.nw"
// WebSocket functions/*{{{*/
int network_web_socket(lua_State *L) {/*{{{*/
  QWebSocket *webSocket = new QWebSocket();
  QWebSocket **p = static_cast<QWebSocket**>(lua_newuserdata(L, sizeof(QWebSocket*)));
  *p = webSocket;
  luaL_getmetatable(L, "network.WebSocket");
  lua_setmetatable(L, -2);
  return 1;
}/*}}}*/
int web_socket_open(lua_State *L) {/*{{{*/

#line 153 "network.nw"
QWebSocket *webSocket =
  *static_cast<QWebSocket**>(luaL_checkudata(L, 1, "network.WebSocket"));
#line 126 "network.nw"
  QUrl url(luaL_checkstring(L, 2));
  url.setPort(lua_tointegerx(L, 3, NULL));
  webSocket->open(url);
  return 0;
}/*}}}*/
int web_socket_close(lua_State *L) {/*{{{*/

#line 153 "network.nw"
QWebSocket *webSocket =
  *static_cast<QWebSocket**>(luaL_checkudata(L, 1, "network.WebSocket"));
#line 133 "network.nw"
  webSocket->close();
  return 0;
}/*}}}*/
int web_socket_write(lua_State *L) {/*{{{*/

#line 153 "network.nw"
QWebSocket *webSocket =
  *static_cast<QWebSocket**>(luaL_checkudata(L, 1, "network.WebSocket"));
#line 138 "network.nw"
  size_t size;
  const char* data = luaL_checklstring(L, 2, &size);
  QByteArray b(data, size);
  int res = webSocket->sendTextMessage(b);
  lua_pushinteger(L, res);
  return 1;
}/*}}}*/

int web_socket_delete(lua_State *L) {/*{{{*/

#line 153 "network.nw"
QWebSocket *webSocket =
  *static_cast<QWebSocket**>(luaL_checkudata(L, 1, "network.WebSocket"));
#line 148 "network.nw"
  delete webSocket;
  return 0;
}/*}}}*/
/*}}}*/
#line 158 "network.nw"
int luaopen_network(lua_State *L) {
  lua_newtable(L);

  // TcpServer metatable/*{{{*/
  luaL_newmetatable(L, "network.TcpServer");

  lua_newtable(L);
  luaL_Reg tcp_server_functions[] = {
    { "listen", &tcp_server_listen },
    { "get_connection", &tcp_server_get_connection },
    { NULL, NULL }
  };
  luaL_setfuncs(L, tcp_server_functions, 0);
  lua_setfield(L, -2, "__index");
  lua_pushcfunction(L, tcp_server_delete);
  lua_setfield(L, -2, "__gc");/*}}}*/
  // TcpSocket metatable/*{{{*/
  luaL_newmetatable(L, "network.TcpSocket");

  lua_newtable(L);
  luaL_Reg tcp_socket_functions[] = {
    { "connect", &tcp_socket_connect },
    { "read", &tcp_socket_read },
    { "read_all", &tcp_socket_read_all },
    { "write", &tcp_socket_write },
    { "close", &tcp_socket_close },
    { NULL, NULL }
  };
  luaL_setfuncs(L, tcp_socket_functions, 0);

  lua_setfield(L, -2, "__index");
  lua_pushcfunction(L, tcp_socket_delete);
  lua_setfield(L, -2, "__gc");/*}}}*/
  // WebSocket metatable/*{{{*/
  luaL_newmetatable(L, "network.WebSocket");
  lua_newtable(L);
  luaL_Reg web_socket_functions[] = {
    { "open", &web_socket_open },
    { "close", &web_socket_close },
    { "write", &web_socket_write },
    { NULL, NULL }
  };
  luaL_setfuncs(L, web_socket_functions, 0);
  lua_setfield(L, -2, "__index");
  lua_pushcfunction(L, web_socket_delete);
  lua_setfield(L, -2, "__gc");/*}}}*/

  luaL_Reg network_functions[] = {
    { "TcpClient", &network_tcp_client },
    { "TcpServer", &network_tcp_server },
    { "WebSocket", &network_web_socket },
    { NULL, NULL }
  };
  luaL_newlib(L, network_functions);
  return 1;
}
<|endoftext|>


<commit_before>#ifndef ORG_EEROS_CORE_SYSTEM_HPP_
#define ORG_EEROS_CORE_SYSTEM_HPP_

#include <stdint.h>

namespace eeros {

//	static bool rosTimeIsUsed = false;

	class System {
	public:
		static double getClockResolution();
		static double getTime();
		static uint64_t getTimeNs();

#ifdef USE_ROS
		static void useRosTime();
#endif

	private:
		System();
	};

};

#endif /* ORG_EEROS_CORE_SYSTEM_HPP_ */
<commit_msg>Remove faulty comment when using with ROS<commit_after>#ifndef ORG_EEROS_CORE_SYSTEM_HPP_
#define ORG_EEROS_CORE_SYSTEM_HPP_

#include <stdint.h>

namespace eeros {

	static bool rosTimeIsUsed __attribute__((unused)) = false;

	class System {
	public:
		static double getClockResolution();
		static double getTime();
		static uint64_t getTimeNs();

#ifdef USE_ROS
		static void useRosTime();
#endif

	private:
		System();
	};

};

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


<commit_before>#include <iostream>
#include <cstdio>
#include <algorithm>
#include <iterator>
#include <utility>
#include <deque>
#include <string>
#include <cstdlib>
#include "nfa.hxx"

extern int yyparse (void*);
extern FILE* yyin;

int main(int argc, char* argv[])
{
    /* Osetreni parametru vstupniho souboru */
    if (argc == 2) {
	if (!(yyin = fopen(argv[1],"r"))) {
	    perror("chyba fopen()");
	    exit(EXIT_FAILURE);
	}
    }
    else
	yyin = stdin;

    NFA nfa;
    int ret = yyparse((void*)&nfa);
    if (ret == 1) {
	std::cerr << "chyba pri parsovani vstupu" << std::endl;
	exit(EXIT_FAILURE);
    }
    /* Ladici vypis vstupniho automatu. */
    std::cout << "input:" << std::endl << printNFA(nfa) << std::endl;

    NFA_conv nfa_conv = convert_NFA2DFA(nfa);

    /* Ladici vypis prevedeneho automatu */
    std::cout << "converted:" << std::endl << printNFA(nfa_conv) << std::endl;

    exit(EXIT_SUCCESS);
}
<commit_msg>Osetri pripadne vyjimky. Osetri pripadne vyjimky. Vypis take zkonvetovany opraveny automat.<commit_after>#include <iostream>
#include <cstdio>
#include <algorithm>
#include <iterator>
#include <utility>
#include <deque>
#include <string>
#include <cstdlib>
#include "nfa.hxx"

extern int yyparse (void*);
extern FILE* yyin;

int main(int argc, char* argv[])
{
    /* Osetreni parametru vstupniho souboru */
    if (argc == 2) {
	if (!(yyin = fopen(argv[1],"r"))) {
	    perror("chyba fopen()");
	    exit(EXIT_FAILURE);
	}
    }
    else
	yyin = stdin;

    NFA nfa;
    NFA_conv nfa_conv;
    int ret = yyparse((void*)&nfa);
    if (ret == 1) {
	std::cerr << "chyba pri parsovani vstupu" << std::endl;
	exit(EXIT_FAILURE);
    }
    /* Ladici vypis vstupniho automatu. */
    std::cout << "input:" << std::endl << printNFA(nfa) << std::endl;

    try {
	nfa_conv = convert_NFA2DFA(nfa);
    }
    catch (state_not_found& e) {
	std::cerr << "chyba pri prevodu v convert_NFA2DFA(): "
		  << e.what() << std::endl;
	std::cerr << "zobrazeni delta na neznamy stav" << std::endl;
	exit(EXIT_FAILURE);
    }

    /* Ladici vypis prevedeneho automatu */
    std::cout << "converted:" << std::endl << printNFA(nfa_conv) << std::endl;
    std::cout << "converted fixed:" << std::endl
	      << printNFA(fix_converted(nfa_conv,true)) << std::endl;

    exit(EXIT_SUCCESS);
}
<|endoftext|>


<commit_before>/*
    Copyright 2009 Brain Research Institute, Melbourne, Australia

    Written by Robert E. Smith, 31/07/13.

    This file is part of MRtrix.

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

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

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "image/handler/sparse.h"

namespace MR
{
  namespace Image
  {
    namespace Handler
    {

      Sparse::Sparse (Default& handler, const std::string& sparse_class, const size_t sparse_size, const File::Entry entry) :
          Default (handler),
          class_name (sparse_class),
          class_size (sparse_size),
          file (entry),
          data_end (0) { }

      void Sparse::load()
      {

        Default::load();

        std::fstream stream (file.name.c_str(), std::ios_base::in | std::ios_base::binary);
        stream.seekg (0, std::ios::end);
        const uint64_t file_size = stream.tellg();
        stream.close();
        const uint64_t current_sparse_data_size = file_size - file.start;

        if (current_sparse_data_size) {

          mmap = new File::MMap (file, Base::writable, true, current_sparse_data_size);
          data_end = current_sparse_data_size;

        } else if (Base::writable) {

          // Default = initialise 16MB, this is enough to store whole-brain fixel data at 2.5mm resolution
          const uint64_t init_sparse_data_size = File::Config::get_int ("SparseDataInitialSize", 16777216);
          const size_t new_file_size = file.start + init_sparse_data_size;
          DEBUG ("Initialising output sparse data file " + file.name + ": new file size " + str(new_file_size) + " (" + str(init_sparse_data_size) + " of which is initial sparse data buffer)");
          File::resize (file.name, new_file_size);
          mmap = new File::MMap (file, Base::writable, false, init_sparse_data_size);

          // Writes a single uint32_t(0) to the start of the sparse data region
          // Any voxel that has its value initialised to 0 will point here, and therefore dereferencing of any
          //   such voxel will yield a SParse::Value with zero elements
          uint32_t zero (0);
          memcpy (off2mem(0), &zero, sizeof(uint32_t));

          data_end = sizeof(uint32_t);

        }

      }

      void Sparse::unload()
      {

        Default::unload();

        const uint64_t truncate_file_size = (data_end == size()) ? 0 : file.start + data_end;
        // Null the excess data before closing the memory map to prevent std::ofstream from giving an error
        //   (writing uninitialised values)
        memset (off2mem(data_end), 0x00, size() - data_end);
        mmap = NULL;

        if (truncate_file_size) {
          DEBUG ("truncating sparse image data file " + file.name + " to " + str(truncate_file_size) + " bytes");
          File::resize (file.name, truncate_file_size);
        }

      }

      uint32_t Sparse::get_numel (const uint64_t offset) const
      {
        return *(reinterpret_cast<uint32_t*>(off2mem(offset)));
      }

      uint64_t Sparse::set_numel (const uint64_t old_offset, const uint32_t numel)
      {

        assert (Base::writable);

        // Before allocating new memory, verify that the current offset does not point to
        //   a voxel that has more elements than is required
        if (old_offset) {

          assert (old_offset < data_end);

          const uint32_t existing_numel = get_numel (old_offset);
          if (existing_numel >= numel) {

            // Set the new number of elements, clear the unwanted data, and return
            memcpy (off2mem(old_offset), &numel, sizeof(uint32_t));
            memset (off2mem(old_offset) + sizeof(uint32_t) + (numel * class_size), 0x00, ((existing_numel - numel) * class_size));
            // If this voxel is being cleared (i.e. no elements), rather than returning a pointer to a voxel with
            //   zero elements, instead return a pointer to the start of the sparse data, where there's a single
            //   uint32_t(0) which can be used for any and all voxels with zero elements
            return numel ? old_offset : 0;

          } else {

            // Existing memory allocation for this voxel is not sufficient; erase it
            // Note that the handler makes no attempt at re-using this memory later; new data is just concatenated
            //   to the end of the buffer
            memset (off2mem(old_offset), 0x00, sizeof(uint32_t) + (existing_numel * class_size));

          }
        }

        const int64_t requested_size = sizeof (uint32_t) + (numel * class_size);
        if (data_end + requested_size > size()) {

          // size() should never be empty if data is being written...
          assert (size());
          uint64_t new_sparse_data_size = 2 * size();

          // Cover rare case where a huge memory request occurs early
          while (new_sparse_data_size < data_end + requested_size)
            new_sparse_data_size *= 2;

          // Memory error arises due to the uninitialised data between the end of the sparse data and the end
          //   of the file at its current size being written using std::ofstream
          // Therefore, explicitly null all data that hasn't already been written
          //   (this does not prohibit the use of this memory for subsequent sparse data though)
          memset (off2mem(data_end), 0x00, size() - data_end);

          mmap = NULL;

          const size_t new_file_size = file.start + new_sparse_data_size;
          DEBUG ("Resizing sparse data file " + file.name + ": new file size " + str(new_file_size) + " (" + str(new_sparse_data_size) + " of which is for sparse data)");
          File::resize (file.name, new_file_size);
          mmap = new File::MMap (file, Base::writable, true, new_sparse_data_size);

        }

        // Write the uint32_t indicating the number of elements in this voxel
        memcpy (off2mem(data_end), &numel, sizeof(uint32_t));

        // The return value is the offset from the beginning of the sparse data
        const uint64_t ret = data_end;
        data_end += requested_size;

        return ret;
      }

      uint8_t* const Sparse::get (const uint64_t voxel_offset, const size_t index) const
      {
        assert (index < get_numel (voxel_offset));
        const uint64_t offset = sizeof(uint32_t) + (index * class_size);
        assert (voxel_offset + offset + class_size <= data_end);
        uint8_t* const ptr = off2mem(voxel_offset) + offset;
        return ptr;
      }

    }
  }
}

<commit_msg>Modified sparse image handler to avoid unnecessary memory allocation for empty voxels<commit_after>/*
    Copyright 2009 Brain Research Institute, Melbourne, Australia

    Written by Robert E. Smith, 31/07/13.

    This file is part of MRtrix.

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

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

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "image/handler/sparse.h"

namespace MR
{
  namespace Image
  {
    namespace Handler
    {

      Sparse::Sparse (Default& handler, const std::string& sparse_class, const size_t sparse_size, const File::Entry entry) :
          Default (handler),
          class_name (sparse_class),
          class_size (sparse_size),
          file (entry),
          data_end (0) { }

      void Sparse::load()
      {

        Default::load();

        std::fstream stream (file.name.c_str(), std::ios_base::in | std::ios_base::binary);
        stream.seekg (0, std::ios::end);
        const uint64_t file_size = stream.tellg();
        stream.close();
        const uint64_t current_sparse_data_size = file_size - file.start;

        if (current_sparse_data_size) {

          mmap = new File::MMap (file, Base::writable, true, current_sparse_data_size);
          data_end = current_sparse_data_size;

        } else if (Base::writable) {

          // Default = initialise 16MB, this is enough to store whole-brain fixel data at 2.5mm resolution
          const uint64_t init_sparse_data_size = File::Config::get_int ("SparseDataInitialSize", 16777216);
          const size_t new_file_size = file.start + init_sparse_data_size;
          DEBUG ("Initialising output sparse data file " + file.name + ": new file size " + str(new_file_size) + " (" + str(init_sparse_data_size) + " of which is initial sparse data buffer)");
          File::resize (file.name, new_file_size);
          mmap = new File::MMap (file, Base::writable, false, init_sparse_data_size);

          // Writes a single uint32_t(0) to the start of the sparse data region
          // Any voxel that has its value initialised to 0 will point here, and therefore dereferencing of any
          //   such voxel will yield a SParse::Value with zero elements
          uint32_t zero (0);
          memcpy (off2mem(0), &zero, sizeof(uint32_t));

          data_end = sizeof(uint32_t);

        }

      }

      void Sparse::unload()
      {

        Default::unload();

        const uint64_t truncate_file_size = (data_end == size()) ? 0 : file.start + data_end;
        // Null the excess data before closing the memory map to prevent std::ofstream from giving an error
        //   (writing uninitialised values)
        memset (off2mem(data_end), 0x00, size() - data_end);
        mmap = NULL;

        if (truncate_file_size) {
          DEBUG ("truncating sparse image data file " + file.name + " to " + str(truncate_file_size) + " bytes");
          File::resize (file.name, truncate_file_size);
        }

      }

      uint32_t Sparse::get_numel (const uint64_t offset) const
      {
        return *(reinterpret_cast<uint32_t*>(off2mem(offset)));
      }

      uint64_t Sparse::set_numel (const uint64_t old_offset, const uint32_t numel)
      {

        assert (Base::writable);

        // Before allocating new memory, verify that the current offset does not point to
        //   a voxel that has more elements than is required
        if (old_offset) {

          assert (old_offset < data_end);

          const uint32_t existing_numel = get_numel (old_offset);
          if (existing_numel >= numel) {

            // Set the new number of elements, clear the unwanted data, and return
            memcpy (off2mem(old_offset), &numel, sizeof(uint32_t));
            memset (off2mem(old_offset) + sizeof(uint32_t) + (numel * class_size), 0x00, ((existing_numel - numel) * class_size));
            // If this voxel is being cleared (i.e. no elements), rather than returning a pointer to a voxel with
            //   zero elements, instead return a pointer to the start of the sparse data, where there's a single
            //   uint32_t(0) which can be used for any and all voxels with zero elements
            return numel ? old_offset : 0;

          } else {

            // Existing memory allocation for this voxel is not sufficient; erase it
            // Note that the handler makes no attempt at re-using this memory later; new data is just concatenated
            //   to the end of the buffer
            memset (off2mem(old_offset), 0x00, sizeof(uint32_t) + (existing_numel * class_size));

          }
        }

        // Don't allocate memory for voxels with no sparse data; just point them all to the start of the
        //   sparse data where theres a single uint32_t(0)
        if (!numel)
          return 0;

        const int64_t requested_size = sizeof (uint32_t) + (numel * class_size);
        if (data_end + requested_size > size()) {

          // size() should never be empty if data is being written...
          assert (size());
          uint64_t new_sparse_data_size = 2 * size();

          // Cover rare case where a huge memory request occurs early
          while (new_sparse_data_size < data_end + requested_size)
            new_sparse_data_size *= 2;

          // Memory error arises due to the uninitialised data between the end of the sparse data and the end
          //   of the file at its current size being written using std::ofstream
          // Therefore, explicitly null all data that hasn't already been written
          //   (this does not prohibit the use of this memory for subsequent sparse data though)
          memset (off2mem(data_end), 0x00, size() - data_end);

          mmap = NULL;

          const size_t new_file_size = file.start + new_sparse_data_size;
          DEBUG ("Resizing sparse data file " + file.name + ": new file size " + str(new_file_size) + " (" + str(new_sparse_data_size) + " of which is for sparse data)");
          File::resize (file.name, new_file_size);
          mmap = new File::MMap (file, Base::writable, true, new_sparse_data_size);

        }

        // Write the uint32_t indicating the number of elements in this voxel
        memcpy (off2mem(data_end), &numel, sizeof(uint32_t));

        // The return value is the offset from the beginning of the sparse data
        const uint64_t ret = data_end;
        data_end += requested_size;

        return ret;
      }

      uint8_t* const Sparse::get (const uint64_t voxel_offset, const size_t index) const
      {
        assert (index < get_numel (voxel_offset));
        const uint64_t offset = sizeof(uint32_t) + (index * class_size);
        assert (voxel_offset + offset + class_size <= data_end);
        uint8_t* const ptr = off2mem(voxel_offset) + offset;
        return ptr;
      }

    }
  }
}

<|endoftext|>