<commit_before>// Copyright (c) Steinwurf ApS 2016.
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#pragma once

#include <cstdint>
#include <string>
#include <type_traits>
#include <ostream>

#include "class_type.hpp"
#include "backing_data.hpp"
#include "json_const_wrapper.hpp"
#include "json_wrapper.hpp"

namespace bourne
{
class json
{
private:

    template<class T, class R = void>
    using check_is_bool = std::enable_if<std::is_same<T, bool>::value, R>;

    template<class T, class R = void>
    using check_is_integral = std::enable_if<
                              std::is_integral<T>::value && !std::is_same<T, bool>::value, R>;

    template<class T, class R = void>
    using check_is_floating_point = std::enable_if<
                                    std::is_floating_point<T>::value, R>;

    template<class T, class R = void>
    using check_is_string = std::enable_if<
                            std::is_convertible<T, std::string>::value, R>;

private:

    using object_type = backing_data::object_type;

    using array_type = backing_data::array_type;

public:

    ////////////////////
    /// Constructors ///
    ////////////////////

    /// Default constructor, creates a null value.
    json();

    /// Creates an empty json value of the given type
    json(class_type type);

    /// Creates a json object.
    /// Odd indexed items in the list will serve as keys for their even counter
    /// part.
    /// Example:
    /// json({"key1", "value1", "key2", "value2"})
    /// will create the following json value:
    /// {
    ///   "key1": "value1",
    ///   "key2": "value2"
    /// }
    json(std::initializer_list<json> list);

    /// Move constructor.
    /// Ensures the backing_data is owned my the correct object.
    json(json&& other);

    /// Copy constructor.
    json(const json& other);

    /// Constructor for creating a boolean value.
    template <typename T>
    json(T b, typename check_is_bool<T>::type* = 0) :
        m_internal(b),
        m_type(class_type::boolean)
    {}

    /// Constructor for creating an integral value.
    template <typename T>
    json(T i, typename check_is_integral<T>::type* = 0) :
        m_internal((int64_t)i),
        m_type(class_type::integral)
    {}

    /// Constructor for creating a floating point value.
    template <typename T>
    json(T f, typename check_is_floating_point<T>::type* = 0) :
        m_internal((double)f),
        m_type(class_type::floating)
    {}

    /// Constructor for creating a string value.
    template <typename T>
    json(T s, typename check_is_string<T>::type* = 0) :
        m_internal(std::string(s)),
        m_type(class_type::string)
    {}

    /// Constructor for creating a null value.
    json(std::nullptr_t);

    /// Destructor
    ~json();

    /////////////////////////////////////
    /// Assignment operator functions ///
    /////////////////////////////////////

    /// Assignment operator for json
    json& operator=(json&& other);

    /// Assignment operator for json
    json& operator=(const json& other);

    /// Assignment operator for boolean
    template <typename T>
    typename check_is_bool<T, json&>::type operator=(T b)
    {
        set_type(class_type::boolean);
        m_internal.m_bool = b;
        return *this;
    }

    /// Assignment operator for integral
    template <typename T>
    typename check_is_integral<T, json&>::type operator=(T i)
    {
        set_type(class_type::integral);
        m_internal.m_int = i;
        return *this;
    }

    /// Assignment operator for floating point
    template <typename T>
    typename check_is_floating_point<T, json&>::type operator=(T f)
    {
        set_type(class_type::floating);
        m_internal.m_float = f;
        return *this;
    }

    /// Assignment operator for string value
    template <typename T>
    typename check_is_string<T, json&>::type operator=(T s)
    {
        set_type(class_type::string);

        // use assignment operator to copy over the string
        *m_internal.m_string = std::string(s);
        return *this;
    }

    /// Assignment operator for null value
    json& operator=(std::nullptr_t);

    ////////////////////////
    /// Access operators ///
    ////////////////////////

    /// Access operator for keys this assumes the json value is of type object
    json& operator[](const std::string& key);

    /// Access operator for index this assumes the json value is of type array
    json& operator[](uint32_t index);

    /// Returns a reference to the json value of the element identified with the
    /// given key. If this
    json& at(const std::string& key);
    const json& at(const std::string& key) const;

    json& at(uint32_t index);
    const json& at(uint32_t index) const;

    /// Append a json value to this json array. If this object is not a json
    /// array, an assert will be triggered.
    template <typename T>
    void append(T arg)
    {
        assert(is_array());
        m_internal.m_array->emplace_back(arg);
    }

    /// Append multiple json values to this json array. If this object is not a
    /// json array, an assert will be triggered.
    template <typename T, typename... U>
    void append(T arg, U... args)
    {
        assert(is_array());
        append(arg);
        append(args...);
    }

    /// Returns true if the key is available. This functions assumes this object
    /// is a json object value.
    bool has_key(const std::string& key) const;

    /// Returns the number of elements in this object or array. If this is not
    /// an object or array, an assert will be triggered.
    uint32_t size() const;

    /// Returns the type of this object.
    class_type json_type() const;

    template <class T>
    bool is() const
    {
        if (std::is_same<T, bool>::value)
        {
            return m_type == class_type::boolean;
        }
        else if (std::is_integral<T>::value)
        {
            return m_type == class_type::integral;
        }
        else if (std::is_floating_point<T>::value)
        {
            return m_type == class_type::floating;
        }
        else if (std::is_convertible<T, std::string>::value)
        {
            return m_type == class_type::string;
        }
        return false;
    }

    /// Returns true if this object is a null value
    bool is_null() const;

    /// Returns true if this object is a boolean value
    bool is_bool() const;

    /// Returns true if this object is a integer value
    bool is_int() const;

    /// Returns true if this object is a floating point value
    bool is_float() const;

    /// Returns true if this object is a string value
    bool is_string() const;

    /// Returns true if this object is a object value
    bool is_object() const;

    /// Returns true if this object is a array value
    bool is_array() const;

    /// Converter for extracting the boolean value.
    template <typename T>
    void to(T& t, typename check_is_bool<T>::type* = 0) const
    {
        t = to_bool();
    }

    /// Converter for extracting the integral value.
    template <typename T>
    void to(T& t, typename check_is_integral<T>::type* = 0) const
    {
        t = to_int();
    }

    /// Converter for extracting the floating point value.
    template <typename T>
    void to(T& t, typename check_is_floating_point<T>::type* = 0) const
    {
        t = to_float();
    }

    /// Converter for extracting the string value.
    template <typename T>
    void to(T& t, typename check_is_string<T>::type* = 0) const
    {
        t = to_string();
    }

    /// Returns the underlying boolean value of this object. If this is not a
    /// boolean value an assert is triggered.
    bool to_bool() const;

    /// Returns the underlying integer value of this object. If this is not a
    /// interger value an assert is triggered.
    int64_t to_int() const;

    /// Returns the underlying floating point value of this object. If this is
    /// not a floating point value an assert is triggered.
    double to_float() const;

    /// Returns the underlying string value of this object. If this is not a
    /// string value an assert is triggered.
    std::string to_string() const;

    /// Returns an iterable object range. If this is not an object value an
    /// assert is triggered.
    json_wrapper<object_type> object_range();

    /// Returns an const iterable object range. If this is not an object value
    /// an assert is triggered.
    json_const_wrapper<object_type> object_range() const;

    /// Returns an iterable array range. If this is not an array value an
    /// assert is triggered.
    json_wrapper<array_type> array_range();

    /// Returns an const iterable array range. If this is not an array value
    /// an assert is triggered.
    json_const_wrapper<array_type> array_range() const;

    /// Dumps this object as a json string.
    std::string dump(uint32_t depth = 1, std::string tab = "  ") const;

    /// Friend function for the insertion operator. This will insert the json
    /// string of this object to the ostream.
    friend std::ostream& operator<<(std::ostream&, const json&);

    ////////////////////////////
    /// Comparison operators ///
    ////////////////////////////

    /// Equality operator, this compares if the content of two json objects are
    /// the same.
    bool operator==(const json& other) const;

    /// Inequality operator, negated equality operator.
    bool operator!=(const json& other) const;

    ////////////////////////
    /// Static Functions ///
    ////////////////////////

    /// Parse a string as a json object.
    static json parse(const std::string& string);

    /// Create a json array
    static json array();
    template <typename... T>
    static json array(T... args)
    {
        json array = json(class_type::array);
        array.append(args...);
        return array;
    }

    /// Create an empty json object
    static json object();

    /// Create a json object
    static json object(std::initializer_list<json> list);

private:

    /// Clears this object - deletes the backing data and sets the type to null
    void clear();

    /// Updates the type of this object, and initializes the backing data based
    /// on this.
    void set_type(class_type type);

private:

    /// The object containing the underlying data
    backing_data m_internal;

    /// The type of this object
    class_type m_type = class_type::null;
};

std::ostream& operator<<(std::ostream& os, const json& json);
}
<commit_msg>added doc<commit_after>// Copyright (c) Steinwurf ApS 2016.
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#pragma once

#include <cstdint>
#include <string>
#include <type_traits>
#include <ostream>

#include "class_type.hpp"
#include "backing_data.hpp"
#include "json_const_wrapper.hpp"
#include "json_wrapper.hpp"

namespace bourne
{
class json
{
private:

    template<class T, class R = void>
    using check_is_bool = std::enable_if<std::is_same<T, bool>::value, R>;

    template<class T, class R = void>
    using check_is_integral = std::enable_if<
                              std::is_integral<T>::value && !std::is_same<T, bool>::value, R>;

    template<class T, class R = void>
    using check_is_floating_point = std::enable_if<
                                    std::is_floating_point<T>::value, R>;

    template<class T, class R = void>
    using check_is_string = std::enable_if<
                            std::is_convertible<T, std::string>::value, R>;

private:

    using object_type = backing_data::object_type;

    using array_type = backing_data::array_type;

public:

    ////////////////////
    /// Constructors ///
    ////////////////////

    /// Default constructor, creates a null value.
    json();

    /// Creates an empty json value of the given type
    json(class_type type);

    /// Creates a json object.
    /// Odd indexed items in the list will serve as keys for their even counter
    /// part.
    /// Example:
    /// json({"key1", "value1", "key2", "value2"})
    /// will create the following json value:
    /// {
    ///   "key1": "value1",
    ///   "key2": "value2"
    /// }
    json(std::initializer_list<json> list);

