<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include <sstream>
#include <TestSuite/Tester.h>
#include <Utility/Configuration.h>

#include "Color.h"

namespace Magnum { namespace Test {

class ColorTest: public TestSuite::Tester {
    public:
        ColorTest();

        void fromHue();
        void fromSaturation();
        void fromValue();

        void hue();
        void saturation();
        void value();

        void hsv();
        void hsvOverflow();
        void hsvAlpha();

        void swizzleType();
        void debug();
        void configuration();
};

typedef BasicColor3<UnsignedByte> Color3ub;
typedef BasicColor4<UnsignedByte> Color4ub;

ColorTest::ColorTest() {
    addTests({&ColorTest::fromHue,
              &ColorTest::fromSaturation,
              &ColorTest::fromValue,

              &ColorTest::hue,
              &ColorTest::saturation,
              &ColorTest::value,

              &ColorTest::hsv,
              &ColorTest::hsvOverflow,
              &ColorTest::hsvAlpha,

              &ColorTest::swizzleType,
              &ColorTest::debug,
              &ColorTest::configuration});
}

void ColorTest::fromHue() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(27.0f), 1.0f, 1.0f), Color3ub(255, 114, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(86.0f), 1.0f, 1.0f), Color3ub(144, 255, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(134.0f), 1.0f, 1.0f), Color3ub(0, 255, 59));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(191.0f), 1.0f, 1.0f), Color3ub(0, 208, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(269.0f), 1.0f, 1.0f), Color3ub(123, 0, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(317.0f), 1.0f, 1.0f), Color3ub(255, 0, 182));
}

void ColorTest::hue() {
    CORRADE_COMPARE(Color3ub(255, 115, 0).hue(), Deg(27.058824f));
    CORRADE_COMPARE(Color3ub(145, 255, 0).hue(), Deg(85.882353f));
    CORRADE_COMPARE(Color3ub(0, 255, 60).hue(), Deg(134.11765f));
    CORRADE_COMPARE(Color3ub(0, 208, 255).hue(), Deg(191.05882f));
    CORRADE_COMPARE(Color3ub(123, 0, 255).hue(), Deg(268.94117f));
    CORRADE_COMPARE(Color3ub(255, 0, 183).hue(), Deg(316.94117f));
}

void ColorTest::fromSaturation() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(0.0f), 0.702f, 1.0f), Color3ub(255, 75, 75));
}

void ColorTest::saturation() {
    CORRADE_COMPARE(Color3ub(255, 76, 76).saturation(), 0.701961f);
    CORRADE_COMPARE(Color3ub().saturation(), 0.0f);
}

void ColorTest::fromValue() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(0.0f), 1.0f, 0.522f), Color3ub(133, 0, 0));
}

void ColorTest::value() {
    CORRADE_COMPARE(Color3ub(133, 0, 0).value(), 0.521569f);
}

void ColorTest::hsv() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(230.0f), 0.749f, 0.427f), Color3ub(27, 40, 108));

    Deg hue;
    Float saturation, value;
    std::tie(hue, saturation, value) = Color3ub(27, 41, 109).toHSV();
    CORRADE_COMPARE(hue, Deg(229.756106f));
    CORRADE_COMPARE(saturation, 0.752294f);
    CORRADE_COMPARE(value, 0.427451f);
}

void ColorTest::hsvOverflow() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(27.0f-360.0f), 1.0f, 1.0f), Color3ub(255, 114, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(86.0f-360.0f), 1.0f, 1.0f), Color3ub(144, 255, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(134.0f-360.0f), 1.0f, 1.0f), Color3ub(0, 255, 59));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(191.0f-360.0f), 1.0f, 1.0f), Color3ub(0, 208, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(269.0f-360.0f), 1.0f, 1.0f), Color3ub(123, 0, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(317.0f-360.0f), 1.0f, 1.0f), Color3ub(255, 0, 182));

    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+27.0f), 1.0f, 1.0f), Color3ub(255, 114, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+86.0f), 1.0f, 1.0f), Color3ub(144, 255, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+134.0f), 1.0f, 1.0f), Color3ub(0, 255, 59));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+191.0f), 1.0f, 1.0f), Color3ub(0, 208, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+269.0f), 1.0f, 1.0f), Color3ub(123, 0, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+317.0f), 1.0f, 1.0f), Color3ub(255, 0, 182));
}

void ColorTest::hsvAlpha() {
    CORRADE_COMPARE(Color4ub::fromHSV(std::make_tuple(Deg(230.0f), 0.749f, 0.427f), 23), Color4ub(27, 40, 108, 23));
    CORRADE_COMPARE(Color4ub::fromHSV(Deg(230.0f), 0.749f, 0.427f, 23), Color4ub(27, 40, 108, 23));
}

void ColorTest::swizzleType() {
    constexpr Color3 origColor3;
    constexpr BasicColor4<UnsignedByte> origColor4;

    constexpr auto a = Math::swizzle<'y', 'z', 'r'>(origColor3);
    CORRADE_VERIFY((std::is_same<decltype(a), const Color3>::value));

    constexpr auto b = Math::swizzle<'y', 'z', 'a'>(origColor4);
    CORRADE_VERIFY((std::is_same<decltype(b), const BasicColor3<UnsignedByte>>::value));

    constexpr auto c = Math::swizzle<'y', 'z', 'y', 'x'>(origColor3);
    CORRADE_VERIFY((std::is_same<decltype(c), const Color4>::value));

    constexpr auto d = Math::swizzle<'y', 'a', 'y', 'x'>(origColor4);
    CORRADE_VERIFY((std::is_same<decltype(d), const BasicColor4<UnsignedByte>>::value));
}

void ColorTest::debug() {
    std::ostringstream o;
    Debug(&o) << Color3(0.5f, 0.75f, 1.0f);
    CORRADE_COMPARE(o.str(), "Vector(0.5, 0.75, 1)\n");

    o.str({});
    Debug(&o) << Color4(0.5f, 0.75f, 0.0f, 1.0f);
    CORRADE_COMPARE(o.str(), "Vector(0.5, 0.75, 0, 1)\n");
}

void ColorTest::configuration() {
    Utility::Configuration c;

    Color3 color3(0.5f, 0.75f, 1.0f);
    std::string value3("0.5 0.75 1");

    c.setValue("color3", color3);
    CORRADE_COMPARE(c.value("color3"), value3);
    CORRADE_COMPARE(c.value<Color3>("color3"), color3);

    Color4 color4(0.5f, 0.75f, 0.0f, 1.0f);
    std::string value4("0.5 0.75 0 1");

    c.setValue("color4", color4);
    CORRADE_COMPARE(c.value("color4"), value4);
    CORRADE_COMPARE(c.value<Color4>("color4"), color4);
}

}}

CORRADE_TEST_MAIN(Magnum::Test::ColorTest)
<commit_msg>Properly test all Color constructors.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include <sstream>
#include <TestSuite/Tester.h>
#include <Utility/Configuration.h>

#include "Color.h"

namespace Magnum { namespace Test {

class ColorTest: public TestSuite::Tester {
    public:
        ColorTest();

        void construct();
        void constructDefault();
        void constructOneValue();
        void constructParts();
        void constructConversion();
        void constructNormalization();
        void constructCopy();

        void fromHue();
        void fromSaturation();
        void fromValue();

        void hue();
        void saturation();
        void value();

        void hsv();
        void hsvOverflow();
        void hsvAlpha();

        void swizzleType();
        void debug();
        void configuration();
};

typedef BasicColor3<UnsignedByte> Color3ub;
typedef BasicColor4<UnsignedByte> Color4ub;

ColorTest::ColorTest() {
    addTests({&ColorTest::construct,
              &ColorTest::constructDefault,
              &ColorTest::constructOneValue,
              &ColorTest::constructParts,
              &ColorTest::constructConversion,
              &ColorTest::constructNormalization,
              &ColorTest::constructCopy,

              &ColorTest::fromHue,
              &ColorTest::fromSaturation,
              &ColorTest::fromValue,

              &ColorTest::hue,
              &ColorTest::saturation,
              &ColorTest::value,

              &ColorTest::hsv,
              &ColorTest::hsvOverflow,
              &ColorTest::hsvAlpha,

              &ColorTest::swizzleType,
              &ColorTest::debug,
              &ColorTest::configuration});
}

void ColorTest::construct() {
    constexpr Color3 a = {1.0f, 0.5f, 0.75f};
    CORRADE_COMPARE(a, Vector3(1.0f, 0.5f, 0.75f));

    constexpr Color4 b = {1.0f, 0.5f, 0.75f, 0.5f};
    CORRADE_COMPARE(b, Vector4(1.0f, 0.5f, 0.75f, 0.5f));

    /* Default alpha */
    constexpr Color4 c = {1.0f, 0.5f, 0.75f};
    constexpr Color4ub d = {10, 25, 176};
    CORRADE_COMPARE(c, Vector4(1.0f, 0.5f, 0.75f, 1.0f));
    CORRADE_COMPARE(d, Math::Vector4<UnsignedByte>(10, 25, 176, 255));
}

void ColorTest::constructDefault() {
    constexpr Vector3 a;
    CORRADE_COMPARE(a, Color3(0.0f, 0.0f, 0.0f));

    constexpr Color4 b;
    constexpr Color4ub c;
    CORRADE_COMPARE(b, Color4(0.0f, 0.0f, 0.0f, 1.0f));
    CORRADE_COMPARE(c, Color4ub(0, 0, 0, 255));
}

void ColorTest::constructOneValue() {
    constexpr Color3 a(0.25f);
    CORRADE_COMPARE(a, Color3(0.25f, 0.25f, 0.25f));

    constexpr Color4 b(0.25f, 0.5f);
    CORRADE_COMPARE(b, Color4(0.25f, 0.25f, 0.25f, 0.5f));

    /* Default alpha */
    constexpr Color4 c(0.25f);
    constexpr Color4ub d(67);
    CORRADE_COMPARE(c, Color4(0.25f, 0.25f, 0.25f, 1.0f));
    CORRADE_COMPARE(d, Color4ub(67, 67, 67, 255));

    /* Implicit conversion is not allowed */
    CORRADE_VERIFY(!(std::is_convertible<Float, Color3>::value));
    CORRADE_VERIFY(!(std::is_convertible<Float, Color4>::value));
}

void ColorTest::constructParts() {
    constexpr Color3 a(1.0f, 0.5f, 0.75f);

    constexpr Color4 b = {a, 0.25f};
    CORRADE_COMPARE(b, Color4(1.0f, 0.5f, 0.75f, 0.25f));

    /* Default alpha */
    constexpr Color3ub c(10, 25, 176);
    constexpr Color4 d = a;
    constexpr Color4ub e = c;
    CORRADE_COMPARE(d, Color4(1.0f, 0.5f, 0.75f, 1.0f));
    CORRADE_COMPARE(e, Color4ub(10, 25, 176, 255));
}

void ColorTest::constructConversion() {
    typedef BasicColor3<Double> Color3d;
    typedef BasicColor4<Double> Color4d;

    constexpr Color3 a(1.0f, 0.5f, 0.75f);
    constexpr Color3d b(a);
    CORRADE_COMPARE(b, Color3d(1.0, 0.5, 0.75));

    constexpr Color4 c(1.0f, 0.5f, 0.75f, 0.25f);
    constexpr Color4d d(c);
    CORRADE_COMPARE(d, Color4d(1.0, 0.5, 0.75, 0.25));

    /* Implicit conversion is not allowed */
    CORRADE_VERIFY(!(std::is_convertible<Color3, Color3d>::value));
    CORRADE_VERIFY(!(std::is_convertible<Color4, Color4d>::value));
}

void ColorTest::constructNormalization() {
    constexpr Color3 a(1.0f, 0.5f, 0.75f);
    auto b = Math::denormalize<Color3ub>(a);
    CORRADE_COMPARE(b, Color3ub(255, 127, 191));

    constexpr Color4 c(1.0f, 0.5f, 0.75f, 0.25f);
    auto d = Math::denormalize<Color4ub>(c);
    CORRADE_COMPARE(d, Color4ub(255, 127, 191, 63));
}

void ColorTest::constructCopy() {
    constexpr Math::Vector<3, Float> a(1.0f, 0.5f, 0.75f);
    constexpr Color3 b(a);
    CORRADE_COMPARE(b, Color3(1.0f, 0.5f, 0.75f));

    constexpr Math::Vector<4, Float> c(1.0f, 0.5f, 0.75f, 0.25f);
    constexpr Color4 d(c);
    CORRADE_COMPARE(d, Color4(1.0f, 0.5f, 0.75f, 0.25f));
}

void ColorTest::fromHue() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(27.0f), 1.0f, 1.0f), Color3ub(255, 114, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(86.0f), 1.0f, 1.0f), Color3ub(144, 255, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(134.0f), 1.0f, 1.0f), Color3ub(0, 255, 59));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(191.0f), 1.0f, 1.0f), Color3ub(0, 208, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(269.0f), 1.0f, 1.0f), Color3ub(123, 0, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(317.0f), 1.0f, 1.0f), Color3ub(255, 0, 182));
}