    /// Move constructor.
    /// Ensures the backing_data is owned my the correct object.
    json(json&& other);

    /// Copy constructor.
    json(const json& other);

    /// Constructor for creating a boolean value.
    template <typename T>
    json(T b, typename check_is_bool<T>::type* = 0) :
        m_internal(b),
        m_type(class_type::boolean)
    {}

    /// Constructor for creating an integral value.
    template <typename T>
    json(T i, typename check_is_integral<T>::type* = 0) :
        m_internal((int64_t)i),
        m_type(class_type::integral)
    {}

    /// Constructor for creating a floating point value.
    template <typename T>
    json(T f, typename check_is_floating_point<T>::type* = 0) :
        m_internal((double)f),
        m_type(class_type::floating)
    {}

    /// Constructor for creating a string value.
    template <typename T>
    json(T s, typename check_is_string<T>::type* = 0) :
        m_internal(std::string(s)),
        m_type(class_type::string)
    {}

    /// Constructor for creating a null value.
    json(std::nullptr_t);

    /// Destructor
    ~json();

    /////////////////////////////////////
    /// Assignment operator functions ///
    /////////////////////////////////////

    /// Assignment operator for json
    json& operator=(json&& other);

    /// Assignment operator for json
    json& operator=(const json& other);

    /// Assignment operator for boolean
    template <typename T>
    typename check_is_bool<T, json&>::type operator=(T b)
    {
        set_type(class_type::boolean);
        m_internal.m_bool = b;
        return *this;
    }

    /// Assignment operator for integral
    template <typename T>
    typename check_is_integral<T, json&>::type operator=(T i)
    {
        set_type(class_type::integral);
        m_internal.m_int = i;
        return *this;
    }

    /// Assignment operator for floating point
    template <typename T>
    typename check_is_floating_point<T, json&>::type operator=(T f)
    {
        set_type(class_type::floating);
        m_internal.m_float = f;
        return *this;
    }

    /// Assignment operator for string value
    template <typename T>
    typename check_is_string<T, json&>::type operator=(T s)
    {
        set_type(class_type::string);

        // use assignment operator to copy over the string
        *m_internal.m_string = std::string(s);
        return *this;
    }

    /// Assignment operator for null value
    json& operator=(std::nullptr_t);

    ////////////////////////
    /// Access operators ///
    ////////////////////////

    /// Access operator for keys this assumes the json value is of type object
    json& operator[](const std::string& key);

    /// Access operator for index this assumes the json value is of type array
    json& operator[](uint32_t index);

    /// Returns a reference to the json value of the element identified with the
    /// given key. If this
    json& at(const std::string& key);
    const json& at(const std::string& key) const;

    json& at(uint32_t index);
    const json& at(uint32_t index) const;

    /// Append a json value to this json array. If this object is not a json
    /// array, an assert will be triggered.
    template <typename T>
    void append(T arg)
    {
        assert(is_array());
        m_internal.m_array->emplace_back(arg);
    }

    /// Append multiple json values to this json array. If this object is not a
    /// json array, an assert will be triggered.
    template <typename T, typename... U>
    void append(T arg, U... args)
    {
        assert(is_array());
        append(arg);
        append(args...);
    }

    /// Returns true if the key is available. This functions assumes this object
    /// is a json object value.
    bool has_key(const std::string& key) const;

    /// Returns the number of elements in this object or array. If this is not
    /// an object or array, an assert will be triggered.
    uint32_t size() const;

    /// Returns the type of this object.
    class_type json_type() const;

    /// Returns true if this object matches the given type
    template <class T>
    bool is() const
    {
        if (std::is_same<T, bool>::value)
        {
            return m_type == class_type::boolean;
        }
        else if (std::is_integral<T>::value)
        {
            return m_type == class_type::integral;
        }
        else if (std::is_floating_point<T>::value)
        {
            return m_type == class_type::floating;
        }
        else if (std::is_convertible<T, std::string>::value)
        {
            return m_type == class_type::string;
        }
        return false;
    }

    /// Returns true if this object is a null value
    bool is_null() const;

    /// Returns true if this object is a boolean value
    bool is_bool() const;

    /// Returns true if this object is a integer value
    bool is_int() const;

    /// Returns true if this object is a floating point value
    bool is_float() const;

    /// Returns true if this object is a string value
    bool is_string() const;

    /// Returns true if this object is a object value
    bool is_object() const;

    /// Returns true if this object is a array value
    bool is_array() const;

    /// Converter for extracting the boolean value.
    template <typename T>
    void to(T& t, typename check_is_bool<T>::type* = 0) const
    {
        t = to_bool();
    }

    /// Converter for extracting the integral value.
    template <typename T>
    void to(T& t, typename check_is_integral<T>::type* = 0) const
    {
        t = to_int();
    }

    /// Converter for extracting the floating point value.
    template <typename T>
    void to(T& t, typename check_is_floating_point<T>::type* = 0) const
    {
        t = to_float();
    }

    /// Converter for extracting the string value.
    template <typename T>
    void to(T& t, typename check_is_string<T>::type* = 0) const
    {
        t = to_string();
    }

    /// Returns the underlying boolean value of this object. If this is not a
    /// boolean value an assert is triggered.
    bool to_bool() const;

    /// Returns the underlying integer value of this object. If this is not a
    /// interger value an assert is triggered.
    int64_t to_int() const;

    /// Returns the underlying floating point value of this object. If this is
    /// not a floating point value an assert is triggered.
    double to_float() const;

    /// Returns the underlying string value of this object. If this is not a
    /// string value an assert is triggered.
    std::string to_string() const;

    /// Returns an iterable object range. If this is not an object value an
    /// assert is triggered.
    json_wrapper<object_type> object_range();

    /// Returns an const iterable object range. If this is not an object value
    /// an assert is triggered.
    json_const_wrapper<object_type> object_range() const;

    /// Returns an iterable array range. If this is not an array value an
    /// assert is triggered.
    json_wrapper<array_type> array_range();

    /// Returns an const iterable array range. If this is not an array value
    /// an assert is triggered.
    json_const_wrapper<array_type> array_range() const;

    /// Dumps this object as a json string.
    std::string dump(uint32_t depth = 1, std::string tab = "  ") const;

    /// Friend function for the insertion operator. This will insert the json
    /// string of this object to the ostream.
    friend std::ostream& operator<<(std::ostream&, const json&);

    ////////////////////////////
    /// Comparison operators ///
    ////////////////////////////

    /// Equality operator, this compares if the content of two json objects are
    /// the same.
    bool operator==(const json& other) const;

    /// Inequality operator, negated equality operator.
    bool operator!=(const json& other) const;

    ////////////////////////
    /// Static Functions ///
    ////////////////////////

    /// Parse a string as a json object.
    static json parse(const std::string& string);

    /// Create a json array
    static json array();
    template <typename... T>
    static json array(T... args)
    {
        json array = json(class_type::array);
        array.append(args...);
        return array;
    }

    /// Create an empty json object
    static json object();

    /// Create a json object
    static json object(std::initializer_list<json> list);

private:

    /// Clears this object - deletes the backing data and sets the type to null
    void clear();

    /// Updates the type of this object, and initializes the backing data based
    /// on this.
    void set_type(class_type type);

private:

    /// The object containing the underlying data
    backing_data m_internal;

    /// The type of this object
    class_type m_type = class_type::null;
};

std::ostream& operator<<(std::ostream& os, const json& json);
}
<|endoftext|>


<commit_before>#include "opencv2/videoio/videoio.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

using namespace cv;
using namespace std;

static void help()
{
        cout << "\nThis program demonstrates usage of depth sensors (Kinect, XtionPRO,...).\n"
                        "The user gets some of the supported output images.\n"
            "\nAll supported output map types:\n"
            "1.) Data given from depth generator\n"
            "   CV_CAP_OPENNI_DEPTH_MAP            - depth values in mm (CV_16UC1)\n"
            "   CV_CAP_OPENNI_POINT_CLOUD_MAP      - XYZ in meters (CV_32FC3)\n"
            "   CV_CAP_OPENNI_DISPARITY_MAP        - disparity in pixels (CV_8UC1)\n"
            "   CV_CAP_OPENNI_DISPARITY_MAP_32F    - disparity in pixels (CV_32FC1)\n"
            "   CV_CAP_OPENNI_VALID_DEPTH_MASK     - mask of valid pixels (not ocluded, not shaded etc.) (CV_8UC1)\n"
            "2.) Data given from RGB image generator\n"
            "   CV_CAP_OPENNI_BGR_IMAGE            - color image (CV_8UC3)\n"
            "   CV_CAP_OPENNI_GRAY_IMAGE           - gray image (CV_8UC1)\n"
         << endl;
}

static void colorizeDisparity( const Mat& gray, Mat& rgb, double maxDisp=-1.f, float S=1.f, float V=1.f )
{
    CV_Assert( !gray.empty() );
    CV_Assert( gray.type() == CV_8UC1 );

    if( maxDisp <= 0 )
    {
        maxDisp = 0;
        minMaxLoc( gray, 0, &maxDisp );
    }

    rgb.create( gray.size(), CV_8UC3 );
    rgb = Scalar::all(0);
    if( maxDisp < 1 )
        return;

    for( int y = 0; y < gray.rows; y++ )
    {
        for( int x = 0; x < gray.cols; x++ )
        {
            uchar d = gray.at<uchar>(y,x);
            unsigned int H = ((uchar)maxDisp - d) * 240 / (uchar)maxDisp;

            unsigned int hi = (H/60) % 6;
            float f = H/60.f - H/60;
            float p = V * (1 - S);
            float q = V * (1 - f * S);
            float t = V * (1 - (1 - f) * S);

            Point3f res;

            if( hi == 0 ) //R = V,  G = t,  B = p
                res = Point3f( p, t, V );
            if( hi == 1 ) // R = q, G = V,  B = p
                res = Point3f( p, V, q );
            if( hi == 2 ) // R = p, G = V,  B = t
                res = Point3f( t, V, p );
            if( hi == 3 ) // R = p, G = q,  B = V
                res = Point3f( V, q, p );
            if( hi == 4 ) // R = t, G = p,  B = V
                res = Point3f( V, p, t );
            if( hi == 5 ) // R = V, G = p,  B = q
                res = Point3f( q, p, V );

            uchar b = (uchar)(std::max(0.f, std::min (res.x, 1.f)) * 255.f);
            uchar g = (uchar)(std::max(0.f, std::min (res.y, 1.f)) * 255.f);
            uchar r = (uchar)(std::max(0.f, std::min (res.z, 1.f)) * 255.f);

            rgb.at<Point3_<uchar> >(y,x) = Point3_<uchar>(b, g, r);
        }
    }
}

static float getMaxDisparity( VideoCapture& capture )
{
    const int minDistance = 400; // mm
    float b = (float)capture.get( CAP_OPENNI_DEPTH_GENERATOR_BASELINE ); // mm
    float F = (float)capture.get( CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH ); // pixels
    return b * F / minDistance;
}

static void printCommandLineParams()
{
    cout << "-cd       Colorized disparity? (0 or 1; 1 by default) Ignored if disparity map is not selected to show." << endl;
    cout << "-fmd      Fixed max disparity? (0 or 1; 0 by default) Ignored if disparity map is not colorized (-cd 0)." << endl;
    cout << "-mode     image mode: resolution and fps, supported three values:  0 - CV_CAP_OPENNI_VGA_30HZ, 1 - CV_CAP_OPENNI_SXGA_15HZ," << endl;
    cout << "          2 - CV_CAP_OPENNI_SXGA_30HZ (0 by default). Ignored if rgb image or gray image are not selected to show." << endl;
    cout << "-m        Mask to set which output images are need. It is a string of size 5. Each element of this is '0' or '1' and" << endl;
    cout << "          determine: is depth map, disparity map, valid pixels mask, rgb image, gray image need or not (correspondently)?" << endl ;
    cout << "          By default -m 01010 i.e. disparity map and rgb image will be shown." << endl ;
    cout << "-r        Filename of .oni video file. The data will grabbed from it." << endl ;
}

static void parseCommandLine( int argc, char* argv[], bool& isColorizeDisp, bool& isFixedMaxDisp, int& imageMode, bool retrievedImageFlags[],
                       string& filename, bool& isFileReading )
{
    // set defaut values
    isColorizeDisp = true;
    isFixedMaxDisp = false;
    imageMode = 0;

    retrievedImageFlags[0] = false;
    retrievedImageFlags[1] = true;
    retrievedImageFlags[2] = false;
    retrievedImageFlags[3] = true;
    retrievedImageFlags[4] = false;

    filename.clear();
    isFileReading = false;

    if( argc == 1 )
    {
        help();
    }
    else
    {
        for( int i = 1; i < argc; i++ )
        {
            if( !strcmp( argv[i], "--help" ) || !strcmp( argv[i], "-h" ) )
            {
                printCommandLineParams();
                exit(0);
            }
            else if( !strcmp( argv[i], "-cd" ) )
            {
                isColorizeDisp = atoi(argv[++i]) == 0 ? false : true;
            }
            else if( !strcmp( argv[i], "-fmd" ) )
            {
                isFixedMaxDisp = atoi(argv[++i]) == 0 ? false : true;
            }
            else if( !strcmp( argv[i], "-mode" ) )
            {
                imageMode = atoi(argv[++i]);
            }
            else if( !strcmp( argv[i], "-m" ) )
            {
                string mask( argv[++i] );
                if( mask.size() != 5)
                    CV_Error( Error::StsBadArg, "Incorrect length of -m argument string" );
                int val = atoi(mask.c_str());

                int l = 100000, r = 10000, sum = 0;
                for( int j = 0; j < 5; j++ )
                {
                    retrievedImageFlags[j] = ((val % l) / r ) == 0 ? false : true;
                    l /= 10; r /= 10;
                    if( retrievedImageFlags[j] ) sum++;
                }

                if( sum == 0 )
                {
                    cout << "No one output image is selected." << endl;
                    exit(0);
                }
            }
            else if( !strcmp( argv[i], "-r" ) )
            {
                filename = argv[++i];
                isFileReading = true;
            }
            else
            {
                cout << "Unsupported command line argument: " << argv[i] << "." << endl;
                exit(-1);
            }
        }
    }
}

/*
 * To work with Kinect or XtionPRO the user must install OpenNI library and PrimeSensorModule for OpenNI and
 * configure OpenCV with WITH_OPENNI flag is ON (using CMake).
 */
int main( int argc, char* argv[] )
{
    bool isColorizeDisp, isFixedMaxDisp;
    int imageMode;
    bool retrievedImageFlags[5];
    string filename;
    bool isVideoReading;
    parseCommandLine( argc, argv, isColorizeDisp, isFixedMaxDisp, imageMode, retrievedImageFlags, filename, isVideoReading );

    cout << "Device opening ..." << endl;
    VideoCapture capture;
    if( isVideoReading )
        capture.open( filename );
    else
        capture.open( CAP_OPENNI );

    cout << "done." << endl;

    if( !capture.isOpened() )
    {
        cout << "Can not open a capture object." << endl;
        return -1;
    }

    if( !isVideoReading )
    {
        bool modeRes=false;
        switch ( imageMode )
        {
            case 0:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_VGA_30HZ );
                break;
            case 1:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_SXGA_15HZ );
                break;
            case 2:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_SXGA_30HZ );
                break;
                //The following modes are only supported by the Xtion Pro Live
            case 3:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_QVGA_30HZ );
                break;
            case 4:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_QVGA_60HZ );
                break;
            default:
                CV_Error( Error::StsBadArg, "Unsupported image mode property.\n");
        }
        if (!modeRes)
            cout << "\nThis image mode is not supported by the device, the default value (CV_CAP_OPENNI_SXGA_15HZ) will be used.\n" << endl;
    }

    // Print some avalible device settings.
    cout << "\nDepth generator output mode:" << endl <<
            "FRAME_WIDTH      " << capture.get( CAP_PROP_FRAME_WIDTH ) << endl <<
            "FRAME_HEIGHT     " << capture.get( CAP_PROP_FRAME_HEIGHT ) << endl <<
            "FRAME_MAX_DEPTH  " << capture.get( CAP_PROP_OPENNI_FRAME_MAX_DEPTH ) << " mm" << endl <<
            "FPS              " << capture.get( CAP_PROP_FPS ) << endl <<
            "REGISTRATION     " << capture.get( CAP_PROP_OPENNI_REGISTRATION ) << endl;
    if( capture.get( CAP_OPENNI_IMAGE_GENERATOR_PRESENT ) )
    {
        cout <<
            "\nImage generator output mode:" << endl <<
            "FRAME_WIDTH   " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FRAME_WIDTH ) << endl <<
            "FRAME_HEIGHT  " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FRAME_HEIGHT ) << endl <<
            "FPS           " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FPS ) << endl;
    }
    else
    {
        cout << "\nDevice doesn't contain image generator." << endl;
        if (!retrievedImageFlags[0] && !retrievedImageFlags[1] && !retrievedImageFlags[2])
            return 0;
    }

    for(;;)
    {
        Mat depthMap;
        Mat validDepthMap;
        Mat disparityMap;
        Mat bgrImage;
        Mat grayImage;

        if( !capture.grab() )
        {
            cout << "Can not grab images." << endl;
            return -1;
        }
        else
        {
            if( retrievedImageFlags[0] && capture.retrieve( depthMap, CAP_OPENNI_DEPTH_MAP ) )
            {
                const float scaleFactor = 0.05f;
                Mat show; depthMap.convertTo( show, CV_8UC1, scaleFactor );
                imshow( "depth map", show );
            }

            if( retrievedImageFlags[1] && capture.retrieve( disparityMap, CAP_OPENNI_DISPARITY_MAP ) )
            {
                if( isColorizeDisp )
                {
                    Mat colorDisparityMap;
                    colorizeDisparity( disparityMap, colorDisparityMap, isFixedMaxDisp ? getMaxDisparity(capture) : -1 );
                    Mat validColorDisparityMap;
                    colorDisparityMap.copyTo( validColorDisparityMap, disparityMap != 0 );
                    imshow( "colorized disparity map", validColorDisparityMap );
                }
                else
                {
                    imshow( "original disparity map", disparityMap );
                }
            }

            if( retrievedImageFlags[2] && capture.retrieve( validDepthMap, CAP_OPENNI_VALID_DEPTH_MASK ) )
                imshow( "valid depth mask", validDepthMap );

            if( retrievedImageFlags[3] && capture.retrieve( bgrImage, CAP_OPENNI_BGR_IMAGE ) )
                imshow( "rgb image", bgrImage );

            if( retrievedImageFlags[4] && capture.retrieve( grayImage, CAP_OPENNI_GRAY_IMAGE ) )
                imshow( "gray image", grayImage );
        }

        if( waitKey( 30 ) >= 0 )
            break;
    }

    return 0;
}
<commit_msg>openni_capture sample: enable OpenNI2 if available<commit_after>#include "opencv2/videoio/videoio.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

using namespace cv;
using namespace std;

static void help()
{
        cout << "\nThis program demonstrates usage of depth sensors (Kinect, XtionPRO,...).\n"
                        "The user gets some of the supported output images.\n"
            "\nAll supported output map types:\n"
            "1.) Data given from depth generator\n"
            "   CV_CAP_OPENNI_DEPTH_MAP            - depth values in mm (CV_16UC1)\n"
            "   CV_CAP_OPENNI_POINT_CLOUD_MAP      - XYZ in meters (CV_32FC3)\n"
            "   CV_CAP_OPENNI_DISPARITY_MAP        - disparity in pixels (CV_8UC1)\n"
            "   CV_CAP_OPENNI_DISPARITY_MAP_32F    - disparity in pixels (CV_32FC1)\n"
            "   CV_CAP_OPENNI_VALID_DEPTH_MASK     - mask of valid pixels (not ocluded, not shaded etc.) (CV_8UC1)\n"
            "2.) Data given from RGB image generator\n"
            "   CV_CAP_OPENNI_BGR_IMAGE            - color image (CV_8UC3)\n"
            "   CV_CAP_OPENNI_GRAY_IMAGE           - gray image (CV_8UC1)\n"
         << endl;
}