void ColorTest::hue() {
    CORRADE_COMPARE(Color3ub(255, 115, 0).hue(), Deg(27.058824f));
    CORRADE_COMPARE(Color3ub(145, 255, 0).hue(), Deg(85.882353f));
    CORRADE_COMPARE(Color3ub(0, 255, 60).hue(), Deg(134.11765f));
    CORRADE_COMPARE(Color3ub(0, 208, 255).hue(), Deg(191.05882f));
    CORRADE_COMPARE(Color3ub(123, 0, 255).hue(), Deg(268.94117f));
    CORRADE_COMPARE(Color3ub(255, 0, 183).hue(), Deg(316.94117f));
}

void ColorTest::fromSaturation() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(0.0f), 0.702f, 1.0f), Color3ub(255, 75, 75));
}

void ColorTest::saturation() {
    CORRADE_COMPARE(Color3ub(255, 76, 76).saturation(), 0.701961f);
    CORRADE_COMPARE(Color3ub().saturation(), 0.0f);
}

void ColorTest::fromValue() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(0.0f), 1.0f, 0.522f), Color3ub(133, 0, 0));
}

void ColorTest::value() {
    CORRADE_COMPARE(Color3ub(133, 0, 0).value(), 0.521569f);
}

void ColorTest::hsv() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(230.0f), 0.749f, 0.427f), Color3ub(27, 40, 108));

    Deg hue;
    Float saturation, value;
    std::tie(hue, saturation, value) = Color3ub(27, 41, 109).toHSV();
    CORRADE_COMPARE(hue, Deg(229.756106f));
    CORRADE_COMPARE(saturation, 0.752294f);
    CORRADE_COMPARE(value, 0.427451f);
}

void ColorTest::hsvOverflow() {
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(27.0f-360.0f), 1.0f, 1.0f), Color3ub(255, 114, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(86.0f-360.0f), 1.0f, 1.0f), Color3ub(144, 255, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(134.0f-360.0f), 1.0f, 1.0f), Color3ub(0, 255, 59));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(191.0f-360.0f), 1.0f, 1.0f), Color3ub(0, 208, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(269.0f-360.0f), 1.0f, 1.0f), Color3ub(123, 0, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(317.0f-360.0f), 1.0f, 1.0f), Color3ub(255, 0, 182));

    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+27.0f), 1.0f, 1.0f), Color3ub(255, 114, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+86.0f), 1.0f, 1.0f), Color3ub(144, 255, 0));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+134.0f), 1.0f, 1.0f), Color3ub(0, 255, 59));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+191.0f), 1.0f, 1.0f), Color3ub(0, 208, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+269.0f), 1.0f, 1.0f), Color3ub(123, 0, 255));
    CORRADE_COMPARE(Color3ub::fromHSV(Deg(360.0f+317.0f), 1.0f, 1.0f), Color3ub(255, 0, 182));
}

void ColorTest::hsvAlpha() {
    CORRADE_COMPARE(Color4ub::fromHSV(std::make_tuple(Deg(230.0f), 0.749f, 0.427f), 23), Color4ub(27, 40, 108, 23));
    CORRADE_COMPARE(Color4ub::fromHSV(Deg(230.0f), 0.749f, 0.427f, 23), Color4ub(27, 40, 108, 23));
}

void ColorTest::swizzleType() {
    constexpr Color3 origColor3;
    constexpr BasicColor4<UnsignedByte> origColor4;

    constexpr auto a = Math::swizzle<'y', 'z', 'r'>(origColor3);
    CORRADE_VERIFY((std::is_same<decltype(a), const Color3>::value));

    constexpr auto b = Math::swizzle<'y', 'z', 'a'>(origColor4);
    CORRADE_VERIFY((std::is_same<decltype(b), const BasicColor3<UnsignedByte>>::value));

    constexpr auto c = Math::swizzle<'y', 'z', 'y', 'x'>(origColor3);
    CORRADE_VERIFY((std::is_same<decltype(c), const Color4>::value));

    constexpr auto d = Math::swizzle<'y', 'a', 'y', 'x'>(origColor4);
    CORRADE_VERIFY((std::is_same<decltype(d), const BasicColor4<UnsignedByte>>::value));
}

void ColorTest::debug() {
    std::ostringstream o;
    Debug(&o) << Color3(0.5f, 0.75f, 1.0f);
    CORRADE_COMPARE(o.str(), "Vector(0.5, 0.75, 1)\n");

    o.str({});
    Debug(&o) << Color4(0.5f, 0.75f, 0.0f, 1.0f);
    CORRADE_COMPARE(o.str(), "Vector(0.5, 0.75, 0, 1)\n");
}

void ColorTest::configuration() {
    Utility::Configuration c;

    Color3 color3(0.5f, 0.75f, 1.0f);
    std::string value3("0.5 0.75 1");

    c.setValue("color3", color3);
    CORRADE_COMPARE(c.value("color3"), value3);
    CORRADE_COMPARE(c.value<Color3>("color3"), color3);

    Color4 color4(0.5f, 0.75f, 0.0f, 1.0f);
    std::string value4("0.5 0.75 0 1");

    c.setValue("color4", color4);
    CORRADE_COMPARE(c.value("color4"), value4);
    CORRADE_COMPARE(c.value<Color4>("color4"), color4);
}

}}

CORRADE_TEST_MAIN(Magnum::Test::ColorTest)
<|endoftext|>


<commit_before>#ifndef _WARN_GUARD_HPP_
#define _WARN_GUARD_HPP_

#ifdef _MSC_VER
#define DO_PRAGMA(x) __pragma(x)
#else
#define DO_PRAGMA(x) _Pragma(#x)
#endif

//=======================================================
// Clang
//=======================================================
#define CLANG_WARN_GUARD_ON                         \
    DO_PRAGMA(clang diagnostic push)                \
    DO_PRAGMA(clang diagnostic ignored "-Wall")     \
    DO_PRAGMA(clang diagnostic ignored "-Wextra")

#define CLANG_WARN_GUARD_OFF                        \
    DO_PRAGMA(clang diagnostic pop)

//=======================================================
// MSVC
//=======================================================
#define MSVC_WARN_GUARD_ON                          \
    DO_PRAGMA(warning(push, 0))

#define MSVC_WARN_GUARD_OFF                         \
    DO_PRAGMA(warning(pop))

//=======================================================
// Gcc
//=======================================================
#define GCC_WARN_GUARD_ON                           \
    DO_PRAGMA(GCC diagnostic push)                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wall")       \
    DO_PRAGMA(GCC diagnostic ignored "-Wextra")

#define GCC_WARN_GUARD_OFF                          \
    DO_PRAGMA(GCC diagnostic pop)

//=======================================================
// Unknown
//=======================================================
#define UNKNOWN_WARN_GUARD_ON
#define UNKNOWN_WARN_GUARD_OFF

//=======================================================
// All
//=======================================================

#ifdef _MSC_VER
    #define WARN_GUARD_ON  MSVC_WARN_GUARD_ON
    #define WARN_GUARD_OFF MSVC_WARN_GUARD_OFF
#elif __clang__
    #define WARN_GUARD_ON  CLANG_WARN_GUARD_ON
    #define WARN_GUARD_OFF CLANG_WARN_GUARD_OFF
#elif __GNUC__
    #define WARN_GUARD_ON  GCC_WARN_GUARD_ON
    #define WARN_GUARD_OFF GCC_WARN_GUARD_OFF
#else
    #define WARN_GUARD_ON  UNKNOWN_WARN_GUARD_ON
    #define WARN_GUARD_OFF UNKNOWN_WARN_GUARD_OFF
#endif