static void colorizeDisparity( const Mat& gray, Mat& rgb, double maxDisp=-1.f, float S=1.f, float V=1.f )
{
    CV_Assert( !gray.empty() );
    CV_Assert( gray.type() == CV_8UC1 );

    if( maxDisp <= 0 )
    {
        maxDisp = 0;
        minMaxLoc( gray, 0, &maxDisp );
    }

    rgb.create( gray.size(), CV_8UC3 );
    rgb = Scalar::all(0);
    if( maxDisp < 1 )
        return;

    for( int y = 0; y < gray.rows; y++ )
    {
        for( int x = 0; x < gray.cols; x++ )
        {
            uchar d = gray.at<uchar>(y,x);
            unsigned int H = ((uchar)maxDisp - d) * 240 / (uchar)maxDisp;

            unsigned int hi = (H/60) % 6;
            float f = H/60.f - H/60;
            float p = V * (1 - S);
            float q = V * (1 - f * S);
            float t = V * (1 - (1 - f) * S);

            Point3f res;

            if( hi == 0 ) //R = V,  G = t,  B = p
                res = Point3f( p, t, V );
            if( hi == 1 ) // R = q, G = V,  B = p
                res = Point3f( p, V, q );
            if( hi == 2 ) // R = p, G = V,  B = t
                res = Point3f( t, V, p );
            if( hi == 3 ) // R = p, G = q,  B = V
                res = Point3f( V, q, p );
            if( hi == 4 ) // R = t, G = p,  B = V
                res = Point3f( V, p, t );
            if( hi == 5 ) // R = V, G = p,  B = q
                res = Point3f( q, p, V );

            uchar b = (uchar)(std::max(0.f, std::min (res.x, 1.f)) * 255.f);
            uchar g = (uchar)(std::max(0.f, std::min (res.y, 1.f)) * 255.f);
            uchar r = (uchar)(std::max(0.f, std::min (res.z, 1.f)) * 255.f);

            rgb.at<Point3_<uchar> >(y,x) = Point3_<uchar>(b, g, r);
        }
    }
}

static float getMaxDisparity( VideoCapture& capture )
{
    const int minDistance = 400; // mm
    float b = (float)capture.get( CAP_OPENNI_DEPTH_GENERATOR_BASELINE ); // mm
    float F = (float)capture.get( CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH ); // pixels
    return b * F / minDistance;
}

static void printCommandLineParams()
{
    cout << "-cd       Colorized disparity? (0 or 1; 1 by default) Ignored if disparity map is not selected to show." << endl;
    cout << "-fmd      Fixed max disparity? (0 or 1; 0 by default) Ignored if disparity map is not colorized (-cd 0)." << endl;
    cout << "-mode     image mode: resolution and fps, supported three values:  0 - CV_CAP_OPENNI_VGA_30HZ, 1 - CV_CAP_OPENNI_SXGA_15HZ," << endl;
    cout << "          2 - CV_CAP_OPENNI_SXGA_30HZ (0 by default). Ignored if rgb image or gray image are not selected to show." << endl;
    cout << "-m        Mask to set which output images are need. It is a string of size 5. Each element of this is '0' or '1' and" << endl;
    cout << "          determine: is depth map, disparity map, valid pixels mask, rgb image, gray image need or not (correspondently)?" << endl ;
    cout << "          By default -m 01010 i.e. disparity map and rgb image will be shown." << endl ;
    cout << "-r        Filename of .oni video file. The data will grabbed from it." << endl ;
}

static void parseCommandLine( int argc, char* argv[], bool& isColorizeDisp, bool& isFixedMaxDisp, int& imageMode, bool retrievedImageFlags[],
                       string& filename, bool& isFileReading )
{
    // set defaut values
    isColorizeDisp = true;
    isFixedMaxDisp = false;
    imageMode = 0;

    retrievedImageFlags[0] = false;
    retrievedImageFlags[1] = true;
    retrievedImageFlags[2] = false;
    retrievedImageFlags[3] = true;
    retrievedImageFlags[4] = false;

    filename.clear();
    isFileReading = false;

    if( argc == 1 )
    {
        help();
    }
    else
    {
        for( int i = 1; i < argc; i++ )
        {
            if( !strcmp( argv[i], "--help" ) || !strcmp( argv[i], "-h" ) )
            {
                printCommandLineParams();
                exit(0);
            }
            else if( !strcmp( argv[i], "-cd" ) )
            {
                isColorizeDisp = atoi(argv[++i]) == 0 ? false : true;
            }
            else if( !strcmp( argv[i], "-fmd" ) )
            {
                isFixedMaxDisp = atoi(argv[++i]) == 0 ? false : true;
            }
            else if( !strcmp( argv[i], "-mode" ) )
            {
                imageMode = atoi(argv[++i]);
            }
            else if( !strcmp( argv[i], "-m" ) )
            {
                string mask( argv[++i] );
                if( mask.size() != 5)
                    CV_Error( Error::StsBadArg, "Incorrect length of -m argument string" );
                int val = atoi(mask.c_str());

                int l = 100000, r = 10000, sum = 0;
                for( int j = 0; j < 5; j++ )
                {
                    retrievedImageFlags[j] = ((val % l) / r ) == 0 ? false : true;
                    l /= 10; r /= 10;
                    if( retrievedImageFlags[j] ) sum++;
                }

                if( sum == 0 )
                {
                    cout << "No one output image is selected." << endl;
                    exit(0);
                }
            }
            else if( !strcmp( argv[i], "-r" ) )
            {
                filename = argv[++i];
                isFileReading = true;
            }
            else
            {
                cout << "Unsupported command line argument: " << argv[i] << "." << endl;
                exit(-1);
            }
        }
    }
}

/*
 * To work with Kinect or XtionPRO the user must install OpenNI library and PrimeSensorModule for OpenNI and
 * configure OpenCV with WITH_OPENNI flag is ON (using CMake).
 */
int main( int argc, char* argv[] )
{
    bool isColorizeDisp, isFixedMaxDisp;
    int imageMode;
    bool retrievedImageFlags[5];
    string filename;
    bool isVideoReading;
    parseCommandLine( argc, argv, isColorizeDisp, isFixedMaxDisp, imageMode, retrievedImageFlags, filename, isVideoReading );

    cout << "Device opening ..." << endl;
    VideoCapture capture;
    if( isVideoReading )
        capture.open( filename );
    else
    {
        capture.open( CAP_OPENNI2 );
        if( !capture.isOpened() )
            capture.open( CAP_OPENNI );
    }

    cout << "done." << endl;

    if( !capture.isOpened() )
    {
        cout << "Can not open a capture object." << endl;
        return -1;
    }

    if( !isVideoReading )
    {
        bool modeRes=false;
        switch ( imageMode )
        {
            case 0:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_VGA_30HZ );
                break;
            case 1:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_SXGA_15HZ );
                break;
            case 2:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_SXGA_30HZ );
                break;
                //The following modes are only supported by the Xtion Pro Live
            case 3:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_QVGA_30HZ );
                break;
            case 4:
                modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_QVGA_60HZ );
                break;
            default:
                CV_Error( Error::StsBadArg, "Unsupported image mode property.\n");
        }
        if (!modeRes)
            cout << "\nThis image mode is not supported by the device, the default value (CV_CAP_OPENNI_SXGA_15HZ) will be used.\n" << endl;
    }

    // Print some avalible device settings.
    cout << "\nDepth generator output mode:" << endl <<
            "FRAME_WIDTH      " << capture.get( CAP_PROP_FRAME_WIDTH ) << endl <<
            "FRAME_HEIGHT     " << capture.get( CAP_PROP_FRAME_HEIGHT ) << endl <<
            "FRAME_MAX_DEPTH  " << capture.get( CAP_PROP_OPENNI_FRAME_MAX_DEPTH ) << " mm" << endl <<
            "FPS              " << capture.get( CAP_PROP_FPS ) << endl <<
            "REGISTRATION     " << capture.get( CAP_PROP_OPENNI_REGISTRATION ) << endl;
    if( capture.get( CAP_OPENNI_IMAGE_GENERATOR_PRESENT ) )
    {
        cout <<
            "\nImage generator output mode:" << endl <<
            "FRAME_WIDTH   " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FRAME_WIDTH ) << endl <<
            "FRAME_HEIGHT  " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FRAME_HEIGHT ) << endl <<
            "FPS           " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FPS ) << endl;
    }
    else
    {
        cout << "\nDevice doesn't contain image generator." << endl;
        if (!retrievedImageFlags[0] && !retrievedImageFlags[1] && !retrievedImageFlags[2])
            return 0;
    }

    for(;;)
    {
        Mat depthMap;
        Mat validDepthMap;
        Mat disparityMap;
        Mat bgrImage;
        Mat grayImage;

        if( !capture.grab() )
        {
            cout << "Can not grab images." << endl;
            return -1;
        }
        else
        {
            if( retrievedImageFlags[0] && capture.retrieve( depthMap, CAP_OPENNI_DEPTH_MAP ) )
            {
                const float scaleFactor = 0.05f;
                Mat show; depthMap.convertTo( show, CV_8UC1, scaleFactor );
                imshow( "depth map", show );
            }

            if( retrievedImageFlags[1] && capture.retrieve( disparityMap, CAP_OPENNI_DISPARITY_MAP ) )
            {
                if( isColorizeDisp )
                {
                    Mat colorDisparityMap;
                    colorizeDisparity( disparityMap, colorDisparityMap, isFixedMaxDisp ? getMaxDisparity(capture) : -1 );
                    Mat validColorDisparityMap;
                    colorDisparityMap.copyTo( validColorDisparityMap, disparityMap != 0 );
                    imshow( "colorized disparity map", validColorDisparityMap );
                }
                else
                {
                    imshow( "original disparity map", disparityMap );
                }
            }

            if( retrievedImageFlags[2] && capture.retrieve( validDepthMap, CAP_OPENNI_VALID_DEPTH_MASK ) )
                imshow( "valid depth mask", validDepthMap );

            if( retrievedImageFlags[3] && capture.retrieve( bgrImage, CAP_OPENNI_BGR_IMAGE ) )
                imshow( "rgb image", bgrImage );

            if( retrievedImageFlags[4] && capture.retrieve( grayImage, CAP_OPENNI_GRAY_IMAGE ) )
                imshow( "gray image", grayImage );
        }

        if( waitKey( 30 ) >= 0 )
            break;
    }

    return 0;
}
<|endoftext|>


<commit_before>#ifndef CONST_STRING_HXX
#define CONST_STRING_HXX

#include <algorithm>
#include <cstddef>
#include <stdexcept>

#include <gsl/gsl_assert.h>

#include <ArrayIteratorPolicy.hxx>
#include <MetaUtils.hxx>
#include <Range.hxx>
#include <StringDetails.hxx>

class ConstString
{
	using IterPolicy = ArrayIteratorPolicy<ConstString>;

public:
	using iterator = typename IterPolicy::const_iterator;
	using reverse_iterator = typename IterPolicy::const_reverse_iterator;
	using const_iterator = typename IterPolicy::const_iterator;
	using const_reverse_iterator = typename IterPolicy::const_reverse_iterator;

	using value_type = const char;
	using reference = const char&;
	using pointer = const char*;

public:
	// Serve for the sole purpose of begin able to be literal type even with default constructor
	ConstString() = default;
	constexpr ConstString(const ConstString& str) = default;

	template<size_t size>
	constexpr ConstString(const char(&cstr)[size]) noexcept : size_(size - 1), cstr_(cstr)
	{}

	template<class TString>
	constexpr ConstString(const TString& other) noexcept : size_(other.size()), cstr_(other.data())
	{}

	constexpr iterator begin() noexcept { return { *this, 0 }; }
	constexpr const_iterator begin() const noexcept { return { *this, 0 }; }
	constexpr const_iterator cbegin() const noexcept { return begin(); }
	constexpr iterator end() noexcept { return { *this, size() }; }
	constexpr const_iterator end() const noexcept { return { *this, size() }; }
	constexpr const_iterator cend() const noexcept { return end(); }

	constexpr reverse_iterator rbegin() noexcept { return end(); }
	constexpr const_reverse_iterator rbegin() const noexcept { return end(); }
	constexpr const_reverse_iterator crbegin() const noexcept { return end(); }
	constexpr reverse_iterator rend() noexcept { return begin(); }
	constexpr const_reverse_iterator rend() const noexcept { return begin(); }
	constexpr const_reverse_iterator crend() const noexcept { return begin(); }

	constexpr const char& at(size_t index) const
	{
		CONSTEXPR_ASSERT(index < size_, "Attempt to access a non-existing index of a constant string");
		return cstr_[index];
	}

	constexpr const char& operator[](size_t index) const
	{
		return at(index);
	}

	constexpr ConstString drop(size_t num) const
	{
		ConstString tmp{*this};
		tmp.cstr_ += num;
		tmp.size_ = size() - num;

		return (num < size() ? tmp : throw std::out_of_range("Attempt to access a non-existing index of a constant string"));
	}

	constexpr ConstString drop(const_iterator it) const
	{
		size_t interval = it - begin();
		ConstString tmp{*this};
		tmp.cstr_ += interval;
		tmp.size_ = end() - it;

		return (it >= begin() && it < end() ? tmp : throw std::out_of_range("Attempt to access a non-existing index of a constant string"));
	}

	constexpr auto find(char c) const noexcept
	-> decltype(begin())
	{
		for(auto it = begin(); it != end(); ++it)
		{
			if(*it == c)
			{
				return it;
			}
		}
		return end();
	}

	// Modified to build with visual studio. Gcc and clang do not need recursion, simple if branches and for loop are working.
	friend constexpr bool operator==(const ConstString& lhs, const ConstString& rhs);

	/* Alternative definition, working on GCC 5.2.0 and Clang 3.7
	It also avoid the recursion depth problem with big strings

	constexpr bool operator==(const ConstString& rhs) const
    {
        if(size_ != rhs.size()) return false;
        for(uint8_t i = 0; i < size_; ++i)
        {
            if((*this)[i] != rhs[i])
            {
                return false;
            }
        }
        return true;
    }
	*/
	constexpr size_t size() const noexcept { return size_; }
	constexpr pointer data() const noexcept { return cstr_; }

	// With this operator, the class would be named ConstStringRef
	/*ConstString operator=(const ConstString& other) noexcept
	{
		cstr_ = other.cstr_;
		return *this;
	}*/

	constexpr operator const char*() const noexcept
	{
		return data();
	}

private:
	size_t size_;

protected:
	pointer cstr_;
};

constexpr bool operator==(const ConstString& lhs, const ConstString& rhs)
{
	return lhs.size() != rhs.size() ? false : Details::equalAux(lhs.size(), lhs, rhs);
}

#endif // CONST_STRING_HXX<commit_msg>Update travis configuration<commit_after>#ifndef CONST_STRING_HXX
#define CONST_STRING_HXX

// Workaround for clang to work with libstdc++
#include <stddef.h>
using max_align_t = size_t;

#include <algorithm>
#include <cstddef>
#include <stdexcept>

#include <gsl/gsl_assert.h>

#include <ArrayIteratorPolicy.hxx>
#include <MetaUtils.hxx>
#include <Range.hxx>
#include <StringDetails.hxx>

class ConstString
{
	using IterPolicy = ArrayIteratorPolicy<ConstString>;

public:
	using iterator = typename IterPolicy::const_iterator;
	using reverse_iterator = typename IterPolicy::const_reverse_iterator;
	using const_iterator = typename IterPolicy::const_iterator;
	using const_reverse_iterator = typename IterPolicy::const_reverse_iterator;

	using value_type = const char;
	using reference = const char&;
	using pointer = const char*;

public:
	// Serve for the sole purpose of begin able to be literal type even with default constructor
	ConstString() = default;
	constexpr ConstString(const ConstString& str) = default;

	template<size_t size>
	constexpr ConstString(const char(&cstr)[size]) noexcept : size_(size - 1), cstr_(cstr)
	{}

	template<class TString>
	constexpr ConstString(const TString& other) noexcept : size_(other.size()), cstr_(other.data())
	{}

	constexpr iterator begin() noexcept { return { *this, 0 }; }
	constexpr const_iterator begin() const noexcept { return { *this, 0 }; }
	constexpr const_iterator cbegin() const noexcept { return begin(); }
	constexpr iterator end() noexcept { return { *this, size() }; }
	constexpr const_iterator end() const noexcept { return { *this, size() }; }
	constexpr const_iterator cend() const noexcept { return end(); }

	constexpr reverse_iterator rbegin() noexcept { return end(); }
	constexpr const_reverse_iterator rbegin() const noexcept { return end(); }
	constexpr const_reverse_iterator crbegin() const noexcept { return end(); }
	constexpr reverse_iterator rend() noexcept { return begin(); }
	constexpr const_reverse_iterator rend() const noexcept { return begin(); }
	constexpr const_reverse_iterator crend() const noexcept { return begin(); }

	constexpr const char& at(size_t index) const
	{
		CONSTEXPR_ASSERT(index < size_, "Attempt to access a non-existing index of a constant string");
		return cstr_[index];
	}

	constexpr const char& operator[](size_t index) const
	{
		return at(index);
	}

	constexpr ConstString drop(size_t num) const
	{
		ConstString tmp{*this};
		tmp.cstr_ += num;
		tmp.size_ = size() - num;

		return (num < size() ? tmp : throw std::out_of_range("Attempt to access a non-existing index of a constant string"));
	}

	constexpr ConstString drop(const_iterator it) const
	{
		size_t interval = it - begin();
		ConstString tmp{*this};
		tmp.cstr_ += interval;
		tmp.size_ = end() - it;

		return (it >= begin() && it < end() ? tmp : throw std::out_of_range("Attempt to access a non-existing index of a constant string"));
	}

	constexpr auto find(char c) const noexcept
	-> decltype(begin())
	{
		for(auto it = begin(); it != end(); ++it)
		{
			if(*it == c)
			{
				return it;
			}
		}
		return end();
	}

	// Modified to build with visual studio. Gcc and clang do not need recursion, simple if branches and for loop are working.
	friend constexpr bool operator==(const ConstString& lhs, const ConstString& rhs);

	/* Alternative definition, working on GCC 5.2.0 and Clang 3.7
	It also avoid the recursion depth problem with big strings

	constexpr bool operator==(const ConstString& rhs) const
    {
        if(size_ != rhs.size()) return false;
        for(uint8_t i = 0; i < size_; ++i)
        {
            if((*this)[i] != rhs[i])
            {
                return false;
            }
        }
        return true;
    }
	*/
	constexpr size_t size() const noexcept { return size_; }
	constexpr pointer data() const noexcept { return cstr_; }

	// With this operator, the class would be named ConstStringRef
	/*ConstString operator=(const ConstString& other) noexcept
	{
		cstr_ = other.cstr_;
		return *this;
	}*/

	constexpr operator const char*() const noexcept
	{
		return data();
	}

private:
	size_t size_;

protected:
	pointer cstr_;
};

constexpr bool operator==(const ConstString& lhs, const ConstString& rhs)
{
	return lhs.size() != rhs.size() ? false : Details::equalAux(lhs.size(), lhs, rhs);
}

#endif // CONST_STRING_HXX<|endoftext|>


<commit_before>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#include<mutex>

#include"ork/ork.hpp"
#if ORK_MSC
#pragma warning(push)
#pragma warning(disable:4371) //Boost layout changed
#pragma warning(disable:4619) //Boost disable non-existant warning
#pragma warning(disable:4625) //Boost implicit copy consructor
#pragma warning(disable:4626) //Boost implicit copy assignment
#pragma warning(disable:4668) //Boost+Windows undefined macro
#pragma warning(disable:5026) //Boost implicit move constructor
#pragma warning(disable:5027) //Boost implicit move assignment
#pragma warning(disable:5031) //Boost unmatched pragma push
#endif

#include"ork/command_line.hpp"
#include"ork/tagger.hpp"
#include"ork/file_utils.hpp"

#define NOMINMAX
#include"windows.h"
#include"DbgHelp.h"