#endif
<commit_msg>WarnGuard mutes now correctly GCC warnings<commit_after>#ifndef _WARN_GUARD_HPP_
#define _WARN_GUARD_HPP_

#ifdef _MSC_VER
#define DO_PRAGMA(x) __pragma(x)
#else
#define DO_PRAGMA(x) _Pragma(#x)
#endif

//=======================================================
// Clang
//=======================================================
#define CLANG_WARN_GUARD_ON                         \
    DO_PRAGMA(clang diagnostic push)                \
    DO_PRAGMA(clang diagnostic ignored "-Wall")     \
    DO_PRAGMA(clang diagnostic ignored "-Wextra")

#define CLANG_WARN_GUARD_OFF                        \
    DO_PRAGMA(clang diagnostic pop)

//=======================================================
// MSVC
//=======================================================
#define MSVC_WARN_GUARD_ON                          \
    DO_PRAGMA(warning(push, 0))

#define MSVC_WARN_GUARD_OFF                         \
    DO_PRAGMA(warning(pop))

//=======================================================
// Gcc
//=======================================================
#define GCC_WARN_GUARD_ON                           \
    DO_PRAGMA(GCC diagnostic push)                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wabi")                           \
    DO_PRAGMA(GCC diagnostic ignored "-Wabi-tag")                       \
    DO_PRAGMA(GCC diagnostic ignored "-Waddress")                       \
    DO_PRAGMA(GCC diagnostic ignored "-Waggregate-return")              \
    DO_PRAGMA(GCC diagnostic ignored "-Waggressive-loop-optimizations") \
    DO_PRAGMA(GCC diagnostic ignored "-Waliasing")                      \
    DO_PRAGMA(GCC diagnostic ignored "-Walign-commons")                 \
    DO_PRAGMA(GCC diagnostic ignored "-Wall")                           \
    DO_PRAGMA(GCC diagnostic ignored "-Wampersand")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Warray-bounds")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Warray-temporaries")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wassign-intercept")              \
    DO_PRAGMA(GCC diagnostic ignored "-Wattributes")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wbad-function-cast")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wbool-compare")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wbuiltin-macro-redefined")       \
    DO_PRAGMA(GCC diagnostic ignored "-Wc++-compat")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wc++11-compat")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wc++14-compat")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wc-binding-type")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wc90-c99-compat")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wc99-c11-compat")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wcast-align")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wcast-qual")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Wchar-subscripts")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wcharacter-truncation")          \
    DO_PRAGMA(GCC diagnostic ignored "-Wchkp")                          \
    DO_PRAGMA(GCC diagnostic ignored "-Wclobbered")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Wcomment")                       \
    DO_PRAGMA(GCC diagnostic ignored "-Wcompare-reals")                 \
    DO_PRAGMA(GCC diagnostic ignored "-Wconditionally-supported")       \
    DO_PRAGMA(GCC diagnostic ignored "-Wconversion")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wconversion-extra")              \
    DO_PRAGMA(GCC diagnostic ignored "-Wconversion-null")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wcoverage-mismatch")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wcpp")                           \
    DO_PRAGMA(GCC diagnostic ignored "-Wctor-dtor-privacy")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wdate-time")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Wdeclaration-after-statement")   \
    DO_PRAGMA(GCC diagnostic ignored "-Wdelete-incomplete")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wdelete-non-virtual-dtor")       \
    DO_PRAGMA(GCC diagnostic ignored "-Wdeprecated")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wdeprecated-declarations")       \
    DO_PRAGMA(GCC diagnostic ignored "-Wdesignated-init")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wdisabled-optimization")         \
    DO_PRAGMA(GCC diagnostic ignored "-Wdiscarded-array-qualifiers")    \
    DO_PRAGMA(GCC diagnostic ignored "-Wdiscarded-qualifiers")          \
    DO_PRAGMA(GCC diagnostic ignored "-Wdiv-by-zero")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wdouble-promotion")              \
    DO_PRAGMA(GCC diagnostic ignored "-Weffc++")                        \
    DO_PRAGMA(GCC diagnostic ignored "-Wempty-body")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wendif-labels")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wenum-compare")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wextra")                         \
    DO_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wformat")                        \
    DO_PRAGMA(GCC diagnostic ignored "-Wformat-contains-nul")           \
    DO_PRAGMA(GCC diagnostic ignored "-Wformat-extra-args")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wformat-nonliteral")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wformat-security")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wformat-signedness")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wformat-y2k")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wformat-zero-length")            \
    DO_PRAGMA(GCC diagnostic ignored "-Wfree-nonheap-object")           \
    DO_PRAGMA(GCC diagnostic ignored "-Wfunction-elimination")          \
    DO_PRAGMA(GCC diagnostic ignored "-Wignored-qualifiers")            \
    DO_PRAGMA(GCC diagnostic ignored "-Wimplicit")                      \
    DO_PRAGMA(GCC diagnostic ignored "-Wimplicit-function-declaration") \
    DO_PRAGMA(GCC diagnostic ignored "-Wimplicit-int")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wimplicit-interface")            \
    DO_PRAGMA(GCC diagnostic ignored "-Wimplicit-procedure")            \
    DO_PRAGMA(GCC diagnostic ignored "-Wincompatible-pointer-types")    \
    DO_PRAGMA(GCC diagnostic ignored "-Winherited-variadic-ctor")       \
    DO_PRAGMA(GCC diagnostic ignored "-Winit-self")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Winline")                        \
    DO_PRAGMA(GCC diagnostic ignored "-Wint-conversion")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wint-to-pointer-cast")           \
    DO_PRAGMA(GCC diagnostic ignored "-Wintrinsic-shadow")              \
    DO_PRAGMA(GCC diagnostic ignored "-Wintrinsics-std")                \
    DO_PRAGMA(GCC diagnostic ignored "-Winvalid-memory-model")          \
    DO_PRAGMA(GCC diagnostic ignored "-Winvalid-offsetof")              \
    DO_PRAGMA(GCC diagnostic ignored "-Winvalid-pch")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wjump-misses-init")              \
    DO_PRAGMA(GCC diagnostic ignored "-Wlarger-than-")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wline-truncation")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wliteral-suffix")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wlogical-not-parentheses")       \
    DO_PRAGMA(GCC diagnostic ignored "-Wlogical-op")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wlong-long")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Wmain")                          \
    DO_PRAGMA(GCC diagnostic ignored "-Wmaybe-uninitialized")           \
    DO_PRAGMA(GCC diagnostic ignored "-Wmemset-transposed-args")        \
    DO_PRAGMA(GCC diagnostic ignored "-Wmissing-braces")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wmissing-declarations")          \
    DO_PRAGMA(GCC diagnostic ignored "-Wmissing-field-initializers")    \
    DO_PRAGMA(GCC diagnostic ignored "-Wmissing-include-dirs")          \
    DO_PRAGMA(GCC diagnostic ignored "-Wmissing-parameter-type")        \
    DO_PRAGMA(GCC diagnostic ignored "-Wmissing-prototypes")            \
    DO_PRAGMA(GCC diagnostic ignored "-Wmultichar")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Wnarrowing")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Wnested-externs")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wnoexcept")                      \
    DO_PRAGMA(GCC diagnostic ignored "-Wnon-template-friend")           \
    DO_PRAGMA(GCC diagnostic ignored "-Wnon-virtual-dtor")              \
    DO_PRAGMA(GCC diagnostic ignored "-Wnonnull")                       \
    DO_PRAGMA(GCC diagnostic ignored "-Wodr")                           \
    DO_PRAGMA(GCC diagnostic ignored "-Wold-style-cast")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wold-style-declaration")         \
    DO_PRAGMA(GCC diagnostic ignored "-Wold-style-definition")          \
    DO_PRAGMA(GCC diagnostic ignored "-Wopenmp-simd")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Woverflow")                      \
    DO_PRAGMA(GCC diagnostic ignored "-Woverlength-strings")            \
    DO_PRAGMA(GCC diagnostic ignored "-Woverloaded-virtual")            \
    DO_PRAGMA(GCC diagnostic ignored "-Woverride-init")                 \
    DO_PRAGMA(GCC diagnostic ignored "-Wpacked")                        \
    DO_PRAGMA(GCC diagnostic ignored "-Wpacked-bitfield-compat")        \
    DO_PRAGMA(GCC diagnostic ignored "-Wpadded")                        \
    DO_PRAGMA(GCC diagnostic ignored "-Wparentheses")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wpedantic")                      \
    DO_PRAGMA(GCC diagnostic ignored "-Wpedantic-ms-format")            \
    DO_PRAGMA(GCC diagnostic ignored "-Wpmf-conversions")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wpointer-arith")                 \
    DO_PRAGMA(GCC diagnostic ignored "-Wpointer-sign")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wpointer-to-int-cast")           \
    DO_PRAGMA(GCC diagnostic ignored "-Wpragmas")                       \
    DO_PRAGMA(GCC diagnostic ignored "-Wproperty-assign-default")       \
    DO_PRAGMA(GCC diagnostic ignored "-Wprotocol")                      \
    DO_PRAGMA(GCC diagnostic ignored "-Wreal-q-constant")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wrealloc-lhs")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wrealloc-lhs-all")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wredundant-decls")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wreorder")                       \
    DO_PRAGMA(GCC diagnostic ignored "-Wreturn-local-addr")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wreturn-type")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wselector")                      \
    DO_PRAGMA(GCC diagnostic ignored "-Wsequence-point")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wshadow")                        \
    DO_PRAGMA(GCC diagnostic ignored "-Wshadow-ivar")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wshift-count-negative")          \
    DO_PRAGMA(GCC diagnostic ignored "-Wshift-count-overflow")          \
    DO_PRAGMA(GCC diagnostic ignored "-Wsign-compare")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wsign-promo")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wsized-deallocation")            \
    DO_PRAGMA(GCC diagnostic ignored "-Wsizeof-array-argument")         \
    DO_PRAGMA(GCC diagnostic ignored "-Wsizeof-pointer-memaccess")      \
    DO_PRAGMA(GCC diagnostic ignored "-Wstack-protector")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wstrict-aliasing")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wstrict-null-sentinel")          \
    DO_PRAGMA(GCC diagnostic ignored "-Wstrict-overflow")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wstrict-prototypes")             \
    DO_PRAGMA(GCC diagnostic ignored "-Wstrict-selector-match")         \
    DO_PRAGMA(GCC diagnostic ignored "-Wsuggest-final-methods")         \
    DO_PRAGMA(GCC diagnostic ignored "-Wsuggest-final-types")           \
    DO_PRAGMA(GCC diagnostic ignored "-Wsuggest-override")              \
    DO_PRAGMA(GCC diagnostic ignored "-Wsurprising")                    \
    DO_PRAGMA(GCC diagnostic ignored "-Wswitch")                        \
    DO_PRAGMA(GCC diagnostic ignored "-Wswitch-bool")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wswitch-default")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wswitch-enum")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wsync-nand")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Wsystem-headers")                \
    DO_PRAGMA(GCC diagnostic ignored "-Wtabs")                          \
    DO_PRAGMA(GCC diagnostic ignored "-Wtarget-lifetime")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wtraditional")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wtraditional-conversion")        \
    DO_PRAGMA(GCC diagnostic ignored "-Wtrampolines")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wtrigraphs")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Wtype-limits")                   \
    DO_PRAGMA(GCC diagnostic ignored "-Wundeclared-selector")           \
    DO_PRAGMA(GCC diagnostic ignored "-Wundef")                         \
    DO_PRAGMA(GCC diagnostic ignored "-Wunderflow")                     \
    DO_PRAGMA(GCC diagnostic ignored "-Wuninitialized")                 \
    DO_PRAGMA(GCC diagnostic ignored "-Wunknown-pragmas")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wunsafe-loop-optimizations")     \
    DO_PRAGMA(GCC diagnostic ignored "-Wunsuffixed-float-constants")    \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused")                        \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-but-set-parameter")      \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-but-set-variable")       \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-dummy-argument")         \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-function")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-label")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-local-typedefs")         \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-macros")                 \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-parameter")              \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-result")                 \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-value")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wunused-variable")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wuse-without-only")              \
    DO_PRAGMA(GCC diagnostic ignored "-Wuseless-cast")                  \
    DO_PRAGMA(GCC diagnostic ignored "-Wvarargs")                       \
    DO_PRAGMA(GCC diagnostic ignored "-Wvariadic-macros")               \
    DO_PRAGMA(GCC diagnostic ignored "-Wvector-operation-performance")  \
    DO_PRAGMA(GCC diagnostic ignored "-Wvirtual-move-assign")           \
    DO_PRAGMA(GCC diagnostic ignored "-Wvla")                           \
    DO_PRAGMA(GCC diagnostic ignored "-Wvolatile-register-var")         \
    DO_PRAGMA(GCC diagnostic ignored "-Wwrite-strings")                 \
    DO_PRAGMA(GCC diagnostic ignored "-Wzero-as-null-pointer-constant") \
    DO_PRAGMA(GCC diagnostic ignored "-Wzerotrip")                      \
    DO_PRAGMA(GCC diagnostic ignored "-frequire-return-statement")