namespace ork {

/*
From database.hpp
*/

bstring uuid2string(const char*const value) {
	b_string_stream stream;
	stream << std::hex;
	LOOPJ(16) {
		stream << (value[j] & (char(15) << 4));
		stream << (value[j] & char(15));
	}
	return stream.str();
}
std::vector<char> string2uuid(const bstring&val) {
	std::vector<char> retval;
	b_string_stream stream;
	stream << std::hex << val;
	LOOPJ(16) {
		char upper, lower;
		stream >> upper >> lower;
		retval.push_back((upper << 4) | lower);
	}
	return retval;
}

/*
From exception.hpp
*/

#if ORK_MSC

backtrace generate_backtrace(const unsigned skip_frames) {
	static const unsigned capture_frames = 128;
	static const unsigned max_name_len = 1024;

	HANDLE process = GetCurrentProcess();
	SymInitialize(process, nullptr, TRUE);

	void *addrs[capture_frames];
	const unsigned short num_addr = CaptureStackBackTrace(skip_frames + 1, capture_frames, addrs, nullptr);

	// Oddly allocated, I know. You must allocate additional memory after the
	// end of the SYMBOL_INFO structure to store the name. This memory must be
	// contiguous, so we can't use basic "new" statements, must resort to malloc
	SYMBOL_INFO *symbol = static_cast<SYMBOL_INFO *>(malloc(sizeof(SYMBOL_INFO) + sizeof(char) * max_name_len));
	symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
	symbol->MaxNameLen = max_name_len - 1;

	// This one stores file/line information
	IMAGEHLP_LINE64 line;
	line.SizeOfStruct = sizeof(line);

	backtrace result;

	LOOPI(num_addr) {
		DWORD64 addr = reinterpret_cast<DWORD64>(addrs[i]);

		DWORD displacement; // I don't care about this output parameter, but it must be supplied
		SymFromAddr(process, addr, 0, symbol);
		SymGetLineFromAddr64(process, addr, &displacement, &line);

		stack_frame frame;
		frame.function = symbol->Name;
		frame.filename = line.FileName;
		frame.line = line.LineNumber;
		result.frames.push_back(frame);
	}

	free(symbol);
	return result;
}

bstring backtrace::str() const {
	b_string_stream stream;

	stream << BORK("backtrace:\n");

	unsigned index = 0;
	for(const stack_frame&sf : frames) {
		stream << index++ << BORK(": ") << sf.function << BORK(" (") << sf.filename << BORK(":") << sf.line << BORK(")\n");
	}

	return stream.str();
}

#else//ORK_MSC

backtrace generate_backtrace(const unsigned skip_frames) {
	return backtrace();
}

bstring backtrace::str() const {
	return bstring();
}

#endif//ORK_MSC

std::ostream &operator << (std::ostream &stream, const backtrace &trace) {
	return stream << trace.str();
}

/*
From file_system.hpp
*/

namespace file {
std::array<uint8_t, 3>utf8_bom = { 0xEF, 0xBB, 0xBF };
std::array<uint8_t, 4>utf8_bom_ = { 0xEF, 0xBB, 0xBF, 0x00 };//For null termination
const char*const utf8_bom_str = reinterpret_cast<char*>(utf8_bom_.data());//Reinterpret cast used to handle pos/neg chars

path canonical_normalized_trimmed(const path&file) {
	const path complete = ext_file::system_complete(file);
	const path canonical = ext_file::canonical(complete);
	string name(canonical.ORK_GEN_STR());
	while(!name.empty() && name.back() == '/') {
		name.pop_back();
	}
	return path(name);
}

bool test_directory(const path&file_or_directory) {
	return ext_file::exists(file_or_directory) && ext_file::is_directory(file_or_directory);
}
bool test_file(const path&file) {
	return ext_file::exists(file) && ext_file::is_regular_file(file);
}
bool ensure_directory(const path&file_or_directory_) {
	//Remove remove_filename and has problems with mixed slashes
	path file_or_directory = canonical_normalized_trimmed(file_or_directory_);
	if(file_or_directory.empty()) {
		return true;
	}
	if(test_directory(file_or_directory)) {
		return true;
	}
	if(file_or_directory.has_extension()) {//Hard to tell if a path would be a directory or file
		file_or_directory.remove_filename();
	}
	file_or_directory = canonical_normalized_trimmed(file_or_directory);
	if(file_or_directory.empty()) {
		return true;//The path was a file in the current directory
	}
	if(test_directory(file_or_directory)) {
		return true;
	}
	return ext_file::create_directories(file_or_directory);
}
bool ensure_file(const path&file) {
	if(!ensure_directory(file))return false;
	if(file.empty() || ext_file::exists(file))return true;
	if(!ext_file::is_regular_file(file))return false;
	return ext_file::create_directories(file);
}

}//namespace file

/*
From file_utils.hpp
*/

bool discard_bom(bi_stream&fin) {
	for(const uint8_t bom : file::utf8_bom) {
		const uint8_t curr = static_cast<uint8_t>(fin.get());
		if(curr != bom) {
			fin.seekg(0);
			return false;
		}
	}
	return true;
}

bool top_subdirectory(const file::path&dir, file::path&p) {
	if(!file::test_directory(dir))ORK_FILE_OPEN_ERR(ORK("Error searching directory!"), dir);

	//Create a list of the paths in the directory, and then sort it
	std::vector<file::path>paths;
	std::copy(ext_file::directory_iterator(dir), ext_file::directory_iterator(), std::back_inserter(paths));
	std::sort(paths.begin(), paths.end());

	for(const file::path&curr_path : paths) {
		if(ext_file::is_directory(curr_path)) {
			p = curr_path;
			return true;
		}
	}

	return false;
}

/*
From text.hpp
*/

struct string_converter_type::impl {
public:
	typedef std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>string_converter;
	typedef std::mutex mutex_type;
	typedef std::lock_guard<mutex_type>lock_type;
public:
	impl() {}
	ORK_NON_COPYABLE(impl)
public:
	string_converter converter;
	std::mutex mutex;
};

string_converter_type::string_converter_type() : _pimpl{ new impl{} } {}
string_converter_type::~string_converter_type() {}

bstring string_converter_type::wide2byte(const wchar_t s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.to_bytes(s);
}
bstring string_converter_type::wide2byte(const wchar_t*s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.to_bytes(s);
}
bstring string_converter_type::wide2byte(const wstring&s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.to_bytes(s);
}
bstring string_converter_type::wide2byte(const wchar_t*first, const wchar_t*last) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.to_bytes(first, last);
}

wstring string_converter_type::byte2wide(const char s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.from_bytes(s);
}
wstring string_converter_type::byte2wide(const char*s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.from_bytes(s);
}
wstring string_converter_type::byte2wide(const bstring&s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.from_bytes(s);
}
wstring string_converter_type::byte2wide(const char*first, const char*last) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.from_bytes(first, last);
}

string_converter_type&g_string_converter() {//From string_types.hpp
	static string_converter_type s_convert;
	return s_convert;
}

}//namespace ork

#if ORK_MSC
#pragma warning(pop)
#endif
<commit_msg>Eliminated unused header and limited pragmas to windows headers<commit_after>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#include<mutex>
#include<sstream>
#include<vector>

#include"ork/tagger.hpp"
#include"ork/file_utils.hpp"

#if ORK_MSC
#pragma warning(push)
#pragma warning(disable:4668) //Windows undefined macro
#define NOMINMAX
#include"windows.h"
#include"DbgHelp.h"
#pragma warning(pop)
#endif

namespace ork {

/*
From database.hpp
*/

bstring uuid2string(const char*const value) {
	b_string_stream stream;
	stream << std::hex;
	LOOPJ(16) {
		stream << (value[j] & (char(15) << 4));
		stream << (value[j] & char(15));
	}
	return stream.str();
}
std::vector<char> string2uuid(const bstring&val) {
	std::vector<char> retval;
	b_string_stream stream;
	stream << std::hex << val;
	LOOPJ(16) {
		char upper, lower;
		stream >> upper >> lower;
		retval.push_back((upper << 4) | lower);
	}
	return retval;
}

/*
From exception.hpp
*/

#if ORK_MSC

backtrace generate_backtrace(const unsigned skip_frames) {
	static const unsigned capture_frames = 128;
	static const unsigned max_name_len = 1024;

	HANDLE process = GetCurrentProcess();
	SymInitialize(process, nullptr, TRUE);

	void *addrs[capture_frames];
	const unsigned short num_addr = CaptureStackBackTrace(skip_frames + 1, capture_frames, addrs, nullptr);

	// Oddly allocated, I know. You must allocate additional memory after the
	// end of the SYMBOL_INFO structure to store the name. This memory must be
	// contiguous, so we can't use basic "new" statements, must resort to malloc
	SYMBOL_INFO *symbol = static_cast<SYMBOL_INFO *>(malloc(sizeof(SYMBOL_INFO) + sizeof(char) * max_name_len));
	symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
	symbol->MaxNameLen = max_name_len - 1;

	// This one stores file/line information
	IMAGEHLP_LINE64 line;
	line.SizeOfStruct = sizeof(line);

	backtrace result;

	LOOPI(num_addr) {
		DWORD64 addr = reinterpret_cast<DWORD64>(addrs[i]);

		DWORD displacement; // I don't care about this output parameter, but it must be supplied
		SymFromAddr(process, addr, 0, symbol);
		SymGetLineFromAddr64(process, addr, &displacement, &line);

		stack_frame frame;
		frame.function = symbol->Name;
		frame.filename = line.FileName;
		frame.line = line.LineNumber;
		result.frames.push_back(frame);
	}

	free(symbol);
	return result;
}

bstring backtrace::str() const {
	b_string_stream stream;

	stream << BORK("backtrace:\n");

	unsigned index = 0;
	for(const stack_frame&sf : frames) {
		stream << index++ << BORK(": ") << sf.function << BORK(" (") << sf.filename << BORK(":") << sf.line << BORK(")\n");
	}

	return stream.str();
}

#else//ORK_MSC

backtrace generate_backtrace(const unsigned skip_frames) {
	return backtrace();
}

bstring backtrace::str() const {
	return bstring();
}

#endif//ORK_MSC

std::ostream &operator << (std::ostream &stream, const backtrace &trace) {
	return stream << trace.str();
}

/*
From file_system.hpp
*/

namespace file {
std::array<uint8_t, 3>utf8_bom = { 0xEF, 0xBB, 0xBF };
std::array<uint8_t, 4>utf8_bom_ = { 0xEF, 0xBB, 0xBF, 0x00 };//For null termination
const char*const utf8_bom_str = reinterpret_cast<char*>(utf8_bom_.data());//Reinterpret cast used to handle pos/neg chars

path canonical_normalized_trimmed(const path&file) {
	const path complete = ext_file::system_complete(file);
	const path canonical = ext_file::canonical(complete);
	string name(canonical.ORK_GEN_STR());
	while(!name.empty() && name.back() == '/') {
		name.pop_back();
	}
	return path(name);
}

bool test_directory(const path&file_or_directory) {
	return ext_file::exists(file_or_directory) && ext_file::is_directory(file_or_directory);
}
bool test_file(const path&file) {
	return ext_file::exists(file) && ext_file::is_regular_file(file);
}
bool ensure_directory(const path&file_or_directory_) {
	//Remove remove_filename and has problems with mixed slashes
	path file_or_directory = canonical_normalized_trimmed(file_or_directory_);
	if(file_or_directory.empty()) {
		return true;
	}
	if(test_directory(file_or_directory)) {
		return true;
	}
	if(file_or_directory.has_extension()) {//Hard to tell if a path would be a directory or file
		file_or_directory.remove_filename();
	}
	file_or_directory = canonical_normalized_trimmed(file_or_directory);
	if(file_or_directory.empty()) {
		return true;//The path was a file in the current directory
	}
	if(test_directory(file_or_directory)) {
		return true;
	}
	return ext_file::create_directories(file_or_directory);
}
bool ensure_file(const path&file) {
	if(!ensure_directory(file))return false;
	if(file.empty() || ext_file::exists(file))return true;
	if(!ext_file::is_regular_file(file))return false;
	return ext_file::create_directories(file);
}

}//namespace file

/*
From file_utils.hpp
*/

bool discard_bom(bi_stream&fin) {
	for(const uint8_t bom : file::utf8_bom) {
		const uint8_t curr = static_cast<uint8_t>(fin.get());
		if(curr != bom) {
			fin.seekg(0);
			return false;
		}
	}
	return true;
}

bool top_subdirectory(const file::path&dir, file::path&p) {
	if(!file::test_directory(dir))ORK_FILE_OPEN_ERR(ORK("Error searching directory!"), dir);

	//Create a list of the paths in the directory, and then sort it
	std::vector<file::path>paths;
	std::copy(ext_file::directory_iterator(dir), ext_file::directory_iterator(), std::back_inserter(paths));
	std::sort(paths.begin(), paths.end());

	for(const file::path&curr_path : paths) {
		if(ext_file::is_directory(curr_path)) {
			p = curr_path;
			return true;
		}
	}

	return false;
}

/*
From text.hpp
*/

struct string_converter_type::impl {
public:
	typedef std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>string_converter;
	typedef std::mutex mutex_type;
	typedef std::lock_guard<mutex_type>lock_type;
public:
	impl() {}
	ORK_NON_COPYABLE(impl)
public:
	string_converter converter;
	std::mutex mutex;
};

string_converter_type::string_converter_type() : _pimpl{ new impl{} } {}
string_converter_type::~string_converter_type() {}

bstring string_converter_type::wide2byte(const wchar_t s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.to_bytes(s);
}
bstring string_converter_type::wide2byte(const wchar_t*s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.to_bytes(s);
}
bstring string_converter_type::wide2byte(const wstring&s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.to_bytes(s);
}
bstring string_converter_type::wide2byte(const wchar_t*first, const wchar_t*last) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.to_bytes(first, last);
}

wstring string_converter_type::byte2wide(const char s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.from_bytes(s);
}
wstring string_converter_type::byte2wide(const char*s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.from_bytes(s);
}
wstring string_converter_type::byte2wide(const bstring&s) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.from_bytes(s);
}
wstring string_converter_type::byte2wide(const char*first, const char*last) {
	impl::lock_type lock(_pimpl->mutex); return _pimpl->converter.from_bytes(first, last);
}

string_converter_type&g_string_converter() {//From string_types.hpp
	static string_converter_type s_convert;
	return s_convert;
}

}//namespace ork
<|endoftext|>