#define GCC_WARN_GUARD_OFF                          \
    DO_PRAGMA(GCC diagnostic pop)

//=======================================================
// Unknown
//=======================================================
#define UNKNOWN_WARN_GUARD_ON
#define UNKNOWN_WARN_GUARD_OFF

//=======================================================
// All
//=======================================================

#ifdef _MSC_VER
    #define WARN_GUARD_ON  MSVC_WARN_GUARD_ON
    #define WARN_GUARD_OFF MSVC_WARN_GUARD_OFF
#elif __clang__
    #define WARN_GUARD_ON  CLANG_WARN_GUARD_ON
    #define WARN_GUARD_OFF CLANG_WARN_GUARD_OFF
#elif __GNUC__
    #define WARN_GUARD_ON  GCC_WARN_GUARD_ON
    #define WARN_GUARD_OFF GCC_WARN_GUARD_OFF
#else
    #define WARN_GUARD_ON  UNKNOWN_WARN_GUARD_ON
    #define WARN_GUARD_OFF UNKNOWN_WARN_GUARD_OFF
#endif

#endif
<|endoftext|>


<commit_before>/*
 * Example of:
 * (partial) triangle listing
 *
 * A(x,z) :- R(x,y), R(y,z), R(z,x)
 */

// util includes
#include "Tuple.hpp"
#include "relation_IO.hpp"

// graph includes
#include "../graph500/grappa/graph.hpp"
#include "../graph500/generator/make_graph.h"
#include "../graph500/generator/utils.h"
#include "../graph500/prng.h"

#include "../graph500/grappa/graph.hpp"

// Grappa includes
#include <Grappa.hpp>
#include "MatchesDHT.hpp"
#include <Cache.hpp>
#include <ParallelLoop.hpp>
#include <GlobalCompletionEvent.hpp>
#include <AsyncDelegate.hpp>
#include <Statistics.hpp>
#include <FullEmpty.hpp>

// command line parameters

// file input
DEFINE_string( fin, "", "Input file relation" );
DEFINE_uint64( file_num_tuples, 0, "Number of lines in file" );

// generating input data
DEFINE_uint64( scale, 7, "Log of number of vertices" );
DEFINE_uint64( edgefactor, 16, "Median degree to try to generate" );
DEFINE_bool( undirected, false, "Generated graph implies undirected edges" );

DEFINE_bool( print, false, "Print results" );

// outputs
GRAPPA_DEFINE_STAT(SimpleStatistic<double>, query_runtime, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir1_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir2_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir3_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir4_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, results_count, 0);

GRAPPA_DEFINE_STAT(SimpleStatistic<double>, index_runtime, 0);

GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, edges_transfered, 0);

using namespace Grappa;

std::ostream& operator<<( std::ostream& o, const Tuple& t ) {
  o << "T( ";
  for (uint64_t i=0; i<TUPLE_LEN; i++) {
    o << t.columns[i] << ", ";
  }
  o << ")";
}

template< typename T >
inline void print_array(const char * name, GlobalAddress<T> base, size_t nelem, int width = 10, int64_t limit=-1) {
  std::stringstream ss;
  ss << name << ":";
  if (limit<0) {
    limit = nelem;
  } else {
    ss << "(trunc)";
  }

  ss << " [";
  for (size_t i=0; i<limit; i++) {
    if (i % width == 0) ss << "\n";
    ss << " " << delegate::read(base+i);
  }
  ss << " ]"; VLOG(1) << ss.str();
}

GlobalAddress<Graph<Vertex>> E1_index, E2_index, E3_index, E4_index;

void squares( tuple_graph e1,
              tuple_graph e2,
              tuple_graph e3,
              tuple_graph e4 ) {

  on_all_cores( [] { Grappa::Statistics::reset(); } );

  // scan tuples and hash join col 1
  VLOG(1) << "Scan tuples, creating index on subject";

  double start, end;
  start = Grappa_walltime();

  // TODO: building this graph is not necessary for forward nested loop join (just need untimed filtering tuples phase)
  FullEmpty<GlobalAddress<Graph<Vertex>>> f1;
  privateTask( [&f1,e1] {
    f1.writeXF( Graph<Vertex>::create(e1) );
  });
// TODO: the create() calls should be in parallel but,
// create() uses allreduce, which currently requires a static var :(
// Fix with a symmetric alloc in allreduce
  auto l_E1_index = f1.readFE();

  FullEmpty<GlobalAddress<Graph<Vertex>>> f2;
  privateTask( [&f2,e2] {
    f2.writeXF( Graph<Vertex>::create(e2) );
  });
  auto l_E2_index = f2.readFE();

  FullEmpty<GlobalAddress<Graph<Vertex>>> f3;
  privateTask( [&f3,e3] {
    f3.writeXF( Graph<Vertex>::create(e3) );
  });
  auto l_E3_index = f3.readFE();

  FullEmpty<GlobalAddress<Graph<Vertex>>> f4;
  privateTask( [&f4,e4] {
    f4.writeXF( Graph<Vertex>::create(e4) );
  });
  auto l_E4_index = f4.readFE();

  //auto l_E1_index = f1.readFE();
  //auto l_E2_index = f2.readFE();
  //auto l_E3_index = f3.readFE();
  //auto l_E4_index = f4.readFE();

  // broadcast index addresses to all cores
  on_all_cores([=] {
    E1_index = l_E1_index;
    E2_index = l_E2_index;
    E3_index = l_E3_index;
    E4_index = l_E4_index;
  });

  end = Grappa_walltime();

  VLOG(1) << "insertions: " << (e1.nedge+e2.nedge+e3.nedge+e4.nedge)/(end-start) << " per sec";
  index_runtime = end - start;

#if DEBUG
  printAll(E1_index);
#endif

  //
  //TODO: there are plenty of corrections/ optimizations to do here
  // 1. captures by reference in the forall_here bodies
  // 2. moving data that is needed only
  // 3. selection by < degree
  //

  // the forall_localized(forall(...)) here is really just a scan of the E1 edge relation
  forall_localized( E1_index->vs, E1_index->nv, [](int64_t ai, Vertex& a) {
  forall_here_async<&impl::local_gce>( 0, a.nadj, [a,ai](int64_t start, int64_t iters) {
  for ( int64_t i=start; i<start+iters; i++ ) { // forall_here_async serialized for
    auto b_ind = a.local_adj[i];
    auto b_ptr = E2_index->vs + b_ind;
    // lookup b vertex
    remotePrivateTask<&impl::local_gce>(b_ptr.core(), [ai,b_ptr] {
      auto b = *(b_ptr.pointer());
      // forall neighbors of b
      forall_here_async<&impl::local_gce>( 0, b.nadj, [ai,b](int64_t start, int64_t iters) {
      for ( int64_t i=start; i<start+iters; i++ ) { // forall_here_async serialized for
        auto c_ind = b.local_adj[i];
        auto c_ptr = E3_index->vs + c_ind;
        // lookup c vertex
        remotePrivateTask<&impl::local_gce>(c_ptr.core(), [ai,b,c_ptr] {
          auto c = *(c_ptr.pointer());
          // forall neighbors of c
          forall_here_async<&impl::local_gce>( 0, c.nadj, [ai,b,c](int64_t start, int64_t iters) {
          for ( int64_t i=start; i<start+iters; i++ ) { // forall_here_async serialized for
            auto d_ind = c.local_adj[i];
            auto d_ptr = E4_index->vs + d_ind;
            // lookup d vertex
            remotePrivateTask<&impl::local_gce>(d_ptr.core(), [ai,b,c,d_ptr] {
              auto d = *(d_ptr.pointer());
              // forall neighbors of d
              forall_here_async<&impl::local_gce>( 0, d.nadj, [ai,b,c,d](int64_t start, int64_t iters) {
              for ( int64_t i=start; i<start+iters; i++ ) { //forall_here_async serialized
                auto aprime = d.local_adj[i];
                // check if the a's match
                if ( aprime == ai ) {
                  results_count++;
                }
              }}); // over d->a
            }); // lookup d
          }}); // over c->d
        }); // lookup c
      }}); // over b->c
    }); // lookup b
  }});}); // over a->b

  end = Grappa_walltime();
  query_runtime = end-start;

  Grappa::Statistics::merge_and_print();

  //VLOG(1) << "joins: " << (end-start) << " seconds; total_results_count=" << total_results_count << "; total_ir1_count=" << total_first_join_results << "; total_ir3_count=" << total_second_join_results;
}

void user_main( int * ignore ) {

  int64_t nvtx_scale = ((int64_t)1)<<FLAGS_scale;
	int64_t desired_nedge = nvtx_scale * FLAGS_edgefactor;

  LOG(INFO) << "scale = " << FLAGS_scale << ", NV = " << nvtx_scale << ", NE = " << desired_nedge;

  // make raw graph edge tuples
  double t;
  tuple_graph tg;
  tg.edges = global_alloc<packed_edge>(desired_nedge);
  LOG(INFO) << "graph generation...";
  t = walltime();
  make_graph( FLAGS_scale, desired_nedge, userseed, userseed, &tg.nedge, &tg.edges );
  double generation_time = walltime() - t;
  LOG(INFO) << "graph_generation: " << generation_time;

  squares( tg, tg, tg, tg );
}

/// Main() entry
int main (int argc, char** argv) {
    Grappa_init( &argc, &argv );
    Grappa_activate();

    Grappa_run_user_main( &user_main, (int*)NULL );
    CHECK( Grappa_done() == true ) << "Grappa not done before scheduler exit";
    Grappa_finish( 0 );
}

<commit_msg>intermediate results for squares<commit_after>/*
 * Example of:
 * (partial) triangle listing
 *
 * A(x,z) :- R(x,y), R(y,z), R(z,x)
 */

// util includes
#include "Tuple.hpp"
#include "relation_IO.hpp"

// graph includes
#include "../graph500/grappa/graph.hpp"
#include "../graph500/generator/make_graph.h"
#include "../graph500/generator/utils.h"
#include "../graph500/prng.h"

#include "../graph500/grappa/graph.hpp"

// Grappa includes
#include <Grappa.hpp>
#include "MatchesDHT.hpp"
#include <Cache.hpp>
#include <ParallelLoop.hpp>
#include <GlobalCompletionEvent.hpp>
#include <AsyncDelegate.hpp>
#include <Statistics.hpp>
#include <FullEmpty.hpp>

// command line parameters

// file input
//DEFINE_string( fin, "", "Input file relation" );
//DEFINE_uint64( file_num_tuples, 0, "Number of lines in file" );

// generating input data
DEFINE_uint64( scale, 7, "Log of number of vertices" );
DEFINE_uint64( edgefactor, 16, "Median degree to try to generate" );
//DEFINE_bool( undirected, false, "Generated graph implies undirected edges" );

DEFINE_bool( print, false, "Print results" );

// outputs
GRAPPA_DEFINE_STAT(SimpleStatistic<double>, query_runtime, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir1_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir2_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir3_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir4_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir5_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir6_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, ir7_count, 0);
GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, results_count, 0);

GRAPPA_DEFINE_STAT(SimpleStatistic<double>, index_runtime, 0);

GRAPPA_DEFINE_STAT(SimpleStatistic<uint64_t>, edges_transfered, 0);

using namespace Grappa;

std::ostream& operator<<( std::ostream& o, const Tuple& t ) {
  o << "T( ";
  for (uint64_t i=0; i<TUPLE_LEN; i++) {
    o << t.columns[i] << ", ";
  }
  o << ")";
}

template< typename T >
inline void print_array(const char * name, GlobalAddress<T> base, size_t nelem, int width = 10, int64_t limit=-1) {
  std::stringstream ss;
  ss << name << ":";
  if (limit<0) {
    limit = nelem;
  } else {
    ss << "(trunc)";
  }

  ss << " [";
  for (size_t i=0; i<limit; i++) {
    if (i % width == 0) ss << "\n";
    ss << " " << delegate::read(base+i);
  }
  ss << " ]"; VLOG(1) << ss.str();
}

GlobalAddress<Graph<Vertex>> E1_index, E2_index, E3_index, E4_index;

void squares( tuple_graph e1,
              tuple_graph e2,
              tuple_graph e3,
              tuple_graph e4 ) {

  on_all_cores( [] { Grappa::Statistics::reset(); } );

  // scan tuples and hash join col 1
  VLOG(1) << "Scan tuples, creating index on subject";

  double start, end;
  start = Grappa_walltime();

  // TODO: building this graph is not necessary for forward nested loop join (just need untimed filtering tuples phase)
  FullEmpty<GlobalAddress<Graph<Vertex>>> f1;
  privateTask( [&f1,e1] {
    f1.writeXF( Graph<Vertex>::create(e1) );
  });
// TODO: the create() calls should be in parallel but,
// create() uses allreduce, which currently requires a static var :(
// Fix with a symmetric alloc in allreduce
  auto l_E1_index = f1.readFE();

  FullEmpty<GlobalAddress<Graph<Vertex>>> f2;
  privateTask( [&f2,e2] {
    f2.writeXF( Graph<Vertex>::create(e2) );
  });
  auto l_E2_index = f2.readFE();

  FullEmpty<GlobalAddress<Graph<Vertex>>> f3;
  privateTask( [&f3,e3] {
    f3.writeXF( Graph<Vertex>::create(e3) );
  });
  auto l_E3_index = f3.readFE();

  FullEmpty<GlobalAddress<Graph<Vertex>>> f4;
  privateTask( [&f4,e4] {
    f4.writeXF( Graph<Vertex>::create(e4) );
  });
  auto l_E4_index = f4.readFE();

  //auto l_E1_index = f1.readFE();
  //auto l_E2_index = f2.readFE();
  //auto l_E3_index = f3.readFE();
  //auto l_E4_index = f4.readFE();

  // broadcast index addresses to all cores
  on_all_cores([=] {
    E1_index = l_E1_index;
    E2_index = l_E2_index;
    E3_index = l_E3_index;
    E4_index = l_E4_index;
  });

  end = Grappa_walltime();

  VLOG(1) << "insertions: " << (e1.nedge+e2.nedge+e3.nedge+e4.nedge)/(end-start) << " per sec";
  index_runtime = end - start;

#if DEBUG
  printAll(E1_index);
#endif

  //
  //TODO: there are plenty of corrections/ optimizations to do here
  // 1. captures by reference in the forall_here bodies
  // 2. moving data that is needed only
  // 3. selection by < degree
  //

  // the forall_localized(forall(...)) here is really just a scan of the E1 edge relation
  forall_localized( E1_index->vs, E1_index->nv, [](int64_t ai, Vertex& a) {
  forall_here_async<&impl::local_gce>( 0, a.nadj, [a,ai](int64_t start, int64_t iters) {
  for ( int64_t i=start; i<start+iters; i++ ) { // forall_here_async serialized for
    ir1_count++; // count(E1)
    auto b_ind = a.local_adj[i];
    auto b_ptr = E2_index->vs + b_ind;
    // lookup b vertex
    remotePrivateTask<&impl::local_gce>(b_ptr.core(), [ai,b_ptr] {
      auto b = *(b_ptr.pointer());
      ir2_count += b.nadj; // count(E1xE2)
      // forall neighbors of b
      forall_here_async<&impl::local_gce>( 0, b.nadj, [ai,b](int64_t start, int64_t iters) {
      for ( int64_t i=start; i<start+iters; i++ ) { // forall_here_async serialized for
        auto c_ind = b.local_adj[i];
        auto c_ptr = E3_index->vs + c_ind;
        // lookup c vertex
        remotePrivateTask<&impl::local_gce>(c_ptr.core(), [ai,b,c_ptr] {
          auto c = *(c_ptr.pointer());
          ir4_count += b.nadj; // count(E1xE2xE3)
          // forall neighbors of c
          forall_here_async<&impl::local_gce>( 0, c.nadj, [ai,b,c](int64_t start, int64_t iters) {
          for ( int64_t i=start; i<start+iters; i++ ) { // forall_here_async serialized for
            auto d_ind = c.local_adj[i];
            auto d_ptr = E4_index->vs + d_ind;
            // lookup d vertex
            remotePrivateTask<&impl::local_gce>(d_ptr.core(), [ai,b,c,d_ptr] {
              auto d = *(d_ptr.pointer());
              // forall neighbors of d
              ir6_count += d.nadj; // count(E1xE2xE3xE4)
              forall_here_async<&impl::local_gce>( 0, d.nadj, [ai,b,c,d](int64_t start, int64_t iters) {
              for ( int64_t i=start; i<start+iters; i++ ) { //forall_here_async serialized
                auto aprime = d.local_adj[i];
                // check if the a's match
                if ( aprime == ai ) {
                  results_count++;
                }
              }}); // over d->a
            }); // lookup d
          }}); // over c->d
        }); // lookup c
      }}); // over b->c
    }); // lookup b
  }});}); // over a->b

  end = Grappa_walltime();
  query_runtime = end-start;

  Grappa::Statistics::merge_and_print();

  //VLOG(1) << "joins: " << (end-start) << " seconds; total_results_count=" << total_results_count << "; total_ir1_count=" << total_first_join_results << "; total_ir3_count=" << total_second_join_results;
}

void user_main( int * ignore ) {

  int64_t nvtx_scale = ((int64_t)1)<<FLAGS_scale;
	int64_t desired_nedge = nvtx_scale * FLAGS_edgefactor;

  LOG(INFO) << "scale = " << FLAGS_scale << ", NV = " << nvtx_scale << ", NE = " << desired_nedge;

  // make raw graph edge tuples
  double t;
  tuple_graph tg;
  tg.edges = global_alloc<packed_edge>(desired_nedge);
  LOG(INFO) << "graph generation...";
  t = walltime();
  make_graph( FLAGS_scale, desired_nedge, userseed, userseed, &tg.nedge, &tg.edges );
  double generation_time = walltime() - t;
  LOG(INFO) << "graph_generation: " << generation_time;

  squares( tg, tg, tg, tg );
}