<commit_before>/*
// $Id$
// Fennel is a library of data storage and processing components.
// Copyright (C) 2005-2005 The Eigenbase Project
// Copyright (C) 2005-2005 Disruptive Tech
// Copyright (C) 2005-2005 LucidEra, Inc.
// Portions Copyright (C) 1999-2005 John V. Sichi
//
// This program 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 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "fennel/common/CommonPreamble.h"
#include "fennel/cache/VMAllocator.h"
#include "fennel/common/SysCallExcn.h"

#include <stdlib.h>
#include <malloc.h>

#ifdef HAVE_MMAP
#include <sys/resource.h>
#include <sys/mman.h>
#endif

FENNEL_BEGIN_CPPFILE("$Id$");

VMAllocator::VMAllocator(size_t cbAllocInit,size_t nLocked)
{
    cbAlloc = cbAllocInit;
    nAllocs = 0;
    if (nLocked) {
#ifdef RLIMIT_MEMLOCK
        struct rlimit rl;
        if (::getrlimit(RLIMIT_MEMLOCK,&rl)) {
            throw SysCallExcn("getrlimit failed");
        }
        if (rl.rlim_cur != RLIM_INFINITY) {
            // REVIEW:  what if other stuff in the same process needs
            // locked pages?
            rl.rlim_cur = nLocked*cbAlloc;
            rl.rlim_max = nLocked*cbAlloc;
            if (::setrlimit(RLIMIT_MEMLOCK,&rl)) {
                throw SysCallExcn("setrlimit failed");
            }
        }
#endif
        bLockPages = true;
    } else {
        bLockPages = false;
    }
}

VMAllocator::~VMAllocator()
{
    assert(!getBytesAllocated());
}

void *VMAllocator::allocate()
{
#ifdef HAVE_MMAP
    void *v = ::mmap(
        NULL,cbAlloc,PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
    if (v == MAP_FAILED) {
        throw SysCallExcn("mmap failed");
    }
    if (bLockPages) {
        if (::mlock(v,cbAlloc)) {
            SysCallExcn excn("mlock failed");
            ::munmap(v,cbAlloc);
            throw excn;
        }
    }
#else
    void *v = malloc(cbAlloc);
    if (v == NULL) {
        throw SysCallExcn("mmap failed");
    }
#endif
    ++nAllocs;
    return v;
}

void VMAllocator::deallocate(void *p)
{
#ifdef HAVE_MMAP
    if (bLockPages) {
        if (::munlock(p,cbAlloc)) {
            throw SysCallExcn("munlock failed");
        }
    }
    if (::munmap((caddr_t)p,cbAlloc)) {
        throw SysCallExcn("munmap failed");
    }
#else
    free(p);
#endif
    --nAllocs;
}

size_t VMAllocator::getBytesAllocated() const
{
    return nAllocs*cbAlloc;
}

FENNEL_END_CPPFILE("$Id$");

// End VMAllocator.cpp
<commit_msg>FENNEL:  add fencing for cache buffers to catch stray out-of-bounds access (both reads and writes) on Linux debug builds; still need to add dynamic mprotect based on  cache page map/lock state<commit_after>/*
// $Id$
// Fennel is a library of data storage and processing components.
// Copyright (C) 2005-2005 The Eigenbase Project
// Copyright (C) 2005-2005 Disruptive Tech
// Copyright (C) 2005-2005 LucidEra, Inc.
// Portions Copyright (C) 1999-2005 John V. Sichi
//
// This program 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 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "fennel/common/CommonPreamble.h"
#include "fennel/cache/VMAllocator.h"
#include "fennel/common/SysCallExcn.h"

#include <stdlib.h>
#include <malloc.h>

#ifdef HAVE_MMAP
#include <sys/resource.h>
#include <sys/mman.h>
#endif

FENNEL_BEGIN_CPPFILE("$Id$");

VMAllocator::VMAllocator(size_t cbAllocInit,size_t nLocked)
{
    cbAlloc = cbAllocInit;
    nAllocs = 0;
    if (nLocked) {
#ifdef RLIMIT_MEMLOCK
        struct rlimit rl;
        if (::getrlimit(RLIMIT_MEMLOCK,&rl)) {
            throw SysCallExcn("getrlimit failed");
        }
        if (rl.rlim_cur != RLIM_INFINITY) {
            // REVIEW:  what if other stuff in the same process needs
            // locked pages?
            rl.rlim_cur = nLocked*cbAlloc;
            rl.rlim_max = nLocked*cbAlloc;
            if (::setrlimit(RLIMIT_MEMLOCK,&rl)) {
                throw SysCallExcn("setrlimit failed");
            }
        }
#endif
        bLockPages = true;
    } else {
        bLockPages = false;
    }
}

VMAllocator::~VMAllocator()
{
    assert(!getBytesAllocated());
}

void *VMAllocator::allocate()
{
#ifdef HAVE_MMAP

    uint cbActualAlloc = cbAlloc;
#ifndef NDEBUG
    // For a debug build, allocate "fence" regions before and after each
    // allocated buffer.  This helps to catch stray pointers around buffer
    // boundaries.  The fence size is one OS memory page, since that's
    // the minimum unit of protection, and also guarantees 512-byte
    // alignment for O_DIRECT file access.
    cbActualAlloc += 2*getpagesize();
#endif

    void *v = ::mmap(
        NULL,cbActualAlloc,
        PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
    if (v == MAP_FAILED) {
        throw SysCallExcn("mmap failed");
    }

#ifndef NDEBUG
    PBuffer p = static_cast<PBuffer>(v);
    memset(p, 0xFE, getpagesize());
    if (::mprotect(p, getpagesize(), PROT_NONE)) {
        SysCallExcn excn("mprotect on pre-fence failed");
        ::munmap(v,cbAlloc);
        throw excn;
    }
    p += getpagesize();
    memset(p, 0xFF, cbAlloc);
    v = p;
    p += cbAlloc;
    memset(p, 0xFE, getpagesize());
    if (::mprotect(p, getpagesize(), PROT_NONE)) {
        SysCallExcn excn("mprotect on post-fence failed");
        ::munmap(v,cbAlloc);
        throw excn;
    }
#endif

    if (bLockPages) {
        if (::mlock(v,cbAlloc)) {
            SysCallExcn excn("mlock failed");
            ::munmap(v,cbAlloc);
            throw excn;
        }
    }
#else
    void *v = malloc(cbAlloc);
    if (v == NULL) {
        throw SysCallExcn("mmap failed");
    }
#endif
    ++nAllocs;
    return v;
}

void VMAllocator::deallocate(void *p)
{
#ifdef HAVE_MMAP
    if (bLockPages) {
        if (::munlock(p,cbAlloc)) {
            throw SysCallExcn("munlock failed");
        }
    }

    uint cbActualAlloc = cbAlloc;
#ifndef NDEBUG
    PBuffer p2 = static_cast<PBuffer>(p);
    p2 -= getpagesize();
    p = p2;
    cbActualAlloc += 2*getpagesize();
#endif
    if (::munmap((caddr_t)p,cbActualAlloc)) {
        throw SysCallExcn("munmap failed");
    }
#else
    free(p);
#endif
    --nAllocs;
}

size_t VMAllocator::getBytesAllocated() const
{
    return nAllocs*cbAlloc;
}

FENNEL_END_CPPFILE("$Id$");

// End VMAllocator.cpp
<|endoftext|>


<commit_before>/*****************************************************************************
 * common.hpp: Basic shared types & helpers
 *****************************************************************************
 * Copyright © 2014 the VideoLAN team
 *
 * Authors: Alexey Sokolov <alexey@alexeysokolov.co.cc>
 *          Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program 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 program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef LIBVLC_CXX_COMMON_H
#define LIBVLC_CXX_COMMON_H

#include <vlc/vlc.h>
#include <memory>

namespace VLC
{
    class Media;
    using MediaPtr = std::shared_ptr<Media>;

    // Work around cross class dependencies
    // Class A needs to access B's internal pointer
    // Class B needs to access A's internal pointer
    // By using a template function to do this, we're delegating
    // the access to both classes' guts to a later point, when the compiler
    // already knows everything it needs.
    // The only drawback is that we can't return decltype(ptr->get()), since when
    // the compiler checks for the prototype, it hasn't parsed all the declarations yet.
    template <typename TYPE, typename REF>
    TYPE* getInternalPtr(const REF& ref)
    {
        return ref.get();
    }

    std::unique_ptr<char, void (*)(void*)> wrapCStr(char* str)
    {
        return std::unique_ptr<char, void(*)(void*)>( str, [](void* ptr) { libvlc_free(ptr); } );
    }
}

#endif
<commit_msg>common.hpp: Fix potential multiple definition<commit_after>/*****************************************************************************
 * common.hpp: Basic shared types & helpers
 *****************************************************************************
 * Copyright © 2014 the VideoLAN team
 *
 * Authors: Alexey Sokolov <alexey@alexeysokolov.co.cc>
 *          Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program 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 program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef LIBVLC_CXX_COMMON_H
#define LIBVLC_CXX_COMMON_H

#include <vlc/vlc.h>
#include <memory>

namespace VLC
{
    class Media;
    using MediaPtr = std::shared_ptr<Media>;

    // Work around cross class dependencies
    // Class A needs to access B's internal pointer
    // Class B needs to access A's internal pointer
    // By using a template function to do this, we're delegating
    // the access to both classes' guts to a later point, when the compiler
    // already knows everything it needs.
    // The only drawback is that we can't return decltype(ptr->get()), since when
    // the compiler checks for the prototype, it hasn't parsed all the declarations yet.
    template <typename TYPE, typename REF>
    TYPE* getInternalPtr(const REF& ref)
    {
        return ref.get();
    }

    inline std::unique_ptr<char, void (*)(void*)> wrapCStr(char* str)
    {
        return std::unique_ptr<char, void(*)(void*)>( str, [](void* ptr) { libvlc_free(ptr); } );
    }
}

#endif
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QGraphicsWidget>
#include <QGraphicsProxyWidget>
#include <QGraphicsAnchorLayout>
#include <QtGui>

static QGraphicsProxyWidget *createItem(const QSizeF &minimum = QSizeF(100.0, 100.0),
                                   const QSizeF &preferred = QSize(150.0, 100.0),
                                   const QSizeF &maximum = QSizeF(200.0, 100.0),
                                   const QString &name = "0")
{
    QGraphicsProxyWidget *w = new QGraphicsProxyWidget;
    w->setWidget(new QPushButton(name));
    w->setData(0, name);
    w->setMinimumSize(minimum);
    w->setPreferredSize(preferred);
    w->setMaximumSize(maximum);

    return w;
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QGraphicsScene scene;
    scene.setSceneRect(0, 0, 800, 480);

    QSizeF minSize(30, 100);
    QSizeF prefSize(210, 100);
    QSizeF maxSize(300, 100);

    QGraphicsProxyWidget *a = createItem(minSize, prefSize, maxSize, "A");
    QGraphicsProxyWidget *b = createItem(minSize, prefSize, maxSize, "B");
    QGraphicsProxyWidget *c = createItem(minSize, prefSize, maxSize, "C");
    QGraphicsProxyWidget *d = createItem(minSize, prefSize, maxSize, "D");
    QGraphicsProxyWidget *e = createItem(minSize, prefSize, maxSize, "E");
    QGraphicsProxyWidget *f = createItem(QSizeF(30, 50), QSizeF(150, 50), maxSize, "F");
    QGraphicsProxyWidget *g = createItem(QSizeF(30, 50), QSizeF(30, 100), maxSize, "G");

    QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
    l->setSpacing(0);

    QGraphicsWidget *w = new QGraphicsWidget(0, Qt::Window);
    w->setPos(20, 20);
    w->setLayout(l);

    // vertical
    QGraphicsAnchor *anchor = l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop);
    anchor = l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop);

    anchor = l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom);
    anchor = l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom);
    anchor = l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
    anchor = l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop);

    anchor = l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
    anchor = l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom);

    anchor = l->addAnchor(c, Qt::AnchorTop, f, Qt::AnchorTop);
    anchor = l->addAnchor(c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom);
    anchor = l->addAnchor(f, Qt::AnchorBottom, g, Qt::AnchorTop);
    anchor = l->addAnchor(c, Qt::AnchorBottom, g, Qt::AnchorBottom);

    // horizontal
    anchor = l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
    anchor = l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft);
    anchor = l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);

    anchor = l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
    anchor = l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft);

    anchor = l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight);
    anchor = l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight);
    anchor = l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft);

    anchor = l->addAnchor(l, Qt::AnchorLeft, f, Qt::AnchorLeft);
    anchor = l->addAnchor(l, Qt::AnchorLeft, g, Qt::AnchorLeft);
    anchor = l->addAnchor(f, Qt::AnchorRight, g, Qt::AnchorRight);

    scene.addItem(w);
    scene.setBackgroundBrush(Qt::darkGreen);
    QGraphicsView *view = new QGraphicsView(&scene);
    view->show();

    return app.exec();
}
<commit_msg>QGraphicsAnchorLayout: Set size policy in the example<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QGraphicsWidget>
#include <QGraphicsProxyWidget>
#include <QGraphicsAnchorLayout>
#include <QtGui>

static QGraphicsProxyWidget *createItem(const QSizeF &minimum = QSizeF(100.0, 100.0),
                                   const QSizeF &preferred = QSize(150.0, 100.0),
                                   const QSizeF &maximum = QSizeF(200.0, 100.0),
                                   const QString &name = "0")
{
    QGraphicsProxyWidget *w = new QGraphicsProxyWidget;
    w->setWidget(new QPushButton(name));
    w->setData(0, name);
    w->setMinimumSize(minimum);
    w->setPreferredSize(preferred);
    w->setMaximumSize(maximum);

    w->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    return w;
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QGraphicsScene scene;
    scene.setSceneRect(0, 0, 800, 480);

    QSizeF minSize(30, 100);
    QSizeF prefSize(210, 100);
    QSizeF maxSize(300, 100);

    QGraphicsProxyWidget *a = createItem(minSize, prefSize, maxSize, "A");
    QGraphicsProxyWidget *b = createItem(minSize, prefSize, maxSize, "B");
    QGraphicsProxyWidget *c = createItem(minSize, prefSize, maxSize, "C");
    QGraphicsProxyWidget *d = createItem(minSize, prefSize, maxSize, "D");
    QGraphicsProxyWidget *e = createItem(minSize, prefSize, maxSize, "E");
    QGraphicsProxyWidget *f = createItem(QSizeF(30, 50), QSizeF(150, 50), maxSize, "F");
    QGraphicsProxyWidget *g = createItem(QSizeF(30, 50), QSizeF(30, 100), maxSize, "G");

    QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
    l->setSpacing(0);

    QGraphicsWidget *w = new QGraphicsWidget(0, Qt::Window);
    w->setPos(20, 20);
    w->setLayout(l);

    // vertical
    QGraphicsAnchor *anchor = l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop);
    anchor = l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop);

    anchor = l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom);
    anchor = l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom);
    anchor = l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
    anchor = l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop);

    anchor = l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
    anchor = l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom);

    anchor = l->addAnchor(c, Qt::AnchorTop, f, Qt::AnchorTop);
    anchor = l->addAnchor(c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom);
    anchor = l->addAnchor(f, Qt::AnchorBottom, g, Qt::AnchorTop);
    anchor = l->addAnchor(c, Qt::AnchorBottom, g, Qt::AnchorBottom);

    // horizontal
    anchor = l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
    anchor = l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft);
    anchor = l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);

    anchor = l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
    anchor = l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft);

    anchor = l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight);
    anchor = l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight);
    anchor = l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft);

    anchor = l->addAnchor(l, Qt::AnchorLeft, f, Qt::AnchorLeft);
    anchor = l->addAnchor(l, Qt::AnchorLeft, g, Qt::AnchorLeft);
    anchor = l->addAnchor(f, Qt::AnchorRight, g, Qt::AnchorRight);

    scene.addItem(w);
    scene.setBackgroundBrush(Qt::darkGreen);
    QGraphicsView *view = new QGraphicsView(&scene);
    view->show();

    return app.exec();
}
<|endoftext|>