/// Main() entry
int main (int argc, char** argv) {
    Grappa_init( &argc, &argv );
    Grappa_activate();

    Grappa_run_user_main( &user_main, (int*)NULL );
    CHECK( Grappa_done() == true ) << "Grappa not done before scheduler exit";
    Grappa_finish( 0 );
}

<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2017, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder 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 HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements source address match controller.
 */

#define WPP_NAME "src_match_controller.tmh"

#include <common/code_utils.hpp>
#include <common/debug.hpp>
#include <common/logging.hpp>
#include <thread/mesh_forwarder.hpp>
#include <thread/src_match_controller.hpp>
#include <thread/thread_netif.hpp>

namespace Thread {

SourceMatchController::SourceMatchController(MeshForwarder &aMeshForwarder) :
    mMeshForwarder(aMeshForwarder),
    mEnabled(false)
{
    ClearTable();
}

otInstance *SourceMatchController::GetInstance(void)
{
    return mMeshForwarder.GetInstance();
}

void SourceMatchController::IncrementMessageCount(Child &aChild)
{
    aChild.IncrementIndirectMessageCount();

    if (aChild.GetIndirectMessageCount() == 0)
    {
        AddEntry(aChild);
    }
}

void SourceMatchController::DecrementMessageCount(Child &aChild)
{
    if (aChild.GetIndirectMessageCount() == 0)
    {
        otLogWarnMac(GetInstance(), "DecrementMessageCount(child 0x%04x) called when already at zero count.",
                     aChild.GetRloc16());
        ExitNow();
    }

    aChild.DecrementIndirectMessageCount();

    if (aChild.GetIndirectMessageCount() == 0)
    {
        ClearEntry(aChild);
    }

exit:
    return;
}

void SourceMatchController::ResetMessageCount(Child &aChild)
{
    aChild.ResetIndirectMessageCount();
    ClearEntry(aChild);
}

void SourceMatchController::SetSrcMatchAsShort(Child &aChild, bool aUseShortAddress)
{
    VerifyOrExit(aChild.mUseShortAddress != aUseShortAddress);

    if (aChild.GetIndirectMessageCount() > 0)
    {
        ClearEntry(aChild);
        aChild.mUseShortAddress = aUseShortAddress;
        AddEntry(aChild);
    }
    else
    {
        aChild.mUseShortAddress = aUseShortAddress;
    }

exit:
    return;
}

void SourceMatchController::ClearTable(void)
{
    otPlatRadioClearSrcMatchShortEntries(GetInstance());
    otPlatRadioClearSrcMatchExtEntries(GetInstance());
    otLogDebgMac(GetInstance(), "SrcAddrMatch - Cleared all entries");
}

void SourceMatchController::Enable(bool aEnable)
{
    mEnabled = aEnable;
    otPlatRadioEnableSrcMatch(GetInstance(), mEnabled);
    otLogDebgMac(GetInstance(), "SrcAddrMatch - %sabling", mEnabled ? "En" : "Dis");
}

void SourceMatchController::AddEntry(Child &aChild)
{
    aChild.mSourceMatchPending = true;

    if (!IsEnabled())
    {
        SuccessOrExit(AddPendingEntries());
        Enable(true);
    }
    else
    {
        VerifyOrExit(AddAddress(aChild) == kThreadError_None, Enable(false));
        aChild.mSourceMatchPending = false;
    }

exit:
    return;
}

ThreadError SourceMatchController::AddAddress(const Child &aChild)
{
    ThreadError error = kThreadError_None;

    if (aChild.mUseShortAddress)
    {
        error = otPlatRadioAddSrcMatchShortEntry(GetInstance(), aChild.GetRloc16());

        otLogDebgMac(GetInstance(), "SrcAddrMatch - Adding short addr: 0x%04x -- %s (%d)",
                     aChild.GetRloc16(), otThreadErrorToString(error), error);
    }
    else
    {
        uint8_t addr[sizeof(aChild.GetExtAddress())];

        for (uint8_t i = 0; i < sizeof(addr); i++)
        {
            addr[i] = aChild.GetExtAddress().m8[sizeof(addr) - 1 - i];
        }

        error = otPlatRadioAddSrcMatchExtEntry(GetInstance(), addr);

        otLogDebgMac(GetInstance(), "SrcAddrMatch - Adding addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x -- %s (%d)",
                     addr[7], addr[6], addr[5], addr[4], addr[3], addr[2], addr[1], addr[0],
                     otThreadErrorToString(error), error);
    }

    return error;
}

void SourceMatchController::ClearEntry(Child &aChild)
{
    ThreadError error = kThreadError_None;

    if (aChild.mSourceMatchPending)
    {
        otLogDebgMac(GetInstance(), "SrcAddrMatch - Clearing pending flag for 0x%04x", aChild.GetRloc16());
        aChild.mSourceMatchPending = false;
        ExitNow();
    }

    if (aChild.mUseShortAddress)
    {
        error = otPlatRadioClearSrcMatchShortEntry(GetInstance(), aChild.GetRloc16());

        otLogDebgMac(GetInstance(), "SrcAddrMatch - Clearing short address: 0x%04x -- %s (%d)",
                     aChild.GetRloc16(), otThreadErrorToString(error), error);
    }
    else
    {
        uint8_t addr[sizeof(aChild.GetExtAddress())];

        for (uint8_t i = 0; i < sizeof(addr); i++)
        {
            addr[i] = aChild.GetExtAddress().m8[sizeof(aChild.GetExtAddress()) - 1 - i];
        }

        error = otPlatRadioClearSrcMatchExtEntry(GetInstance(), addr);

        otLogDebgMac(GetInstance(), "SrcAddrMatch - Clearing addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x -- %s (%d)",
                     addr[7], addr[6], addr[5], addr[4], addr[3], addr[2], addr[1], addr[0],
                     otThreadErrorToString(error), error);
    }

    SuccessOrExit(error);

    if (!IsEnabled())
    {
        SuccessOrExit(AddPendingEntries());
        Enable(true);
    }

exit:
    return;
}

ThreadError SourceMatchController::AddPendingEntries(void)
{
    ThreadError error = kThreadError_None;
    uint8_t numChildren;
    Child *child;

    child = mMeshForwarder.GetNetif().GetMle().GetChildren(&numChildren);

    for (uint8_t i = 0; i < numChildren; i++, child++)
    {
        if (child->IsStateValidOrRestoring() && child->mSourceMatchPending)
        {
            SuccessOrExit(AddAddress(*child));
            child->mSourceMatchPending = false;
        }
    }

exit:
    return error;
}

}  // namespace Thread
<commit_msg>Fix incorrect logic in IncrementMessageCount() method (#1589)<commit_after>/*
 *  Copyright (c) 2017, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder 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 HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements source address match controller.
 */

#define WPP_NAME "src_match_controller.tmh"

#include <common/code_utils.hpp>
#include <common/debug.hpp>
#include <common/logging.hpp>
#include <thread/mesh_forwarder.hpp>
#include <thread/src_match_controller.hpp>
#include <thread/thread_netif.hpp>

namespace Thread {

SourceMatchController::SourceMatchController(MeshForwarder &aMeshForwarder) :
    mMeshForwarder(aMeshForwarder),
    mEnabled(false)
{
    ClearTable();
}

otInstance *SourceMatchController::GetInstance(void)
{
    return mMeshForwarder.GetInstance();
}

void SourceMatchController::IncrementMessageCount(Child &aChild)
{
    if (aChild.GetIndirectMessageCount() == 0)
    {
        AddEntry(aChild);
    }

    aChild.IncrementIndirectMessageCount();
}

void SourceMatchController::DecrementMessageCount(Child &aChild)
{
    if (aChild.GetIndirectMessageCount() == 0)
    {
        otLogWarnMac(GetInstance(), "DecrementMessageCount(child 0x%04x) called when already at zero count.",
                     aChild.GetRloc16());
        ExitNow();
    }

    aChild.DecrementIndirectMessageCount();

    if (aChild.GetIndirectMessageCount() == 0)
    {
        ClearEntry(aChild);
    }

exit:
    return;
}

void SourceMatchController::ResetMessageCount(Child &aChild)
{
    aChild.ResetIndirectMessageCount();
    ClearEntry(aChild);
}

void SourceMatchController::SetSrcMatchAsShort(Child &aChild, bool aUseShortAddress)
{
    VerifyOrExit(aChild.mUseShortAddress != aUseShortAddress);

    if (aChild.GetIndirectMessageCount() > 0)
    {
        ClearEntry(aChild);
        aChild.mUseShortAddress = aUseShortAddress;
        AddEntry(aChild);
    }
    else
    {
        aChild.mUseShortAddress = aUseShortAddress;
    }

exit:
    return;
}

void SourceMatchController::ClearTable(void)
{
    otPlatRadioClearSrcMatchShortEntries(GetInstance());
    otPlatRadioClearSrcMatchExtEntries(GetInstance());
    otLogDebgMac(GetInstance(), "SrcAddrMatch - Cleared all entries");
}

void SourceMatchController::Enable(bool aEnable)
{
    mEnabled = aEnable;
    otPlatRadioEnableSrcMatch(GetInstance(), mEnabled);
    otLogDebgMac(GetInstance(), "SrcAddrMatch - %sabling", mEnabled ? "En" : "Dis");
}

void SourceMatchController::AddEntry(Child &aChild)
{
    aChild.mSourceMatchPending = true;

    if (!IsEnabled())
    {
        SuccessOrExit(AddPendingEntries());
        Enable(true);
    }
    else
    {
        VerifyOrExit(AddAddress(aChild) == kThreadError_None, Enable(false));
        aChild.mSourceMatchPending = false;
    }

exit:
    return;
}

ThreadError SourceMatchController::AddAddress(const Child &aChild)
{
    ThreadError error = kThreadError_None;

    if (aChild.mUseShortAddress)
    {
        error = otPlatRadioAddSrcMatchShortEntry(GetInstance(), aChild.GetRloc16());

        otLogDebgMac(GetInstance(), "SrcAddrMatch - Adding short addr: 0x%04x -- %s (%d)",
                     aChild.GetRloc16(), otThreadErrorToString(error), error);
    }
    else
    {
        uint8_t addr[sizeof(aChild.GetExtAddress())];

        for (uint8_t i = 0; i < sizeof(addr); i++)
        {
            addr[i] = aChild.GetExtAddress().m8[sizeof(addr) - 1 - i];
        }

        error = otPlatRadioAddSrcMatchExtEntry(GetInstance(), addr);

        otLogDebgMac(GetInstance(), "SrcAddrMatch - Adding addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x -- %s (%d)",
                     addr[7], addr[6], addr[5], addr[4], addr[3], addr[2], addr[1], addr[0],
                     otThreadErrorToString(error), error);
    }

    return error;
}

void SourceMatchController::ClearEntry(Child &aChild)
{
    ThreadError error = kThreadError_None;

    if (aChild.mSourceMatchPending)
    {
        otLogDebgMac(GetInstance(), "SrcAddrMatch - Clearing pending flag for 0x%04x", aChild.GetRloc16());
        aChild.mSourceMatchPending = false;
        ExitNow();
    }

    if (aChild.mUseShortAddress)
    {
        error = otPlatRadioClearSrcMatchShortEntry(GetInstance(), aChild.GetRloc16());

        otLogDebgMac(GetInstance(), "SrcAddrMatch - Clearing short address: 0x%04x -- %s (%d)",
                     aChild.GetRloc16(), otThreadErrorToString(error), error);
    }
    else
    {
        uint8_t addr[sizeof(aChild.GetExtAddress())];

        for (uint8_t i = 0; i < sizeof(addr); i++)
        {
            addr[i] = aChild.GetExtAddress().m8[sizeof(aChild.GetExtAddress()) - 1 - i];
        }

        error = otPlatRadioClearSrcMatchExtEntry(GetInstance(), addr);

        otLogDebgMac(GetInstance(), "SrcAddrMatch - Clearing addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x -- %s (%d)",
                     addr[7], addr[6], addr[5], addr[4], addr[3], addr[2], addr[1], addr[0],
                     otThreadErrorToString(error), error);
    }

    SuccessOrExit(error);

    if (!IsEnabled())
    {
        SuccessOrExit(AddPendingEntries());
        Enable(true);
    }

exit:
    return;
}

ThreadError SourceMatchController::AddPendingEntries(void)
{
    ThreadError error = kThreadError_None;
    uint8_t numChildren;
    Child *child;

    child = mMeshForwarder.GetNetif().GetMle().GetChildren(&numChildren);

    for (uint8_t i = 0; i < numChildren; i++, child++)
    {
        if (child->IsStateValidOrRestoring() && child->mSourceMatchPending)
        {
            SuccessOrExit(AddAddress(*child));
            child->mSourceMatchPending = false;
        }
    }

exit:
    return error;
}

}  // namespace Thread
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mapplicationpage.h"
#include "mapplicationpage_p.h"
#include "mapplicationpagemodel.h"
#include "mapplicationwindow.h"
#include "mwidgetview.h"
#include "mondisplaychangeevent.h"
#include "mwidgetcreator.h"
#include "mpannableviewport.h"

#include <QAction>
#include <QGraphicsLinearLayout>

M_REGISTER_WIDGET(MApplicationPage)

MApplicationPagePrivate::MApplicationPagePrivate() :
    pannableViewport(0),
    panDirection(0),
    contentCreated(false)
{}

void MApplicationPagePrivate::init()
{
    Q_Q(MApplicationPage);

    QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0.0);

    pannableViewport = new MPannableViewport;
    pannableViewport->setClipping(false);
    panDirection = pannableViewport->panDirection();

    layout->addItem(pannableViewport);

    q->setLayout(layout);

    q->connect(q,
               SIGNAL(sceneWindowStateChanged(MSceneWindow::SceneWindowState,
                                              MSceneWindow::SceneWindowState)),
               SLOT(_q_onSceneWindowStateChanged(MSceneWindow::SceneWindowState,
                                                 MSceneWindow::SceneWindowState)));
}

void MApplicationPagePrivate::_q_onCentralWidgetDestroyed()
{
    Q_Q(MApplicationPage);
    q->model()->setCentralWidget(0);
}

void MApplicationPagePrivate::_q_onSceneWindowStateChanged(
        MSceneWindow::SceneWindowState newState, MSceneWindow::SceneWindowState oldState)
{
    Q_Q(MApplicationPage);

    if (oldState == MSceneWindow::Disappeared &&
            (newState == MSceneWindow::Appearing || newState == MSceneWindow::Appeared)) {

        if (!contentCreated) {
            contentCreated = true;
            q->createContent();
        }
    }
}

MApplicationPage::MApplicationPage(QGraphicsItem *parent)
    : MSceneWindow(new MApplicationPagePrivate, new MApplicationPageModel,
                     MSceneWindow::ApplicationPage, QString(), parent)
{
    Q_D(MApplicationPage);

    d->init();
}

MApplicationPage::~MApplicationPage()
{
    Q_D(MApplicationPage);
    setCentralWidget(0);

    // If the application quits while this page is being displayed, it might happen
    // that MNavigationBar gets destroyed before this page. In that case, since
    // the custom content will be a child of MNavigationBar in the scene graph, it
    // could have been detroyed along with it.
    // Therefore, we only delete the custom content if we still have it.
    if (!d->customNavigationBarContent.isNull()) {
        delete d->customNavigationBarContent.data();
        d->customNavigationBarContent.clear();
    }
}

void MApplicationPage::setCentralWidget(QGraphicsWidget *centralWidget)
{
    if (model()->centralWidget())
        delete model()->centralWidget();

    model()->setCentralWidget(centralWidget);

    if (centralWidget)
        connect(centralWidget, SIGNAL(destroyed()), SLOT(_q_onCentralWidgetDestroyed()));
}

QGraphicsWidget *MApplicationPage::centralWidget()
{
    return model()->centralWidget();
}

MApplicationWindow *MApplicationPage::applicationWindow()
{
    MApplicationWindow *applicationWindow = 0;

    if (scene() != 0) {
        QList<QGraphicsView *> viewsList = scene()->views();
        int i = 0;

        while (applicationWindow == 0 && i < viewsList.count()) {

            applicationWindow = qobject_cast<MApplicationWindow *>(viewsList[i]);
            ++i;
        }
    }

    return applicationWindow;
}

const QString MApplicationPage::title() const
{
    return model()->title();
}

void MApplicationPage::setTitle(const QString &title)
{
    model()->setTitle(title);
}

void MApplicationPage::createContent()
{
    Q_D(MApplicationPage);

    d->contentCreated = true;
}

bool MApplicationPage::isContentCreated() const
{
    Q_D(const MApplicationPage);

    return d->contentCreated;
}

void MApplicationPage::setRememberPosition(bool remember)
{
    model()->setRememberPosition(remember);
}

bool MApplicationPage::rememberPosition() const
{
    return model()->rememberPosition();
}

void MApplicationPage::setPannable(bool pannable)
{
    Q_D(MApplicationPage);

    if (pannable)
        d->pannableViewport->setPanDirection(d->panDirection);
    else
        d->pannableViewport->setPanDirection(0);
}

bool MApplicationPage::isPannable() const
{
    Q_D(const MApplicationPage);

    return d->pannableViewport->panDirection() != 0;
}

void MApplicationPage::setPanningDirection(Qt::Orientations direction)
{
    Q_D(MApplicationPage);

    d->panDirection = direction;
    d->pannableViewport->setPanDirection(direction);
}

Qt::Orientations MApplicationPage::panningDirection() const
{
    Q_D(const MApplicationPage);

    return d->pannableViewport->panDirection();
}

void MApplicationPage::actionEvent(QActionEvent *e)
{
    switch (e->type()) {
    case QEvent::ActionRemoved:
    case QEvent::ActionChanged:
    case QEvent::ActionAdded: {
        emit actionUpdated(e);
        break;
    }
    default: {
        break;
    }
    }
}

void MApplicationPage::enterDisplayEvent()
{
    MSceneWindow::enterDisplayEvent();
}

void MApplicationPagePrivate::doEnterDisplayEvent()
{
    Q_Q(MApplicationPage);

    if (!contentCreated) {
        contentCreated = true;
        q->createContent();
    }

    MWidgetPrivate::doEnterDisplayEvent();
}

void MApplicationPagePrivate::setExposedContentRect(const QRectF &exposedContentRect)
{
    Q_Q(MApplicationPage);

    if (exposedContentRect != q->model()->exposedContentRect()) {
        q->model()->setExposedContentRect(exposedContentRect);
        emit q->exposedContentRectChanged();
    }
}

QRectF MApplicationPage::exposedContentRect() const
{
    return model()->exposedContentRect();
}

MApplicationPageModel::ComponentDisplayMode MApplicationPage::componentDisplayMode(
    Component component) const
{
    MApplicationPageModel::ComponentDisplayMode displayMode;

    switch (component) {
    case NavigationBar:
        displayMode = model()->navigationBarDisplayMode();
        break;

    case HomeButton:
        displayMode = model()->homeButtonDisplayMode();
        break;

    case EscapeButton:
        displayMode = model()->escapeButtonDisplayMode();
        break;

    default: // StatusBar
        displayMode = model()->statusBarDisplayMode();
    };

    return displayMode;
}

void MApplicationPage::setComponentsDisplayMode(Components components,
        MApplicationPageModel::ComponentDisplayMode displayMode)
{
    if (components.testFlag(NavigationBar)) {
        model()->setNavigationBarDisplayMode(displayMode);
    }

    if (components.testFlag(HomeButton)) {
        model()->setHomeButtonDisplayMode(displayMode);
    }

    if (components.testFlag(EscapeButton)) {
        model()->setEscapeButtonDisplayMode(displayMode);
    }

    if (components.testFlag(StatusBar)) {
        model()->setStatusBarDisplayMode(displayMode);
    }
}

bool MApplicationPage::isProgressIndicatorVisible() const
{
    return model()->progressIndicatorVisible();
}

void MApplicationPage::setProgressIndicatorVisible(bool visible)
{
    model()->setProgressIndicatorVisible(visible);
}

void MApplicationPage::setAutoMarginsForComponentsEnabled(bool enabled)
{
    model()->setAutoMarginsForComponentsEnabled(enabled);
}

bool MApplicationPage::autoMarginsForComponentsEnabled() const
{
    return model()->autoMarginsForComponentsEnabled();
}

MApplicationPageModel::PageEscapeMode MApplicationPage::escapeMode() const
{
    return model()->escapeMode();
}

void MApplicationPage::setEscapeMode(MApplicationPageModel::PageEscapeMode mode)
{
    model()->setEscapeMode(mode);
}

MPannableViewport * MApplicationPage::pannableViewport()
{
    Q_D(MApplicationPage);

    return d->pannableViewport;
}

void MApplicationPage::setCustomNavigationBarContent(QGraphicsWidget *customNavigationBarContent)
{
    Q_D(MApplicationPage);
    QGraphicsWidget *oldCustomNavigationBarContent = 0;

    if (customNavigationBarContent == d->customNavigationBarContent.data())
        return;

    oldCustomNavigationBarContent = d->customNavigationBarContent.data();

    d->customNavigationBarContent = customNavigationBarContent;

    // Let MApplicationWindow remove this content from the navigation bar
    emit customNavigationBarContentChanged();

    if (oldCustomNavigationBarContent)
        delete oldCustomNavigationBarContent;
}

QGraphicsWidget *MApplicationPage::customNavigationBarContent()
{
    Q_D(MApplicationPage);
    return d->customNavigationBarContent.data();
}

#include "moc_mapplicationpage.cpp"
<commit_msg>Fixes: NB#273218 - Toolbar is not displayed on tapping in the viewer view<commit_after>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mapplicationpage.h"
#include "mapplicationpage_p.h"
#include "mapplicationpagemodel.h"
#include "mapplicationwindow.h"
#include "mwidgetview.h"
#include "mondisplaychangeevent.h"
#include "mwidgetcreator.h"
#include "mpannableviewport.h"
#include "mdebug.h"

#include <QAction>
#include <QGraphicsLinearLayout>

M_REGISTER_WIDGET(MApplicationPage)

MApplicationPagePrivate::MApplicationPagePrivate() :
    pannableViewport(0),
    panDirection(0),
    contentCreated(false)
{}

void MApplicationPagePrivate::init()
{
    Q_Q(MApplicationPage);

    QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0.0);

    pannableViewport = new MPannableViewport;
    pannableViewport->setClipping(false);
    panDirection = pannableViewport->panDirection();

    layout->addItem(pannableViewport);

    q->setLayout(layout);

    q->connect(q,
               SIGNAL(sceneWindowStateChanged(MSceneWindow::SceneWindowState,
                                              MSceneWindow::SceneWindowState)),
               SLOT(_q_onSceneWindowStateChanged(MSceneWindow::SceneWindowState,
                                                 MSceneWindow::SceneWindowState)));
}

void MApplicationPagePrivate::_q_onCentralWidgetDestroyed()
{
    Q_Q(MApplicationPage);
    q->model()->setCentralWidget(0);
}

void MApplicationPagePrivate::_q_onSceneWindowStateChanged(
        MSceneWindow::SceneWindowState newState, MSceneWindow::SceneWindowState oldState)
{
    Q_Q(MApplicationPage);

    if (oldState == MSceneWindow::Disappeared &&
            (newState == MSceneWindow::Appearing || newState == MSceneWindow::Appeared)) {

        if (!contentCreated) {
            contentCreated = true;
            q->createContent();
        }
    }
}

MApplicationPage::MApplicationPage(QGraphicsItem *parent)
    : MSceneWindow(new MApplicationPagePrivate, new MApplicationPageModel,
                     MSceneWindow::ApplicationPage, QString(), parent)
{
    Q_D(MApplicationPage);

    d->init();
}

MApplicationPage::~MApplicationPage()
{
    Q_D(MApplicationPage);
    setCentralWidget(0);

    // If the application quits while this page is being displayed, it might happen
    // that MNavigationBar gets destroyed before this page. In that case, since
    // the custom content will be a child of MNavigationBar in the scene graph, it
    // could have been detroyed along with it.
    // Therefore, we only delete the custom content if we still have it.
    if (!d->customNavigationBarContent.isNull()) {
        delete d->customNavigationBarContent.data();
        d->customNavigationBarContent.clear();
    }
}

void MApplicationPage::setCentralWidget(QGraphicsWidget *centralWidget)
{
    if (model()->centralWidget())
        delete model()->centralWidget();

    model()->setCentralWidget(centralWidget);

    if (centralWidget)
        connect(centralWidget, SIGNAL(destroyed()), SLOT(_q_onCentralWidgetDestroyed()));
}

QGraphicsWidget *MApplicationPage::centralWidget()
{
    return model()->centralWidget();
}

MApplicationWindow *MApplicationPage::applicationWindow()
{
    MApplicationWindow *applicationWindow = 0;

    if (scene() != 0) {
        QList<QGraphicsView *> viewsList = scene()->views();
        int i = 0;

        while (applicationWindow == 0 && i < viewsList.count()) {

            applicationWindow = qobject_cast<MApplicationWindow *>(viewsList[i]);
            ++i;
        }
    }

    return applicationWindow;
}

const QString MApplicationPage::title() const
{
    return model()->title();
}

void MApplicationPage::setTitle(const QString &title)
{
    model()->setTitle(title);
}

void MApplicationPage::createContent()
{
    Q_D(MApplicationPage);

    d->contentCreated = true;
}

bool MApplicationPage::isContentCreated() const
{
    Q_D(const MApplicationPage);

    return d->contentCreated;
}

void MApplicationPage::setRememberPosition(bool remember)
{
    model()->setRememberPosition(remember);
}

bool MApplicationPage::rememberPosition() const
{
    return model()->rememberPosition();
}

void MApplicationPage::setPannable(bool pannable)
{
    Q_D(MApplicationPage);

    if (pannable)
        d->pannableViewport->setPanDirection(d->panDirection);
    else
        d->pannableViewport->setPanDirection(0);
}

bool MApplicationPage::isPannable() const
{
    Q_D(const MApplicationPage);

    return d->pannableViewport->panDirection() != 0;
}

void MApplicationPage::setPanningDirection(Qt::Orientations direction)
{
    Q_D(MApplicationPage);

    d->panDirection = direction;
    d->pannableViewport->setPanDirection(direction);
}

Qt::Orientations MApplicationPage::panningDirection() const
{
    Q_D(const MApplicationPage);

    return d->pannableViewport->panDirection();
}

void MApplicationPage::actionEvent(QActionEvent *e)
{
    switch (e->type()) {
    case QEvent::ActionRemoved:
    case QEvent::ActionChanged:
    case QEvent::ActionAdded: {
        emit actionUpdated(e);
        break;
    }
    default: {
        break;
    }
    }
}

void MApplicationPage::enterDisplayEvent()
{
    MSceneWindow::enterDisplayEvent();
}

void MApplicationPagePrivate::doEnterDisplayEvent()
{
    Q_Q(MApplicationPage);

    if (!contentCreated) {
        contentCreated = true;
        q->createContent();
    }

    MWidgetPrivate::doEnterDisplayEvent();
}

void MApplicationPagePrivate::setExposedContentRect(const QRectF &exposedContentRect)
{
    Q_Q(MApplicationPage);

    if (exposedContentRect != q->model()->exposedContentRect()) {
        q->model()->setExposedContentRect(exposedContentRect);
        emit q->exposedContentRectChanged();
    }
}

QRectF MApplicationPage::exposedContentRect() const
{
    return model()->exposedContentRect();
}

MApplicationPageModel::ComponentDisplayMode MApplicationPage::componentDisplayMode(
    Component component) const
{
    MApplicationPageModel::ComponentDisplayMode displayMode;

    switch (component) {
    case NavigationBar:
        displayMode = model()->navigationBarDisplayMode();
        break;

    case HomeButton:
        displayMode = model()->homeButtonDisplayMode();
        break;

    case EscapeButton:
        displayMode = model()->escapeButtonDisplayMode();
        break;

    case StatusBar:
        displayMode = model()->statusBarDisplayMode();
        break;

    default: //AllComponents
        // return EscapeButton to keep original behaviour but throw a warning
        displayMode = model()->escapeButtonDisplayMode();
        mWarning("MApplicationPage") << "MApplicationPageModel::AllComponents is "
                                     << "not allowed when asking for componentDisplayMode";
    };

    return displayMode;
}

void MApplicationPage::setComponentsDisplayMode(Components components,
        MApplicationPageModel::ComponentDisplayMode displayMode)
{
    if (components.testFlag(NavigationBar)) {
        model()->setNavigationBarDisplayMode(displayMode);
    }

    if (components.testFlag(HomeButton)) {
        model()->setHomeButtonDisplayMode(displayMode);
    }

    if (components.testFlag(EscapeButton)) {
        model()->setEscapeButtonDisplayMode(displayMode);
    }

    if (components.testFlag(StatusBar)) {
        model()->setStatusBarDisplayMode(displayMode);
    }
}

bool MApplicationPage::isProgressIndicatorVisible() const
{
    return model()->progressIndicatorVisible();
}

void MApplicationPage::setProgressIndicatorVisible(bool visible)
{
    model()->setProgressIndicatorVisible(visible);
}

void MApplicationPage::setAutoMarginsForComponentsEnabled(bool enabled)
{
    model()->setAutoMarginsForComponentsEnabled(enabled);
}

bool MApplicationPage::autoMarginsForComponentsEnabled() const
{
    return model()->autoMarginsForComponentsEnabled();
}

MApplicationPageModel::PageEscapeMode MApplicationPage::escapeMode() const
{
    return model()->escapeMode();
}

void MApplicationPage::setEscapeMode(MApplicationPageModel::PageEscapeMode mode)
{
    model()->setEscapeMode(mode);
}

MPannableViewport * MApplicationPage::pannableViewport()
{
    Q_D(MApplicationPage);

    return d->pannableViewport;
}

void MApplicationPage::setCustomNavigationBarContent(QGraphicsWidget *customNavigationBarContent)
{
    Q_D(MApplicationPage);
    QGraphicsWidget *oldCustomNavigationBarContent = 0;

    if (customNavigationBarContent == d->customNavigationBarContent.data())
        return;

    oldCustomNavigationBarContent = d->customNavigationBarContent.data();

    d->customNavigationBarContent = customNavigationBarContent;

    // Let MApplicationWindow remove this content from the navigation bar
    emit customNavigationBarContentChanged();

    if (oldCustomNavigationBarContent)
        delete oldCustomNavigationBarContent;
}

QGraphicsWidget *MApplicationPage::customNavigationBarContent()
{
    Q_D(MApplicationPage);
    return d->customNavigationBarContent.data();
}

#include "moc_mapplicationpage.cpp"
<|endoftext|>