<commit_before>/*
 *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  Contact: Michal Witanowski <m.witanowski@samsung.com>
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License
 */

/**
 * @file
 * @author  Michal Witanowski (m.witanowski@samsung.com)
 * @brief   Unit test of Configuration
 */

#include "config.hpp"
#include "ut.hpp"
#include "config/fields.hpp"
#include "config/manager.hpp"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;
using namespace config;

BOOST_AUTO_TEST_SUITE(ConfigurationSuite)

struct TestConfig {
    // subtree class
    struct SubConfig {

        struct SubSubConfig {
            int intVal;

            CONFIG_REGISTER
            (
                intVal
            )
        };

        int intVal;
        std::vector<int> intVector;
        SubSubConfig subSubObj;

        CONFIG_REGISTER
        (
            intVal,
            intVector,
            subSubObj
        )
    };

    int intVal;
    std::int64_t int64Val;
    std::string stringVal;
    double doubleVal;
    bool boolVal;

    std::vector<int> emptyIntVector;
    std::vector<int> intVector;
    std::vector<std::string> stringVector;
    std::vector<double> doubleVector;

    SubConfig subObj;
    std::vector<SubConfig> subVector;

    CONFIG_REGISTER
    (
        intVal,
        int64Val,
        stringVal,
        doubleVal,
        boolVal,

        emptyIntVector,
        intVector,
        stringVector,
        doubleVector,

        subObj,
        subVector
    )
};

/**
 * JSON string used in ConfigSuite test cases
 * For the purpose of these tests the order of this string
 * has to be equal to the above REGISTER order
 */
const std::string jsonTestString =
    "{ \"intVal\": 12345, "
    "\"int64Val\": -1234567890123456789, "
    "\"stringVal\": \"blah\", "
    "\"doubleVal\": -1.234000, "
    "\"boolVal\": true, "
    "\"emptyIntVector\": [ ], "
    "\"intVector\": [ 1, 2, 3 ], "
    "\"stringVector\": [ \"a\", \"b\" ], "
    "\"doubleVector\": [ 0.000000, 1.000000, 2.000000 ], "
    "\"subObj\": { \"intVal\": 54321, \"intVector\": [ 1, 2 ], \"subSubObj\": { \"intVal\": 234 } }, "
    "\"subVector\": [ { \"intVal\": 123, \"intVector\": [ 3, 4 ], \"subSubObj\": { \"intVal\": 345 } }, "
    "{ \"intVal\": 456, \"intVector\": [ 5, 6 ], \"subSubObj\": { \"intVal\": 567 } } ] }";

// Floating point tolerance as a number of rounding errors
const int TOLERANCE = 1;

BOOST_AUTO_TEST_CASE(FromStringTest)
{
    TestConfig testConfig;

    BOOST_REQUIRE_NO_THROW(loadFromString(jsonTestString, testConfig));

    BOOST_CHECK_EQUAL(12345, testConfig.intVal);
    BOOST_CHECK_EQUAL(-1234567890123456789ll, testConfig.int64Val);
    BOOST_CHECK_EQUAL("blah", testConfig.stringVal);
    BOOST_CHECK_CLOSE(-1.234, testConfig.doubleVal, TOLERANCE);
    BOOST_CHECK_EQUAL(true, testConfig.boolVal);

    BOOST_REQUIRE_EQUAL(0, testConfig.emptyIntVector.size());

    BOOST_REQUIRE_EQUAL(3, testConfig.intVector.size());
    BOOST_CHECK_EQUAL(1, testConfig.intVector[0]);
    BOOST_CHECK_EQUAL(2, testConfig.intVector[1]);
    BOOST_CHECK_EQUAL(3, testConfig.intVector[2]);

    BOOST_REQUIRE_EQUAL(2, testConfig.stringVector.size());
    BOOST_CHECK_EQUAL("a", testConfig.stringVector[0]);
    BOOST_CHECK_EQUAL("b", testConfig.stringVector[1]);

    BOOST_REQUIRE_EQUAL(3, testConfig.doubleVector.size());
    BOOST_CHECK_CLOSE(0.0, testConfig.doubleVector[0], TOLERANCE);
    BOOST_CHECK_CLOSE(1.0, testConfig.doubleVector[1], TOLERANCE);
    BOOST_CHECK_CLOSE(2.0, testConfig.doubleVector[2], TOLERANCE);

    BOOST_CHECK_EQUAL(54321, testConfig.subObj.intVal);
    BOOST_CHECK_EQUAL(2,     testConfig.subObj.intVector.size());
    BOOST_CHECK_EQUAL(1,     testConfig.subObj.intVector[0]);
    BOOST_CHECK_EQUAL(2,     testConfig.subObj.intVector[1]);
    BOOST_CHECK_EQUAL(234,   testConfig.subObj.subSubObj.intVal);

    BOOST_REQUIRE_EQUAL(2, testConfig.subVector.size());
    BOOST_CHECK_EQUAL(123, testConfig.subVector[0].intVal);
    BOOST_CHECK_EQUAL(456, testConfig.subVector[1].intVal);
    BOOST_CHECK_EQUAL(345, testConfig.subVector[0].subSubObj.intVal);
    BOOST_CHECK_EQUAL(567, testConfig.subVector[1].subSubObj.intVal);
    BOOST_CHECK_EQUAL(3,   testConfig.subVector[0].intVector[0]);
    BOOST_CHECK_EQUAL(5,   testConfig.subVector[1].intVector[0]);
    BOOST_CHECK_EQUAL(4,   testConfig.subVector[0].intVector[1]);
    BOOST_CHECK_EQUAL(6,   testConfig.subVector[1].intVector[1]);

}

BOOST_AUTO_TEST_CASE(ToStringTest)
{
    TestConfig testConfig;
    BOOST_REQUIRE_NO_THROW(loadFromString(jsonTestString, testConfig));

    std::string out = saveToString(testConfig);
    BOOST_CHECK_EQUAL(out, jsonTestString);
}

namespace loadErrorsTest {

#define DECLARE_CONFIG(name, type) \
    struct name { \
        type field; \
        CONFIG_REGISTER(field) \
    };
DECLARE_CONFIG(IntConfig, int)
DECLARE_CONFIG(StringConfig, std::string)
DECLARE_CONFIG(DoubleConfig, double)
DECLARE_CONFIG(BoolConfig, bool)
DECLARE_CONFIG(ArrayConfig, std::vector<int>)
DECLARE_CONFIG(ObjectConfig, IntConfig)
#undef DECLARE_CONFIG

} // namespace loadErrorsTest

BOOST_AUTO_TEST_CASE(LoadErrorsTest)
{
    using namespace loadErrorsTest;

    IntConfig config;
    BOOST_REQUIRE_NO_THROW(loadFromString("{\"field\":1}", config));

    BOOST_CHECK_THROW(loadFromString("", config), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{", config), ConfigException); // invalid json
    BOOST_CHECK_THROW(loadFromString("{}", config), ConfigException); // missing field

    // invalid type

    IntConfig intConfig;
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": 1}", intConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1234567890123456789}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": -1234567890123456789}", intConfig), ConfigException);

    StringConfig stringConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", stringConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": \"1\"}", stringConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", stringConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", stringConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", stringConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", stringConfig), ConfigException);

    DoubleConfig doubleConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", doubleConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", doubleConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": 1.0}", doubleConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", doubleConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", doubleConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", doubleConfig), ConfigException);

    BoolConfig boolConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", boolConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", boolConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", boolConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": true}", boolConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", boolConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", boolConfig), ConfigException);

    ArrayConfig arrayConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", arrayConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", arrayConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", arrayConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", arrayConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": []}", arrayConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", arrayConfig), ConfigException);

    ObjectConfig objectConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", objectConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": {\"field\": 1}}", objectConfig));
}

namespace hasVisitableTest {

struct NotVisitable {};
struct Visitable {
    template<typename V>
    void accept(V v);
};
struct ConstVisitable {
    template<typename V>
    void accept(V v) const;
};
struct FullVisitable {
    template<typename V>
    void accept(V v);
    template<typename V>
    void accept(V v) const;
};
struct DerivedVisitable : FullVisitable {};
struct MissingArg {
    template<typename V>
    void accept();
};
struct WrongArg {
    template<typename V>
    void accept(int v);
};
struct NotFunction {
    int accept;
};

} // namespace hasVisitableTest

BOOST_AUTO_TEST_CASE(HasVisibleInternalHelperTest)
{
    using namespace hasVisitableTest;

    static_assert(isVisitable<Visitable>::value, "");
    static_assert(isVisitable<ConstVisitable>::value, "");
    static_assert(isVisitable<FullVisitable>::value, "");
    static_assert(isVisitable<DerivedVisitable>::value, "");

    static_assert(!isVisitable<NotVisitable>::value, "");
    static_assert(!isVisitable<MissingArg>::value, "");
    static_assert(!isVisitable<WrongArg>::value, "");
    static_assert(!isVisitable<NotFunction>::value, "");

    BOOST_CHECK(isVisitable<Visitable>());
}

BOOST_AUTO_TEST_CASE(FromToKVStoreTest)
{
    TestConfig config;
    loadFromString(jsonTestString, config);

    std::string dbPath = fs::unique_path("/tmp/kvstore-%%%%.db3").string();

    saveToKVStore(dbPath, config);
    TestConfig outConfig;
    loadFromKVStore(dbPath, outConfig);

    std::string out = saveToString(outConfig);
    BOOST_CHECK_EQUAL(out, jsonTestString);

    fs::remove(dbPath);
    fs::remove(dbPath + "-journal");
}

BOOST_AUTO_TEST_CASE(FromToFDTest)
{
    TestConfig config;
    loadFromString(jsonTestString, config);
    // Setup fd
    std::string fifoPath = fs::unique_path("/tmp/fdstore-%%%%").string();
    BOOST_CHECK(::mkfifo(fifoPath.c_str(), S_IWUSR | S_IRUSR) >= 0);
    int fd = ::open(fifoPath.c_str(), O_RDWR);
    BOOST_REQUIRE(fd >= 0);

    // The test
    saveToFD(fd, config);
    TestConfig outConfig;
    loadFromFD(fd, outConfig);
    std::string out = saveToString(outConfig);
    BOOST_CHECK_EQUAL(out, jsonTestString);

    // Cleanup
    BOOST_CHECK(::close(fd) >= 0);
    fs::remove(fifoPath);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Added testing union in config file<commit_after>/*
 *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  Contact: Michal Witanowski <m.witanowski@samsung.com>
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License
 */

/**
 * @file
 * @author  Michal Witanowski (m.witanowski@samsung.com)
 * @brief   Unit test of Configuration
 */

#include "config.hpp"
#include "ut.hpp"
#include "config/fields.hpp"
#include "config/fields-union.hpp"
#include "config/manager.hpp"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;
using namespace config;

BOOST_AUTO_TEST_SUITE(ConfigurationSuite)

struct TestConfig {
    // subtree class
    struct SubConfig {

        struct SubSubConfig {
            int intVal;

            CONFIG_REGISTER
            (
                intVal
            )
        };

        int intVal;
        std::vector<int> intVector;
        SubSubConfig subSubObj;

        CONFIG_REGISTER
        (
            intVal,
            intVector,
            subSubObj
        )
    };

    struct SubConfigOption {
        CONFIG_DECLARE_UNION
        (
            SubConfig,
            int
        )
    };

    int intVal;
    std::int64_t int64Val;
    std::string stringVal;
    double doubleVal;
    bool boolVal;

    std::vector<int> emptyIntVector;
    std::vector<int> intVector;
    std::vector<std::string> stringVector;
    std::vector<double> doubleVector;

    SubConfig subObj;
    std::vector<SubConfig> subVector;

    SubConfigOption union1;
    SubConfigOption union2;
    std::vector<SubConfigOption> unions;

    CONFIG_REGISTER
    (
        intVal,
        int64Val,
        stringVal,
        doubleVal,
        boolVal,

        emptyIntVector,
        intVector,
        stringVector,
        doubleVector,

        subObj,
        subVector,

        union1,
        union2,
        unions
    )
};

/**
 * JSON string used in ConfigSuite test cases
 * For the purpose of these tests the order of this string
 * has to be equal to the above REGISTER order
 */
const std::string jsonTestString =
    "{ \"intVal\": 12345, "
    "\"int64Val\": -1234567890123456789, "
    "\"stringVal\": \"blah\", "
    "\"doubleVal\": -1.234000, "
    "\"boolVal\": true, "
    "\"emptyIntVector\": [ ], "
    "\"intVector\": [ 1, 2, 3 ], "
    "\"stringVector\": [ \"a\", \"b\" ], "
    "\"doubleVector\": [ 0.000000, 1.000000, 2.000000 ], "
    "\"subObj\": { \"intVal\": 54321, \"intVector\": [ 1, 2 ], \"subSubObj\": { \"intVal\": 234 } }, "
    "\"subVector\": [ { \"intVal\": 123, \"intVector\": [ 3, 4 ], \"subSubObj\": { \"intVal\": 345 } }, "
        "{ \"intVal\": 456, \"intVector\": [ 5, 6 ], \"subSubObj\": { \"intVal\": 567 } } ], "
    "\"union1\": { \"type\": \"int\", \"value\": 2 }, "
    "\"union2\": { \"type\": \"SubConfig\", \"value\": { \"intVal\": 54321, \"intVector\": [ 1 ], "
        "\"subSubObj\": { \"intVal\": 234 } } }, "
    "\"unions\": [ "
        "{ \"type\": \"int\", \"value\": 2 }, "
        "{ \"type\": \"SubConfig\", \"value\": { \"intVal\": 54321, \"intVector\": [ 1 ], "
            "\"subSubObj\": { \"intVal\": 234 } } } ] }";

// Floating point tolerance as a number of rounding errors
const int TOLERANCE = 1;

BOOST_AUTO_TEST_CASE(FromStringTest)
{
    TestConfig testConfig;

    BOOST_REQUIRE_NO_THROW(loadFromString(jsonTestString, testConfig));

    BOOST_CHECK_EQUAL(12345, testConfig.intVal);
    BOOST_CHECK_EQUAL(-1234567890123456789ll, testConfig.int64Val);
    BOOST_CHECK_EQUAL("blah", testConfig.stringVal);
    BOOST_CHECK_CLOSE(-1.234, testConfig.doubleVal, TOLERANCE);
    BOOST_CHECK_EQUAL(true, testConfig.boolVal);

    BOOST_REQUIRE_EQUAL(0, testConfig.emptyIntVector.size());

    BOOST_REQUIRE_EQUAL(3, testConfig.intVector.size());
    BOOST_CHECK_EQUAL(1, testConfig.intVector[0]);
    BOOST_CHECK_EQUAL(2, testConfig.intVector[1]);
    BOOST_CHECK_EQUAL(3, testConfig.intVector[2]);

    BOOST_REQUIRE_EQUAL(2, testConfig.stringVector.size());
    BOOST_CHECK_EQUAL("a", testConfig.stringVector[0]);
    BOOST_CHECK_EQUAL("b", testConfig.stringVector[1]);

    BOOST_REQUIRE_EQUAL(3, testConfig.doubleVector.size());
    BOOST_CHECK_CLOSE(0.0, testConfig.doubleVector[0], TOLERANCE);
    BOOST_CHECK_CLOSE(1.0, testConfig.doubleVector[1], TOLERANCE);
    BOOST_CHECK_CLOSE(2.0, testConfig.doubleVector[2], TOLERANCE);

    BOOST_CHECK_EQUAL(54321, testConfig.subObj.intVal);
    BOOST_CHECK_EQUAL(2,     testConfig.subObj.intVector.size());
    BOOST_CHECK_EQUAL(1,     testConfig.subObj.intVector[0]);
    BOOST_CHECK_EQUAL(2,     testConfig.subObj.intVector[1]);
    BOOST_CHECK_EQUAL(234,   testConfig.subObj.subSubObj.intVal);

    BOOST_REQUIRE_EQUAL(2, testConfig.subVector.size());
    BOOST_CHECK_EQUAL(123, testConfig.subVector[0].intVal);
    BOOST_CHECK_EQUAL(456, testConfig.subVector[1].intVal);
    BOOST_CHECK_EQUAL(345, testConfig.subVector[0].subSubObj.intVal);
    BOOST_CHECK_EQUAL(567, testConfig.subVector[1].subSubObj.intVal);
    BOOST_CHECK_EQUAL(3,   testConfig.subVector[0].intVector[0]);
    BOOST_CHECK_EQUAL(5,   testConfig.subVector[1].intVector[0]);
    BOOST_CHECK_EQUAL(4,   testConfig.subVector[0].intVector[1]);
    BOOST_CHECK_EQUAL(6,   testConfig.subVector[1].intVector[1]);

}

BOOST_AUTO_TEST_CASE(ToStringTest)
{
    TestConfig testConfig;
    BOOST_REQUIRE_NO_THROW(loadFromString(jsonTestString, testConfig));

    std::string out = saveToString(testConfig);
    BOOST_CHECK_EQUAL(out, jsonTestString);
}

namespace loadErrorsTest {

#define DECLARE_CONFIG(name, type) \
    struct name { \
        type field; \
        CONFIG_REGISTER(field) \
    };
DECLARE_CONFIG(IntConfig, int)
DECLARE_CONFIG(StringConfig, std::string)
DECLARE_CONFIG(DoubleConfig, double)
DECLARE_CONFIG(BoolConfig, bool)
DECLARE_CONFIG(ArrayConfig, std::vector<int>)
DECLARE_CONFIG(ObjectConfig, IntConfig)
#undef DECLARE_CONFIG

} // namespace loadErrorsTest

BOOST_AUTO_TEST_CASE(LoadErrorsTest)
{
    using namespace loadErrorsTest;

    IntConfig config;
    BOOST_REQUIRE_NO_THROW(loadFromString("{\"field\":1}", config));

    BOOST_CHECK_THROW(loadFromString("", config), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{", config), ConfigException); // invalid json
    BOOST_CHECK_THROW(loadFromString("{}", config), ConfigException); // missing field

    // invalid type

    IntConfig intConfig;
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": 1}", intConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1234567890123456789}", intConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": -1234567890123456789}", intConfig), ConfigException);

    StringConfig stringConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", stringConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": \"1\"}", stringConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", stringConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", stringConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", stringConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", stringConfig), ConfigException);

    DoubleConfig doubleConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", doubleConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", doubleConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": 1.0}", doubleConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", doubleConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", doubleConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", doubleConfig), ConfigException);

    BoolConfig boolConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", boolConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", boolConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", boolConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": true}", boolConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", boolConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", boolConfig), ConfigException);

    ArrayConfig arrayConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", arrayConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", arrayConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", arrayConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", arrayConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": []}", arrayConfig));
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", arrayConfig), ConfigException);

    ObjectConfig objectConfig;
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": \"1\"}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": 1.0}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": true}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": []}", objectConfig), ConfigException);
    BOOST_CHECK_THROW(loadFromString("{\"field\": {}}", objectConfig), ConfigException);
    BOOST_CHECK_NO_THROW(loadFromString("{\"field\": {\"field\": 1}}", objectConfig));
}

namespace hasVisitableTest {

struct NotVisitable {};
struct Visitable {
    template<typename V>
    void accept(V v);
};
struct ConstVisitable {
    template<typename V>
    void accept(V v) const;
};
struct FullVisitable {
    template<typename V>
    void accept(V v);
    template<typename V>
    void accept(V v) const;
};
struct DerivedVisitable : FullVisitable {};
struct MissingArg {
    template<typename V>
    void accept();
};
struct WrongArg {
    template<typename V>
    void accept(int v);
};
struct NotFunction {
    int accept;
};

} // namespace hasVisitableTest

BOOST_AUTO_TEST_CASE(HasVisibleInternalHelperTest)
{
    using namespace hasVisitableTest;

    static_assert(isVisitable<Visitable>::value, "");
    static_assert(isVisitable<ConstVisitable>::value, "");
    static_assert(isVisitable<FullVisitable>::value, "");
    static_assert(isVisitable<DerivedVisitable>::value, "");

    static_assert(!isVisitable<NotVisitable>::value, "");
    static_assert(!isVisitable<MissingArg>::value, "");
    static_assert(!isVisitable<WrongArg>::value, "");
    static_assert(!isVisitable<NotFunction>::value, "");

    BOOST_CHECK(isVisitable<Visitable>());
}

BOOST_AUTO_TEST_CASE(FromToKVStoreTest)
{
    TestConfig config;
    loadFromString(jsonTestString, config);

    std::string dbPath = fs::unique_path("/tmp/kvstore-%%%%.db3").string();

    saveToKVStore(dbPath, config);
    TestConfig outConfig;
    loadFromKVStore(dbPath, outConfig);

    std::string out = saveToString(outConfig);
    BOOST_CHECK_EQUAL(out, jsonTestString);

    fs::remove(dbPath);
    fs::remove(dbPath + "-journal");
}

BOOST_AUTO_TEST_CASE(FromToFDTest)
{
    TestConfig config;
    loadFromString(jsonTestString, config);
    // Setup fd
    std::string fifoPath = fs::unique_path("/tmp/fdstore-%%%%").string();
    BOOST_CHECK(::mkfifo(fifoPath.c_str(), S_IWUSR | S_IRUSR) >= 0);
    int fd = ::open(fifoPath.c_str(), O_RDWR);
    BOOST_REQUIRE(fd >= 0);

    // The test
    saveToFD(fd, config);
    TestConfig outConfig;
    loadFromFD(fd, outConfig);
    std::string out = saveToString(outConfig);
    BOOST_CHECK_EQUAL(out, jsonTestString);

    // Cleanup
    BOOST_CHECK(::close(fd) >= 0);
    fs::remove(fifoPath);
}

BOOST_AUTO_TEST_CASE(ConfigUnion)
{
    TestConfig testConfig;
    BOOST_REQUIRE_NO_THROW(loadFromString(jsonTestString, testConfig));

    BOOST_CHECK(testConfig.union1.is<int>());
    BOOST_CHECK(!testConfig.union1.is<TestConfig::SubConfig>());
    BOOST_CHECK_EQUAL(testConfig.union1.as<int>(), 2);
    BOOST_CHECK(!testConfig.union2.is<int>());
    BOOST_CHECK(testConfig.union2.is<TestConfig::SubConfig>());
    TestConfig::SubConfig& subConfig = testConfig.union2.as<TestConfig::SubConfig>();
    BOOST_CHECK_EQUAL(subConfig.intVal, 54321);
    BOOST_CHECK(testConfig.unions[0].is<int>());
    BOOST_CHECK(testConfig.unions[1].is<TestConfig::SubConfig>());

    std::string out = saveToString(testConfig);
    BOOST_CHECK_EQUAL(out, jsonTestString);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
Allocore Example: Texture

Description:
This demonstrates how to create and display a texture.

Author:
Lance Putnam, Nov. 2013
*/

#include "allocore/io/al_App.hpp"
using namespace al;

class MyApp : public App{
public:

	Texture tex;

	MyApp():
		// Construct texture
		// Arguments: width, height, pixel format, pixel data type
		// Note that when we construct a texture in this way, the default
		// policy is to allocate a client-side buffer to hold the pixels.
		tex(64,64, Graphics::RGBA, Graphics::UBYTE)
	{
		// The default magnification filter is linear
		//tex.filterMag(Texture::NEAREST);

		// Get a pointer to the (client-side) pixel buffer.
		// When we make a read access to the pixels, they are flagged as dirty
		// and get sent to the GPU the next time the texture bound.
		unsigned char * pixels = tex.data<unsigned char>();

		// Loop through the pixels to generate an image
		int Nx = tex.width();
		int Ny = tex.height();
		for(int j=0; j<Ny; ++j){ float y = float(j)/(Ny-1)*2-1;
		for(int i=0; i<Nx; ++i){ float x = float(i)/(Nx-1)*2-1;

			float m = 1 - al::clip(hypot(x,y));
			float a = al::wrap(atan2(y,x)/M_2PI);

			Color col = HSV(a,1,m);

			int idx = j*Nx + i;
			int stride = tex.numComponents();
			pixels[idx*stride + 0] = col.r * 255.;
			pixels[idx*stride + 1] = col.g * 255.;
			pixels[idx*stride + 2] = col.b * 255.;
			pixels[idx*stride + 3] = col.a;
		}}

		nav().pos().set(0,0,4);
		initWindow();
	}

	void onDraw(Graphics& g){

		// Borrow a temporary Mesh from Graphics
		Mesh& m = g.mesh();

		m.reset();

		// Generate geometry
		m.primitive(Graphics::TRIANGLE_STRIP);
		m.vertex(-1,  1);
		m.vertex(-1, -1);
		m.vertex( 1,  1);
		m.vertex( 1, -1);

		// Add texture coordinates
		m.texCoord(0,1);
		m.texCoord(0,0);
		m.texCoord(1,1);
		m.texCoord(1,0);

		// We must tell the GPU to use the texture when rendering primitives
		tex.bind();
			g.draw(m);
		tex.unbind();
	}
};

int main(){
	MyApp().start();
}
<commit_msg>Update texture example<commit_after>/*
Allocore Example: Texture

Description:
This demonstrates how to create and display a texture.

Author:
Lance Putnam, Nov. 2013
*/

#include "allocore/io/al_App.hpp"
using namespace al;

class MyApp : public App{
public:

	Texture tex;
	Mesh mesh;

	MyApp():
		// Construct texture
		// Arguments: width, height, pixel format, pixel data type
		// Note that when we construct a texture in this way, the default
		// policy is to allocate a client-side buffer to hold the pixels.
		tex(64,64, Graphics::RGBA, Graphics::UBYTE)
	{
		// The default magnification filter is linear
		//tex.filterMag(Texture::NEAREST);

		// Get a pointer to the (client-side) pixel buffer.
		// When we make a read access to the pixels, they are flagged as dirty
		// and get sent to the GPU the next time the texture is bound.
		unsigned char * pixels = tex.data<unsigned char>();

		// Loop through the pixels to generate an image
		int Nx = tex.width();
		int Ny = tex.height();
		for(int j=0; j<Ny; ++j){ float y = float(j)/(Ny-1)*2-1;
		for(int i=0; i<Nx; ++i){ float x = float(i)/(Nx-1)*2-1;

			float m = 1 - al::clip(hypot(x,y));
			float a = al::wrap(atan2(y,x)/M_2PI);

			Color col = HSV(a,1,m);

			int idx = j*Nx + i;
			int stride = tex.numComponents();
			pixels[idx*stride + 0] = col.r * 255.;
			pixels[idx*stride + 1] = col.g * 255.;
			pixels[idx*stride + 2] = col.b * 255.;
			pixels[idx*stride + 3] = col.a;
		}}

		// Generate the geometry onto which to display the texture
		mesh.primitive(Graphics::TRIANGLE_STRIP);
		mesh.vertex(-1,  1);
		mesh.vertex(-1, -1);
		mesh.vertex( 1,  1);
		mesh.vertex( 1, -1);

		// Add texture coordinates
		mesh.texCoord(0,1);
		mesh.texCoord(0,0);
		mesh.texCoord(1,1);
		mesh.texCoord(1,0);

		// The color acts as a multiplier on the texture color
		mesh.color(RGB(1)); // white: shows texture as is
		//mesh.color(RGB(1,0,0)); // red: shows only red components

		nav().pullBack(4);
		initWindow();
	}

	void onDraw(Graphics& g){
		// We must tell the GPU to use the texture when rendering primitives
		tex.bind();
			g.draw(mesh);
		tex.unbind();
	}
};

int main(){
	MyApp().start();
}
<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>

#include "threading/parallelregion.hpp"

using namespace fc;

BOOST_AUTO_TEST_CASE( test_ownership_handling)
{
	struct dummy_region : parallel_region
	{
		dummy_region(std::shared_ptr<tick_controller> tick) :
			parallel_region(tick)
		{
			get_ticks()->switch_tick() >> [this](){ switch_count = switch_count+1;};
			get_ticks()->fire_outgoing() >> [this](){ fire_count = fire_count+1;};
			get_ticks()->work_tick() >> [this](){ work_count = work_count+1;};
		}

		int switch_count = 0;
		int fire_count = 0;
		int work_count = 0;
	};

	dummy_region test_region_1(std::make_shared<tick_controller>());
	dummy_region test_child(test_region_1.get_ticks());

	test_region_1.get_ticks()->in_switch_buffers()();
	// switch tick is forwarded to child buffers, thus their count should increase
	BOOST_CHECK_EQUAL(test_region_1.switch_count, 1);
	BOOST_CHECK_EQUAL(test_child.switch_count, 1);

	test_region_1.get_ticks()->in_fire_outgoing()();
	// fire tick is not forwarded
	BOOST_CHECK_EQUAL(test_region_1.fire_count, 1);
	BOOST_CHECK_EQUAL(test_child.fire_count, 0);

	test_region_1.get_ticks()->in_work()();
	// work tick is not forwarded
	BOOST_CHECK_EQUAL(test_region_1.work_count, 1);
	BOOST_CHECK_EQUAL(test_child.work_count, 0);
	//work tick fires outgoing events of child region
	BOOST_CHECK_EQUAL(test_child.fire_count, 1);

	dummy_region test_child_2(test_region_1.get_ticks());
	test_region_1.get_ticks()->in_switch_buffers()();
	// switch tick is forwarded to child buffers, thus their count should increase
	BOOST_CHECK_EQUAL(test_region_1.switch_count, 2);
	BOOST_CHECK_EQUAL(test_child.switch_count, 2);
	BOOST_CHECK_EQUAL(test_child_2.switch_count, 1);
}

BOOST_AUTO_TEST_CASE( test_region_buffers)
{
	struct test_region_t : parallel_region
	{
		test_region_t(std::shared_ptr<tick_controller> tick) :
			parallel_region(tick)
		{
			attach_event_in_buffer(incoming_event); // ToDo move this to the bufffer, which only gets this pointer in constructor
			attach_event_out_buffer(leaving_event);

			incoming_event >> [this](int i) {storage = i; };
			incoming_event >> [](int i) { return ++i; } >> leaving_event;
		}

		exit_event<int> leaving_event;
		enter_event<int> incoming_event;

		int storage = 0;
	};

	test_region_t test_region(std::make_shared<tick_controller>());
	event_out_port<int> sender;
	std::vector<int> sink_buffer;
	event_in_port<int> sink([&](int i){ sink_buffer.push_back(i); });

	sender >> test_region.incoming_event.region_port();
	test_region.leaving_event.region_port() >> sink;
	sender.fire(1);

	// since the buffer was not yet switched, the event has no effect yet.
	BOOST_CHECK_EQUAL(test_region.storage, 0);

	test_region.get_ticks()->in_switch_buffers()();
	// since the region has not yet had its work tick triggered...
	BOOST_CHECK_EQUAL(test_region.storage, 0);

	test_region.get_ticks()->in_work()();
	BOOST_CHECK_EQUAL(test_region.storage, 1); //now!

	test_region.get_ticks()->in_switch_buffers()();
	BOOST_CHECK_EQUAL(sink_buffer.size(), 0);

	test_region.get_ticks()->in_fire_outgoing()();
	BOOST_CHECK_EQUAL(sink_buffer.size(), 1);
	BOOST_CHECK_EQUAL(sink_buffer.front(), 2);
}

BOOST_AUTO_TEST_CASE( test_region_state)
{

}

<commit_msg>deleted falsly merged file test_region<commit_after><|endoftext|>


<commit_before>#include <cstdio>
#include <cassert>
#include <sstream>

#include "config.h"
#include "manager.h"
#include "bundle.h"
#include "stringtie.h"
#include "scallop.h"
#include "gtf_gene.h"
#include "nested_graph.h"

manager::manager()
{
}

manager::~manager()
{
}

int manager::process(const string &file, string a)
{
	algo = a;
	string s = file.substr(file.size() - 3, 3);
	if(s == "bam" || s == "sam") assemble_bam(file);
	else if(s == "gtf") assemble_gtf(file);
	else assemble_example(file);
	return 0;
}

int manager::assemble_bam(const string &file)
{
    samFile *fn = sam_open(file.c_str(), "r");
    bam_hdr_t *h= sam_hdr_read(fn);
    bam1_t *b = bam_init1();

	int index = 0;
	bundle_base bb;
    while(sam_read1(fn, h, b) >= 0)
	{
		bam1_core_t &p = b->core;
		if((p.flag & 0x4) >= 1) continue;		// read is not mapped, TODO
		if((p.flag & 0x100) >= 1) continue;		// secondary alignment
		if(p.n_cigar < 1) continue;				// should never happen
		if(p.n_cigar > 7) continue;				// ignore hits with more than 7 cigar types
		//if(p.qual <= 4) continue;				// ignore hits with quality-score < 5
		if(bb.get_num_hits() > 0 && (bb.get_rpos() + min_bundle_gap < p.pos || p.tid != bb.get_tid()))
		{
			if(bb.get_num_hits() < min_num_hits_in_bundle)
			{
				bb.clear();
				continue;
			}

			/*
			bundle bd(bb);
			bd.print(index);

			splice_graph gr;
			bd.build_splice_graph(gr);

			stringtie st(gr);
			st.assemble();
			st.print("stringtie");

			scallop sc("", gr);
			sc.assemble();
			sc.print();

			bd.output_gtf(stringtie_fout, st.paths, "stringtie", index);
			bd.output_gtf(scallop_fout, sc.paths, "scallop", index);
			*/

			index++;
			bb.clear();
			if(max_num_bundles > 0 && index > max_num_bundles) break;
		}
		bb.add_hit(h, b);
    }

    bam_destroy1(b);
    bam_hdr_destroy(h);
    sam_close(fn);

	return 0;
}

int manager::assemble_gtf(const string &file)
{
	ifstream fin(file.c_str());
	if(fin.fail())
	{
		printf("open file %s error\n", file.c_str());
		return 0;
	}

	char line[102400];

	vector<gtf_gene> genes;
	map<string, int> m;
	while(fin.getline(line, 102400, '\n'))
	{
		gtf_exon ge(line);
		if(ge.feature != "exon") continue;
		if(m.find(ge.gene_id) == m.end())
		{
			gtf_gene gg;
			gg.add_exon(ge);
			genes.push_back(gg);
			m.insert(pair<string, int>(ge.gene_id, genes.size() - 1));
		}
		else
		{
			genes[m[ge.gene_id]].add_exon(ge);
		}
	}

	for(int i = 0; i < genes.size(); i++)
	{
		gtf_gene &gg = genes[i];
		if(gg.exons.size() <= 0) continue;

		string name = gg.exons[0].gene_id;

		// DEBUG
		//if(name != "ZNF415") continue;

		splice_graph gr;
		gg.build_splice_graph(gr);

		string s;
		int p0 = gr.compute_num_paths();
		int p1 = gr.num_edges() - gr.num_vertices() + 2;
		assert(p0 >= p1);
		if(p0 == p1) s = "EASY";
		else s = "HARD";

		if(algo == "")
		{
			printf("gene %s, %lu transcipts, total %lu exons, %d paths, %d required, %s\n",
					name.c_str(), gg.transcripts.size(), gg.exons.size(), p0, p1, s.c_str());
		}
		else if(algo == "scallop")
		{
			if(s == "EASY") continue;
			scallop sc(gg.exons[0].gene_id, gr);
			sc.assemble();
		}
		else if(algo == "stringtie")
		{
			if(s == "EASY") continue;
			stringtie st(gg.exons[0].gene_id, gr);
			st.assemble();
		}
	}

	return 0;
}

int manager::assemble_example(const string &file)
{
	splice_graph gr;
	gr.build(file);

	scallop sc("example", gr);
	sc.assemble();

	return 0;
}
<commit_msg>add trivial, easy and hard<commit_after>#include <cstdio>
#include <cassert>
#include <sstream>

#include "config.h"
#include "manager.h"
#include "bundle.h"
#include "stringtie.h"
#include "scallop.h"
#include "gtf_gene.h"
#include "nested_graph.h"

manager::manager()
{
}

manager::~manager()
{
}

int manager::process(const string &file, string a)
{
	algo = a;
	string s = file.substr(file.size() - 3, 3);
	if(s == "bam" || s == "sam") assemble_bam(file);
	else if(s == "gtf") assemble_gtf(file);
	else assemble_example(file);
	return 0;
}

int manager::assemble_bam(const string &file)
{
    samFile *fn = sam_open(file.c_str(), "r");
    bam_hdr_t *h= sam_hdr_read(fn);
    bam1_t *b = bam_init1();

	int index = 0;
	bundle_base bb;
    while(sam_read1(fn, h, b) >= 0)
	{
		bam1_core_t &p = b->core;
		if((p.flag & 0x4) >= 1) continue;		// read is not mapped, TODO
		if((p.flag & 0x100) >= 1) continue;		// secondary alignment
		if(p.n_cigar < 1) continue;				// should never happen
		if(p.n_cigar > 7) continue;				// ignore hits with more than 7 cigar types
		//if(p.qual <= 4) continue;				// ignore hits with quality-score < 5
		if(bb.get_num_hits() > 0 && (bb.get_rpos() + min_bundle_gap < p.pos || p.tid != bb.get_tid()))
		{
			if(bb.get_num_hits() < min_num_hits_in_bundle)
			{
				bb.clear();
				continue;
			}

			/*
			bundle bd(bb);
			bd.print(index);

			splice_graph gr;
			bd.build_splice_graph(gr);

			stringtie st(gr);
			st.assemble();
			st.print("stringtie");

			scallop sc("", gr);
			sc.assemble();
			sc.print();

			bd.output_gtf(stringtie_fout, st.paths, "stringtie", index);
			bd.output_gtf(scallop_fout, sc.paths, "scallop", index);
			*/

			index++;
			bb.clear();
			if(max_num_bundles > 0 && index > max_num_bundles) break;
		}
		bb.add_hit(h, b);
    }

    bam_destroy1(b);
    bam_hdr_destroy(h);
    sam_close(fn);

	return 0;
}

int manager::assemble_gtf(const string &file)
{
	ifstream fin(file.c_str());
	if(fin.fail())
	{
		printf("open file %s error\n", file.c_str());
		return 0;
	}

	char line[102400];

	vector<gtf_gene> genes;
	map<string, int> m;
	while(fin.getline(line, 102400, '\n'))
	{
		gtf_exon ge(line);
		if(ge.feature != "exon") continue;
		if(m.find(ge.gene_id) == m.end())
		{
			gtf_gene gg;
			gg.add_exon(ge);
			genes.push_back(gg);
			m.insert(pair<string, int>(ge.gene_id, genes.size() - 1));
		}
		else
		{
			genes[m[ge.gene_id]].add_exon(ge);
		}
	}

	for(int i = 0; i < genes.size(); i++)
	{
		gtf_gene &gg = genes[i];
		if(gg.exons.size() <= 0) continue;

		string name = gg.exons[0].gene_id;

		// DEBUG
		//if(name != "ZNF415") continue;

		splice_graph gr;
		gg.build_splice_graph(gr);

		string s;
		int p0 = gr.compute_num_paths();
		int p1 = gr.num_edges() - gr.num_vertices() + 2;
		int p2 = gg.transcripts.size();
		assert(p0 >= p1);

		//printf("#paths = %d, delta = %d, #transcripts = %d\n", p0, p1, p2);

		if(p0 == p1) assert(p2 >= p1);
		if(p0 == p1) s = "TRIVIAL";
		else if(p2 >= p1) s = "EASY";
		else s = "HARD";

		if(algo == "")
		{
			printf("gene %s, %lu transcipts, total %lu exons, %d paths, %d required, %s\n",
					name.c_str(), gg.transcripts.size(), gg.exons.size(), p0, p1, s.c_str());
		}
		else if(algo == "scallop")
		{
			if(s != "HARD") continue;
			scallop sc(gg.exons[0].gene_id, gr);
			sc.assemble();
		}
		else if(algo == "stringtie")
		{
			if(s != "HARD") continue;
			stringtie st(gg.exons[0].gene_id, gr);
			st.assemble();
		}
	}

	return 0;
}

int manager::assemble_example(const string &file)
{
	splice_graph gr;
	gr.build(file);

	scallop sc("example", gr);
	sc.assemble();

	return 0;
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2008-2018 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <thrust/detail/config.h>
#include <thrust/detail/allocator/allocator_traits.h>
#include <thrust/detail/type_traits/is_call_possible.h>
#include <thrust/detail/integer_traits.h>

#if THRUST_CPP_DIALECT >= 2011
  #include <thrust/detail/type_deduction.h>
#endif

#include <new>

namespace thrust
{
namespace detail
{
namespace allocator_traits_detail
{

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_allocate_with_hint_impl, allocate)

template<typename Alloc>
  class has_member_allocate_with_hint
{
  typedef typename allocator_traits<Alloc>::pointer            pointer;
  typedef typename allocator_traits<Alloc>::size_type          size_type;
  typedef typename allocator_traits<Alloc>::const_void_pointer const_void_pointer;

  public:
    typedef typename has_member_allocate_with_hint_impl<Alloc, pointer(size_type,const_void_pointer)>::type type;
    static const bool value = type::value;
};

template<typename Alloc>
__host__ __device__
  typename enable_if<
    has_member_allocate_with_hint<Alloc>::value,
    typename allocator_traits<Alloc>::pointer
  >::type
    allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n, typename allocator_traits<Alloc>::const_void_pointer hint)
{
  return a.allocate(n,hint);
}

template<typename Alloc>
__host__ __device__
  typename disable_if<
    has_member_allocate_with_hint<Alloc>::value,
    typename allocator_traits<Alloc>::pointer
  >::type
    allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n, typename allocator_traits<Alloc>::const_void_pointer)
{
  return a.allocate(n);
}

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_construct1_impl, construct)

template<typename Alloc, typename T>
  struct has_member_construct1
    : has_member_construct1_impl<Alloc, void(T*)>
{};

__thrust_exec_check_disable__
template<typename Alloc, typename T>
  inline __host__ __device__
    typename enable_if<
      has_member_construct1<Alloc,T>::value
    >::type
      construct(Alloc &a, T *p)
{
  a.construct(p);
}

__thrust_exec_check_disable__
template<typename Alloc, typename T>
  inline __host__ __device__
    typename disable_if<
      has_member_construct1<Alloc,T>::value
    >::type
      construct(Alloc &, T *p)
{
  ::new(static_cast<void*>(p)) T();
}

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_construct2_impl, construct)

template<typename Alloc, typename T, typename Arg1>
  struct has_member_construct2
    : has_member_construct2_impl<Alloc, void(T*,const Arg1 &)>
{};

__thrust_exec_check_disable__
template<typename Alloc, typename T, typename Arg1>
  inline __host__ __device__
    typename enable_if<
      has_member_construct2<Alloc,T,Arg1>::value
    >::type
      construct(Alloc &a, T *p, const Arg1 &arg1)
{
  a.construct(p,arg1);
}

__thrust_exec_check_disable__
template<typename Alloc, typename T, typename Arg1>
  inline __host__ __device__
    typename disable_if<
      has_member_construct2<Alloc,T,Arg1>::value
    >::type
      construct(Alloc &, T *p, const Arg1 &arg1)
{
  ::new(static_cast<void*>(p)) T(arg1);
}

#if THRUST_CPP_DIALECT >= 2011

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_constructN_impl, construct)

template<typename Alloc, typename T, typename... Args>
  struct has_member_constructN
    : has_member_constructN_impl<Alloc, void(T*, Args...)>
{};

__thrust_exec_check_disable__
template<typename Alloc, typename T, typename... Args>
  inline __host__ __device__
    typename enable_if<
      has_member_constructN<Alloc, T, Args...>::value
    >::type
      construct(Alloc &a, T* p, Args&&... args)
{
  a.construct(p, THRUST_FWD(args)...);
}

__thrust_exec_check_disable__
template<typename Alloc, typename T, typename... Args>
  inline __host__ __device__
    typename disable_if<
      has_member_constructN<Alloc, T, Args...>::value
    >::type
      construct(Alloc &, T* p, Args&&... args)
{
  ::new(static_cast<void*>(p)) T(THRUST_FWD(args)...);
}

#endif

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_destroy_impl, destroy)

template<typename Alloc, typename T>
  struct has_member_destroy
    : has_member_destroy_impl<Alloc, void(T*)>
{};

__thrust_exec_check_disable__
template<typename Alloc, typename T>
  inline __host__ __device__
    typename enable_if<
      has_member_destroy<Alloc,T>::value
    >::type
      destroy(Alloc &a, T *p)
{
  a.destroy(p);
}

__thrust_exec_check_disable__
template<typename Alloc, typename T>
  inline __host__ __device__
    typename disable_if<
      has_member_destroy<Alloc,T>::value
    >::type
      destroy(Alloc &, T *p)
{
  p->~T();
}

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_max_size_impl, max_size)

template<typename Alloc>
  class has_member_max_size
{
  typedef typename allocator_traits<Alloc>::size_type size_type;

  public:
    typedef typename has_member_max_size_impl<Alloc, size_type(void)>::type type;
    static const bool value = type::value;
};

template<typename Alloc>
__host__ __device__
  typename enable_if<
    has_member_max_size<Alloc>::value,
    typename allocator_traits<Alloc>::size_type
  >::type
    max_size(const Alloc &a)
{
  return a.max_size();
}

template<typename Alloc>
__host__ __device__
  typename disable_if<
    has_member_max_size<Alloc>::value,
    typename allocator_traits<Alloc>::size_type
  >::type
    max_size(const Alloc &)
{
  typedef typename allocator_traits<Alloc>::size_type size_type;
  return thrust::detail::integer_traits<size_type>::const_max;
}

template<typename Alloc>
__host__ __device__
  typename enable_if<
    has_member_system<Alloc>::value,
    typename allocator_system<Alloc>::type &
  >::type
    system(Alloc &a)
{
  // return the allocator's system
  return a.system();
}

template<typename Alloc>
__host__ __device__
  typename disable_if<
    has_member_system<Alloc>::value,
    typename allocator_system<Alloc>::type
  >::type
    system(Alloc &)
{
  // return a copy of a value-initialized system
  return typename allocator_system<Alloc>::type();
}

} // end allocator_traits_detail

template<typename Alloc>
__host__ __device__
  typename allocator_traits<Alloc>::pointer
    allocator_traits<Alloc>
      ::allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n)
{
  struct workaround_warnings
  {
    __thrust_exec_check_disable__
    static __host__ __device__
    typename allocator_traits<Alloc>::pointer
      allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n)
    {
      return a.allocate(n);
    }
  };

  return workaround_warnings::allocate(a, n);
}

template<typename Alloc>
__host__ __device__
  typename allocator_traits<Alloc>::pointer
    allocator_traits<Alloc>
      ::allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n, typename allocator_traits<Alloc>::const_void_pointer hint)
{
  return allocator_traits_detail::allocate(a, n, hint);
}

template<typename Alloc>
__host__ __device__
  void allocator_traits<Alloc>
    ::deallocate(Alloc &a, typename allocator_traits<Alloc>::pointer p, typename allocator_traits<Alloc>::size_type n)
{
  struct workaround_warnings
  {
    __thrust_exec_check_disable__
    static __host__ __device__
    void deallocate(Alloc &a, typename allocator_traits<Alloc>::pointer p, typename allocator_traits<Alloc>::size_type n)
    {
      return a.deallocate(p,n);
    }
  };

  return workaround_warnings::deallocate(a,p,n);
}

template<typename Alloc>
  template<typename T>
  __host__ __device__
    void allocator_traits<Alloc>
      ::construct(allocator_type &a, T *p)
{
  return allocator_traits_detail::construct(a,p);
}

template<typename Alloc>
  template<typename T, typename Arg1>
  __host__ __device__
    void allocator_traits<Alloc>
      ::construct(allocator_type &a, T *p, const Arg1 &arg1)
{
  return allocator_traits_detail::construct(a,p,arg1);
}

#if THRUST_CPP_DIALECT >= 2011

template<typename Alloc>
  template<typename T, typename... Args>
  __host__ __device__
    void allocator_traits<Alloc>
      ::construct(allocator_type &a, T *p, Args&&... args)
{
  return allocator_traits_detail::construct(a, p, THRUST_FWD(args)...);
}

#endif

template<typename Alloc>
  template<typename T>
  __host__ __device__
    void allocator_traits<Alloc>
      ::destroy(allocator_type &a, T *p)
{
  return allocator_traits_detail::destroy(a,p);
}

template<typename Alloc>
__host__ __device__
  typename allocator_traits<Alloc>::size_type
    allocator_traits<Alloc>
      ::max_size(const allocator_type &a)
{
  return allocator_traits_detail::max_size(a);
}

template<typename Alloc>
__host__ __device__
  typename allocator_system<Alloc>::get_result_type
    allocator_system<Alloc>
      ::get(Alloc &a)
{
  return allocator_traits_detail::system(a);
}

} // end detail
} // end thrust

<commit_msg>Handle deprecated C++17 std::allocator API.<commit_after>/*
 *  Copyright 2008-2018 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <thrust/detail/config.h>
#include <thrust/detail/allocator/allocator_traits.h>
#include <thrust/detail/type_traits/is_call_possible.h>
#include <thrust/detail/integer_traits.h>

#if THRUST_CPP_DIALECT >= 2011
  #include <thrust/detail/type_deduction.h>
#endif

#include <memory>
#include <new>

namespace thrust
{
namespace detail
{

#if THRUST_CPP_DIALECT >= 2011

// std::allocator's member functions are deprecated in C++17 and removed in
// C++20, so we can't just use the generic implementation for allocator_traits
// that calls the allocator's member functions.
// Instead, specialize allocator_traits for std::allocator and defer to
// std::allocator_traits<std::allocator> and let the STL do whatever it needs
// to for the current c++ version. Manually forward the calls to suppress
// host/device warnings.
template <typename T>
struct allocator_traits<std::allocator<T>>
  : public std::allocator_traits<std::allocator<T>>
{
private:
  using superclass = std::allocator_traits<std::allocator<T>>;

public:
  using allocator_type = typename superclass::allocator_type;
  using value_type = typename superclass::value_type;
  using pointer = typename superclass::pointer;
  using const_pointer = typename superclass::const_pointer;
  using void_pointer = typename superclass::void_pointer;
  using const_void_pointer = typename superclass::const_void_pointer;
  using difference_type = typename superclass::difference_type;
  using size_type = typename superclass::size_type;
  using propagate_on_container_swap = typename superclass::propagate_on_container_swap;
  using propagate_on_container_copy_assignment =
    typename superclass::propagate_on_container_copy_assignment;
  using propagate_on_container_move_assignment =
    typename superclass::propagate_on_container_move_assignment;

  // std::allocator_traits added this in C++17, but thrust::allocator_traits defines
  // it unconditionally.
  using is_always_equal = typename eval_if<
      allocator_traits_detail::has_is_always_equal<allocator_type>::value,
      allocator_traits_detail::nested_is_always_equal<allocator_type>,
      is_empty<allocator_type>
    >::type;

  template <typename U>
  using rebind_alloc = std::allocator<U>;
  template <typename U>
  using rebind_traits = allocator_traits<std::allocator<U>>;

  __thrust_exec_check_disable__
  __host__ __device__
  static pointer allocate(allocator_type &a, size_type n)
  {
    return superclass::allocate(a, n);
  }

  __thrust_exec_check_disable__
  __host__ __device__
  static pointer allocate(allocator_type &a, size_type n, const_void_pointer hint)
  {
    return superclass::allocate(a, n, hint);
  }

  __thrust_exec_check_disable__
  __host__ __device__
  static void deallocate(allocator_type &a, pointer p, size_type n)
  {
    superclass::deallocate(a, p, n);
  }

  __thrust_exec_check_disable__
  template <typename U, typename ...Args>
  __host__ __device__
  static void construct(allocator_type &a, U *p, Args&&... args)
  {
    superclass::construct(a, p, THRUST_FWD(args)...);
  }

  __thrust_exec_check_disable__
  template <typename U>
  __host__ __device__
  static void destroy(allocator_type &a, U *p)
  {
    superclass::destroy(a, p);
  }

  __thrust_exec_check_disable__
  __host__ __device__
  static size_type max_size(const allocator_type &a)
  {
    return superclass::max_size(a);
  }
};

#endif //  C++11

namespace allocator_traits_detail
{

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_allocate_with_hint_impl, allocate)

template<typename Alloc>
  class has_member_allocate_with_hint
{
  typedef typename allocator_traits<Alloc>::pointer            pointer;
  typedef typename allocator_traits<Alloc>::size_type          size_type;
  typedef typename allocator_traits<Alloc>::const_void_pointer const_void_pointer;

  public:
    typedef typename has_member_allocate_with_hint_impl<Alloc, pointer(size_type,const_void_pointer)>::type type;
    static const bool value = type::value;
};

template<typename Alloc>
__host__ __device__
  typename enable_if<
    has_member_allocate_with_hint<Alloc>::value,
    typename allocator_traits<Alloc>::pointer
  >::type
    allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n, typename allocator_traits<Alloc>::const_void_pointer hint)
{
  return a.allocate(n,hint);
}

template<typename Alloc>
__host__ __device__
  typename disable_if<
    has_member_allocate_with_hint<Alloc>::value,
    typename allocator_traits<Alloc>::pointer
  >::type
    allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n, typename allocator_traits<Alloc>::const_void_pointer)
{
  return a.allocate(n);
}

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_construct1_impl, construct)

template<typename Alloc, typename T>
  struct has_member_construct1
    : has_member_construct1_impl<Alloc, void(T*)>
{};

__thrust_exec_check_disable__
template<typename Alloc, typename T>
  inline __host__ __device__
    typename enable_if<
      has_member_construct1<Alloc,T>::value
    >::type
      construct(Alloc &a, T *p)
{
  a.construct(p);
}

__thrust_exec_check_disable__
template<typename Alloc, typename T>
  inline __host__ __device__
    typename disable_if<
      has_member_construct1<Alloc,T>::value
    >::type
      construct(Alloc &, T *p)
{
  ::new(static_cast<void*>(p)) T();
}

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_construct2_impl, construct)

template<typename Alloc, typename T, typename Arg1>
  struct has_member_construct2
    : has_member_construct2_impl<Alloc, void(T*,const Arg1 &)>
{};

__thrust_exec_check_disable__
template<typename Alloc, typename T, typename Arg1>
  inline __host__ __device__
    typename enable_if<
      has_member_construct2<Alloc,T,Arg1>::value
    >::type
      construct(Alloc &a, T *p, const Arg1 &arg1)
{
  a.construct(p,arg1);
}

__thrust_exec_check_disable__
template<typename Alloc, typename T, typename Arg1>
  inline __host__ __device__
    typename disable_if<
      has_member_construct2<Alloc,T,Arg1>::value
    >::type
      construct(Alloc &, T *p, const Arg1 &arg1)
{
  ::new(static_cast<void*>(p)) T(arg1);
}

#if THRUST_CPP_DIALECT >= 2011

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_constructN_impl, construct)

template<typename Alloc, typename T, typename... Args>
  struct has_member_constructN
    : has_member_constructN_impl<Alloc, void(T*, Args...)>
{};

__thrust_exec_check_disable__
template<typename Alloc, typename T, typename... Args>
  inline __host__ __device__
    typename enable_if<
      has_member_constructN<Alloc, T, Args...>::value
    >::type
      construct(Alloc &a, T* p, Args&&... args)
{
  a.construct(p, THRUST_FWD(args)...);
}

__thrust_exec_check_disable__
template<typename Alloc, typename T, typename... Args>
  inline __host__ __device__
    typename disable_if<
      has_member_constructN<Alloc, T, Args...>::value
    >::type
      construct(Alloc &, T* p, Args&&... args)
{
  ::new(static_cast<void*>(p)) T(THRUST_FWD(args)...);
}

#endif

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_destroy_impl, destroy)

template<typename Alloc, typename T>
  struct has_member_destroy
    : has_member_destroy_impl<Alloc, void(T*)>
{};

__thrust_exec_check_disable__
template<typename Alloc, typename T>
  inline __host__ __device__
    typename enable_if<
      has_member_destroy<Alloc,T>::value
    >::type
      destroy(Alloc &a, T *p)
{
  a.destroy(p);
}

__thrust_exec_check_disable__
template<typename Alloc, typename T>
  inline __host__ __device__
    typename disable_if<
      has_member_destroy<Alloc,T>::value
    >::type
      destroy(Alloc &, T *p)
{
  p->~T();
}

__THRUST_DEFINE_IS_CALL_POSSIBLE(has_member_max_size_impl, max_size)

template<typename Alloc>
  class has_member_max_size
{
  typedef typename allocator_traits<Alloc>::size_type size_type;

  public:
    typedef typename has_member_max_size_impl<Alloc, size_type(void)>::type type;
    static const bool value = type::value;
};

template<typename Alloc>
__host__ __device__
  typename enable_if<
    has_member_max_size<Alloc>::value,
    typename allocator_traits<Alloc>::size_type
  >::type
    max_size(const Alloc &a)
{
  return a.max_size();
}

template<typename Alloc>
__host__ __device__
  typename disable_if<
    has_member_max_size<Alloc>::value,
    typename allocator_traits<Alloc>::size_type
  >::type
    max_size(const Alloc &)
{
  typedef typename allocator_traits<Alloc>::size_type size_type;
  return thrust::detail::integer_traits<size_type>::const_max;
}

template<typename Alloc>
__host__ __device__
  typename enable_if<
    has_member_system<Alloc>::value,
    typename allocator_system<Alloc>::type &
  >::type
    system(Alloc &a)
{
  // return the allocator's system
  return a.system();
}

template<typename Alloc>
__host__ __device__
  typename disable_if<
    has_member_system<Alloc>::value,
    typename allocator_system<Alloc>::type
  >::type
    system(Alloc &)
{
  // return a copy of a value-initialized system
  return typename allocator_system<Alloc>::type();
}

} // end allocator_traits_detail

template<typename Alloc>
__host__ __device__
  typename allocator_traits<Alloc>::pointer
    allocator_traits<Alloc>
      ::allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n)
{
  struct workaround_warnings
  {
    __thrust_exec_check_disable__
    static __host__ __device__
    typename allocator_traits<Alloc>::pointer
      allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n)
    {
      return a.allocate(n);
    }
  };

  return workaround_warnings::allocate(a, n);
}

template<typename Alloc>
__host__ __device__
  typename allocator_traits<Alloc>::pointer
    allocator_traits<Alloc>
      ::allocate(Alloc &a, typename allocator_traits<Alloc>::size_type n, typename allocator_traits<Alloc>::const_void_pointer hint)
{
  return allocator_traits_detail::allocate(a, n, hint);
}

template<typename Alloc>
__host__ __device__
  void allocator_traits<Alloc>
    ::deallocate(Alloc &a, typename allocator_traits<Alloc>::pointer p, typename allocator_traits<Alloc>::size_type n)
{
  struct workaround_warnings
  {
    __thrust_exec_check_disable__
    static __host__ __device__
    void deallocate(Alloc &a, typename allocator_traits<Alloc>::pointer p, typename allocator_traits<Alloc>::size_type n)
    {
      return a.deallocate(p,n);
    }
  };

  return workaround_warnings::deallocate(a,p,n);
}

template<typename Alloc>
  template<typename T>
  __host__ __device__
    void allocator_traits<Alloc>
      ::construct(allocator_type &a, T *p)
{
  return allocator_traits_detail::construct(a,p);
}

template<typename Alloc>
  template<typename T, typename Arg1>
  __host__ __device__
    void allocator_traits<Alloc>
      ::construct(allocator_type &a, T *p, const Arg1 &arg1)
{
  return allocator_traits_detail::construct(a,p,arg1);
}

#if THRUST_CPP_DIALECT >= 2011

template<typename Alloc>
  template<typename T, typename... Args>
  __host__ __device__
    void allocator_traits<Alloc>
      ::construct(allocator_type &a, T *p, Args&&... args)
{
  return allocator_traits_detail::construct(a, p, THRUST_FWD(args)...);
}

#endif

template<typename Alloc>
  template<typename T>
  __host__ __device__
    void allocator_traits<Alloc>
      ::destroy(allocator_type &a, T *p)
{
  return allocator_traits_detail::destroy(a,p);
}

template<typename Alloc>
__host__ __device__
  typename allocator_traits<Alloc>::size_type
    allocator_traits<Alloc>
      ::max_size(const allocator_type &a)
{
  return allocator_traits_detail::max_size(a);
}

template<typename Alloc>
__host__ __device__
  typename allocator_system<Alloc>::get_result_type
    allocator_system<Alloc>
      ::get(Alloc &a)
{
  return allocator_traits_detail::system(a);
}

} // end detail
} // end thrust

<|endoftext|>


<commit_before>/*
 *
 *  Copyright 2008-2010 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <thrust/random/normal_distribution.h>
#include <thrust/random/uniform_real_distribution.h>
#include <thrust/detail/cstdint.h>
#include <thrust/detail/integer_traits.h>

namespace thrust
{

namespace random
{

namespace experimental
{

template<typename RealType>
  normal_distribution<RealType>
    ::normal_distribution(RealType a, RealType b)
      :m_param(a,b)
{
} // end normal_distribution::normal_distribution()

template<typename RealType>
  normal_distribution<RealType>
    ::normal_distribution(const param_type &parm)
      :m_param(parm)
{
} // end normal_distribution::normal_distribution()

template<typename RealType>
  void normal_distribution<RealType>
    ::reset(void)
{
} // end normal_distribution::reset()

template<typename RealType>
  template<typename UniformRandomNumberGenerator>
    typename normal_distribution<RealType>::result_type
      normal_distribution<RealType>
        ::operator()(UniformRandomNumberGenerator &urng)
{
  return operator()(urng, m_param);
} // end normal_distribution::operator()()

template<typename RealType>
  template<typename UniformRandomNumberGenerator>
    typename normal_distribution<RealType>::result_type
      normal_distribution<RealType>
        ::operator()(UniformRandomNumberGenerator &urng,
                     const param_type &parm)
{
  typedef typename UniformRandomNumberGenerator::result_type uint_type;
  const uint_type urng_range = UniformRandomNumberGenerator::max - UniformRandomNumberGenerator::min;

  // Constants for conversion
  const result_type S1 = static_cast<result_type>(1) / urng_range;
  const result_type S2 = S1 / 2;

  result_type S3 = static_cast<result_type>(-1.4142135623730950488016887242097); // -sqrt(2)

  // Get the integer value
  uint_type u = urng() - UniformRandomNumberGenerator::min;

  // Ensure the conversion to float will give a value in the range [0,0.5)
  if(u > (urng_range / 2))
  {
    u = urng_range - u;
    S3 = -S3;
  }

  // Convert to floating point in [0,0.5)
  result_type p = u*S1 + S2;

  // Apply inverse error function
  return parm.first + parm.second * S3 * erfcinv(2 * p);

//  // sample [0,1)
//  thrust::uniform_real_distribution<result_type> u01;
//  result_type z = u01(urng);
//
//  result_type S3 = static_cast<result_type>(-1.4142135623730950488016887242097); // -sqrt(2)
//
//  if(z > 0.5)
//  {
//    z = 1.0f - z;
//    S3 = -S3;
//  }
//
//  // Apply inverse error function
//  return parm.first + parm.second * S3 * erfcinv(2 * z);
} // end normal_distribution::operator()()

template<typename RealType>
  typename normal_distribution<RealType>::param_type
    normal_distribution<RealType>
      ::param(void) const
{
  return m_param;
} // end normal_distribution::param()

template<typename RealType>
  void normal_distribution<RealType>
    ::param(const param_type &parm)
{
  m_param = parm;
} // end normal_distribution::param()

template<typename RealType>
  typename normal_distribution<RealType>::result_type
    normal_distribution<RealType>
      ::min(void) const
{
  // XXX this solution is pretty terrible
  const thrust::detail::uint32_t inf_as_int = 0x7f800000u;
  const float inf = *reinterpret_cast<const float*>(&inf_as_int);
  return result_type(-inf);
} // end normal_distribution::min()

template<typename RealType>
  typename normal_distribution<RealType>::result_type
    normal_distribution<RealType>
      ::max(void) const
{
  // XXX this solution is pretty terrible
  const thrust::detail::uint32_t inf_as_int = 0x7f800000u;
  const float inf = *reinterpret_cast<const float*>(&inf_as_int);
  return result_type(inf);
} // end normal_distribution::max()

template<typename RealType>
  typename normal_distribution<RealType>::result_type
    normal_distribution<RealType>
      ::mean(void) const
{
  return m_param.first;
} // end normal_distribution::mean()

template<typename RealType>
  typename normal_distribution<RealType>::result_type
    normal_distribution<RealType>
      ::stddev(void) const
{
  return m_param.second;
} // end normal_distribution::stddev()

template<typename RealType>
  bool normal_distribution<RealType>
    ::equal(const normal_distribution &rhs) const
{
  return m_param == rhs.param();
}

template<typename RealType>
  template<typename CharT, typename Traits>
    std::basic_ostream<CharT,Traits>&
      normal_distribution<RealType>
        ::stream_out(std::basic_ostream<CharT,Traits> &os) const
{
  typedef std::basic_ostream<CharT,Traits> ostream_type;
  typedef typename ostream_type::ios_base  ios_base;

  // save old flags and fill character
  const typename ios_base::fmtflags flags = os.flags();
  const CharT fill = os.fill();

  const CharT space = os.widen(' ');
  os.flags(ios_base::dec | ios_base::fixed | ios_base::left);
  os.fill(space);

  os << mean() << space << stddev();

  // restore old flags and fill character
  os.flags(flags);
  os.fill(fill);
  return os;
}

template<typename RealType>
  template<typename CharT, typename Traits>
    std::basic_istream<CharT,Traits>&
      normal_distribution<RealType>
        ::stream_in(std::basic_istream<CharT,Traits> &is)
{
  typedef std::basic_istream<CharT,Traits> istream_type;
  typedef typename istream_type::ios_base  ios_base;

  // save old flags
  const typename ios_base::fmtflags flags = is.flags();

  is.flags(ios_base::skipws);

  is >> m_param.first >> m_param.second;

  // restore old flags
  is.flags(flags);
  return is;
}

template<typename RealType>
bool operator==(const normal_distribution<RealType> &lhs,
                const normal_distribution<RealType> &rhs)
{
  return thrust::random::detail::random_core_access::equal(lhs,rhs);
}

template<typename RealType>
bool operator!=(const normal_distribution<RealType> &lhs,
                const normal_distribution<RealType> &rhs)
{
  return !(lhs == rhs);
}

template<typename RealType,
         typename CharT, typename Traits>
std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits> &os,
           const normal_distribution<RealType> &d)
{
  return thrust::random::detail::random_core_access::stream_out(os,d);
}

template<typename RealType,
         typename CharT, typename Traits>
std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits> &is,
           normal_distribution<RealType> &d)
{
  return thrust::random::detail::random_core_access::stream_in(is,d);
}

} // end experimental

} // end random

} // end thrust

<commit_msg>Eliminate commented-out code from normal_distribution's generation function.<commit_after>/*
 *
 *  Copyright 2008-2010 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <thrust/random/normal_distribution.h>
#include <thrust/random/uniform_real_distribution.h>
#include <thrust/detail/cstdint.h>
#include <thrust/detail/integer_traits.h>

namespace thrust
{

namespace random
{

namespace experimental
{

template<typename RealType>
  normal_distribution<RealType>
    ::normal_distribution(RealType a, RealType b)
      :m_param(a,b)
{
} // end normal_distribution::normal_distribution()

template<typename RealType>
  normal_distribution<RealType>
    ::normal_distribution(const param_type &parm)
      :m_param(parm)
{
} // end normal_distribution::normal_distribution()

template<typename RealType>
  void normal_distribution<RealType>
    ::reset(void)
{
} // end normal_distribution::reset()

template<typename RealType>
  template<typename UniformRandomNumberGenerator>
    typename normal_distribution<RealType>::result_type
      normal_distribution<RealType>
        ::operator()(UniformRandomNumberGenerator &urng)
{
  return operator()(urng, m_param);
} // end normal_distribution::operator()()

template<typename RealType>
  template<typename UniformRandomNumberGenerator>
    typename normal_distribution<RealType>::result_type
      normal_distribution<RealType>
        ::operator()(UniformRandomNumberGenerator &urng,
                     const param_type &parm)
{
  typedef typename UniformRandomNumberGenerator::result_type uint_type;
  const uint_type urng_range = UniformRandomNumberGenerator::max - UniformRandomNumberGenerator::min;

  // Constants for conversion
  const result_type S1 = static_cast<result_type>(1) / urng_range;
  const result_type S2 = S1 / 2;

  result_type S3 = static_cast<result_type>(-1.4142135623730950488016887242097); // -sqrt(2)

  // Get the integer value
  uint_type u = urng() - UniformRandomNumberGenerator::min;

  // Ensure the conversion to float will give a value in the range [0,0.5)
  if(u > (urng_range / 2))
  {
    u = urng_range - u;
    S3 = -S3;
  }

  // Convert to floating point in [0,0.5)
  result_type p = u*S1 + S2;

  // Apply inverse error function
  return parm.first + parm.second * S3 * erfcinv(2 * p);
} // end normal_distribution::operator()()

template<typename RealType>
  typename normal_distribution<RealType>::param_type
    normal_distribution<RealType>
      ::param(void) const
{
  return m_param;
} // end normal_distribution::param()

template<typename RealType>
  void normal_distribution<RealType>
    ::param(const param_type &parm)
{
  m_param = parm;
} // end normal_distribution::param()

template<typename RealType>
  typename normal_distribution<RealType>::result_type
    normal_distribution<RealType>
      ::min(void) const
{
  // XXX this solution is pretty terrible
  const thrust::detail::uint32_t inf_as_int = 0x7f800000u;
  const float inf = *reinterpret_cast<const float*>(&inf_as_int);
  return result_type(-inf);
} // end normal_distribution::min()

template<typename RealType>
  typename normal_distribution<RealType>::result_type
    normal_distribution<RealType>
      ::max(void) const
{
  // XXX this solution is pretty terrible
  const thrust::detail::uint32_t inf_as_int = 0x7f800000u;
  const float inf = *reinterpret_cast<const float*>(&inf_as_int);
  return result_type(inf);
} // end normal_distribution::max()

template<typename RealType>
  typename normal_distribution<RealType>::result_type
    normal_distribution<RealType>
      ::mean(void) const
{
  return m_param.first;
} // end normal_distribution::mean()

template<typename RealType>
  typename normal_distribution<RealType>::result_type
    normal_distribution<RealType>
      ::stddev(void) const
{
  return m_param.second;
} // end normal_distribution::stddev()

template<typename RealType>
  bool normal_distribution<RealType>
    ::equal(const normal_distribution &rhs) const
{
  return m_param == rhs.param();
}

template<typename RealType>
  template<typename CharT, typename Traits>
    std::basic_ostream<CharT,Traits>&
      normal_distribution<RealType>
        ::stream_out(std::basic_ostream<CharT,Traits> &os) const
{
  typedef std::basic_ostream<CharT,Traits> ostream_type;
  typedef typename ostream_type::ios_base  ios_base;

  // save old flags and fill character
  const typename ios_base::fmtflags flags = os.flags();
  const CharT fill = os.fill();

  const CharT space = os.widen(' ');
  os.flags(ios_base::dec | ios_base::fixed | ios_base::left);
  os.fill(space);

  os << mean() << space << stddev();

  // restore old flags and fill character
  os.flags(flags);
  os.fill(fill);
  return os;
}

template<typename RealType>
  template<typename CharT, typename Traits>
    std::basic_istream<CharT,Traits>&
      normal_distribution<RealType>
        ::stream_in(std::basic_istream<CharT,Traits> &is)
{
  typedef std::basic_istream<CharT,Traits> istream_type;
  typedef typename istream_type::ios_base  ios_base;

  // save old flags
  const typename ios_base::fmtflags flags = is.flags();

  is.flags(ios_base::skipws);

  is >> m_param.first >> m_param.second;

  // restore old flags
  is.flags(flags);
  return is;
}

template<typename RealType>
bool operator==(const normal_distribution<RealType> &lhs,
                const normal_distribution<RealType> &rhs)
{
  return thrust::random::detail::random_core_access::equal(lhs,rhs);
}

template<typename RealType>
bool operator!=(const normal_distribution<RealType> &lhs,
                const normal_distribution<RealType> &rhs)
{
  return !(lhs == rhs);
}

template<typename RealType,
         typename CharT, typename Traits>
std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits> &os,
           const normal_distribution<RealType> &d)
{
  return thrust::random::detail::random_core_access::stream_out(os,d);
}

template<typename RealType,
         typename CharT, typename Traits>
std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits> &is,
           normal_distribution<RealType> &d)
{
  return thrust::random::detail::random_core_access::stream_in(is,d);
}

} // end experimental

} // end random

} // end thrust

<|endoftext|>


<commit_before>// ///////////////////////////////////////////////////////////////////////////
// tenh/mathutil.hpp by Ted Nitz, created 2013/08/15
// Copyright Leap Motion Inc.
// ///////////////////////////////////////////////////////////////////////////

#ifndef TENH_MATHUTIL_HPP_
#define TENH_MATHUTIL_HPP_

#include "tenh/core.hpp"
#include "tenh/meta/lvd.hpp"

// TODO: Decide if/how this code should be split amongst files.
namespace Tenh {

using Lvd::Meta::If;

Uint32 factorial(Uint32 x)
{
    return (x > 0) ? factorial(x-1) * x : 1;
}

template<Uint32 X>
struct Factorial_t
{
    static const Uint32 V = (X > 0) ? Factorial_t<X-1>::V * X : 1;
};

Uint32 binomial_coefficient(Uint32 n, Uint32 k)
{
  return (k == 0) ? 1 : binomial_coefficient(n,k-1) * (n - k + 1) / k;
}

template<Uint32 N, Uint32 K>
struct BinomialCoefficient_t
{
    static const Uint32 V = (K == 0) ? 1 : BinomialCoefficient_t<N,K-1>::V * (N - K + 1) / K;
};

Uint32 index_of_greatest_triangular_number_less_than(Uint32 x, Uint32 d, Uint32 iteration = 0)
{
    return (binomial_coefficient(iteration,d) > x) ? iteration - 1 : index_of_greatest_triangular_number_less_than(x,d,iteration+1);
}

template<Uint32 N>
struct TemplateInt
{
    static const Uint32 V = N;
};

template<Uint32 X, Uint32 D, Uint32 iteration=0>
struct IndexOfGreatestTriangularNumberLessThan_t
{
    static const Uint32 V = If<(BinomialCoefficient_t<iteration,D>::V > X), TemplateInt<iteration - 1>, IndexOfGreatestTriangularNumberLessThan_t<X,D,iteration+1> >::T::V;
};

} // end of namespace Tenh

#endif // TENH_MATHUTIL_HPP_
<commit_msg>Fix Factorial_t and BinomialCoefficient_t to not recurse infinitely.<commit_after>// ///////////////////////////////////////////////////////////////////////////
// tenh/mathutil.hpp by Ted Nitz, created 2013/08/15
// Copyright Leap Motion Inc.
// ///////////////////////////////////////////////////////////////////////////

#ifndef TENH_MATHUTIL_HPP_
#define TENH_MATHUTIL_HPP_

#include "tenh/core.hpp"
#include "tenh/meta/lvd.hpp"

// TODO: Decide if/how this code should be split amongst files.
namespace Tenh {

using Lvd::Meta::If;

Uint32 factorial(Uint32 x)
{
    return (x > 0) ? factorial(x-1) * x : 1;
}

template<Uint32 X>
struct Factorial_t
{
    static const Uint32 V = Factorial_t<X-1>::V * X;
};

template<>
struct Factorial_t<0>
{
    static const Uint32 V = 1;
};

Uint32 binomial_coefficient(Uint32 n, Uint32 k)
{
  return (k == 0) ? 1 : binomial_coefficient(n,k-1) * (n - k + 1) / k;
}

template<Uint32 N, Uint32 K>
struct BinomialCoefficient_t
{
    static const Uint32 V = BinomialCoefficient_t<N,K-1>::V * (N - K + 1) / K;
};

template<Uint32 N>
struct BinomialCoefficient_t<N,0>
{
    static const Uint32 V = 1 ;
};

Uint32 index_of_greatest_triangular_number_less_than(Uint32 x, Uint32 d, Uint32 iteration = 0)
{
    return (binomial_coefficient(iteration,d) > x) ? iteration - 1 : index_of_greatest_triangular_number_less_than(x,d,iteration+1);
}

template<Uint32 N>
struct TemplateInt
{
    static const Uint32 V = N;
};

template<Uint32 X, Uint32 D, Uint32 iteration=0>
struct IndexOfGreatestTriangularNumberLessThan_t
{
    static const Uint32 V = If<(BinomialCoefficient_t<iteration,D>::V > X), TemplateInt<iteration - 1>, IndexOfGreatestTriangularNumberLessThan_t<X,D,iteration+1> >::T::V;
};

} // end of namespace Tenh

#endif // TENH_MATHUTIL_HPP_
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libetonyek project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "IWAMessage.h"

#include <cassert>
#include <memory>

namespace libetonyek
{

using std::make_pair;

namespace
{

struct AccessError {};
struct ParseError {};

}

IWAMessage::Field::Field(const IWAMessage::WireType wireType)
  : m_wireType(wireType)
  , m_pieces()
  , m_realField()
{
}

IWAMessage::IWAMessage()
  : m_input()
  , m_fields()
{
}

IWAMessage::IWAMessage(const RVNGInputStreamPtr_t &input, unsigned long length)
  : m_input(input)
  , m_fields()
{
  if (length == 0)
    return;

  parse(length);
}

IWAMessage::IWAMessage(const RVNGInputStreamPtr_t &input, const long start, const long end)
  : m_input(input)
  , m_fields()
{
  if (end==start) return; // rare, but ok
  assert(end > start);

  if (input->seek(start, librevenge::RVNG_SEEK_SET) == 0)
    parse(static_cast<unsigned long>(end - start));
}

void IWAMessage::parse(const unsigned long length) try
{
  assert(bool(m_input));

  const long startPos = m_input->tell();
  while (!m_input->isEnd() && (length > static_cast<unsigned long>(m_input->tell() - startPos)))
  {
    const auto spec = unsigned(readUVar(m_input));
    const unsigned wireType = spec & 0x7;

    long start = m_input->tell();

    switch (wireType)
    {
    case 0:
      readUVar(m_input);
      break;
    case 1:
      readU64(m_input);
      break;
    case 2:
    {
      const uint64_t len = readUVar(m_input);
      start = m_input->tell(); // the field parser expects just the actual data
      if (m_input->seek((long) len, librevenge::RVNG_SEEK_CUR) != 0)
        throw ParseError();
      break;
    }
    case 5:
      readU32(m_input);
      break;
    default:
      ETONYEK_DEBUG_MSG(("IWAMessage::IWAMessage: unexpected wire type %d\n", wireType));
      throw ParseError();
    }

    const long end = m_input->tell();
    if (length >= static_cast<unsigned long>(end - startPos))
    {
      const unsigned field = spec >> 3;
      auto it = m_fields.find(field);
      if ((it != m_fields.end()) && (it->second.m_wireType != WireType(wireType)))
      {
        ETONYEK_DEBUG_MSG(("IWAMessage::IWAMessage: wire type %d of field %d does not match previously seen %d\n", wireType, field, it->second.m_wireType));
        continue;
      }
      if (it == m_fields.end())
        it = m_fields.insert(make_pair(field, Field(WireType(wireType)))).first;
      assert(it != m_fields.end());
      it->second.m_pieces.push_back(make_pair(start, end));
    }
  }
}
catch (...)
{
  // The format is quite robust: a small damage like a bit flip
  // cannot break more than a single message and there is a good
  // chance that it will not affect parsing significantly. So we try
  // to get as much data as possible, ignoring parsing errors.
}

const IWAUInt32Field &IWAMessage::uint32(const std::size_t field) const
{
  return getField<IWAUInt32Field>(field, WIRE_TYPE_VARINT, IWAField::TAG_UINT32);
}

const IWAUInt64Field &IWAMessage::uint64(const std::size_t field) const
{
  return getField<IWAUInt64Field>(field, WIRE_TYPE_VARINT, IWAField::TAG_UINT64);
}

const IWASInt32Field &IWAMessage::sint32(const std::size_t field) const
{
  return getField<IWASInt32Field>(field, WIRE_TYPE_VARINT, IWAField::TAG_SINT32);
}

const IWASInt64Field &IWAMessage::sint64(const std::size_t field) const
{
  return getField<IWASInt64Field>(field, WIRE_TYPE_VARINT, IWAField::TAG_SINT64);
}

const IWABoolField &IWAMessage::bool_(const std::size_t field) const
{
  return getField<IWABoolField>(field, WIRE_TYPE_VARINT, IWAField::TAG_BOOL);
}

const IWAFixed64Field &IWAMessage::fixed64(const std::size_t field) const
{
  return getField<IWAFixed64Field>(field, WIRE_TYPE_64_BIT, IWAField::TAG_FIXED64);
}

const IWADoubleField &IWAMessage::double_(const std::size_t field) const
{
  return getField<IWADoubleField>(field, WIRE_TYPE_64_BIT, IWAField::TAG_DOUBLE);
}

const IWAStringField &IWAMessage::string(const std::size_t field) const
{
  return getField<IWAStringField>(field, WIRE_TYPE_LENGTH_DELIMITED, IWAField::TAG_STRING);
}

const IWABytesField &IWAMessage::bytes(const std::size_t field) const
{
  return getField<IWABytesField>(field, WIRE_TYPE_LENGTH_DELIMITED, IWAField::TAG_BYTES);
}

const IWAMessageField &IWAMessage::message(const std::size_t field) const
{
  return getField<IWAMessageField>(field, WIRE_TYPE_LENGTH_DELIMITED, IWAField::TAG_MESSAGE);
}

const IWAFixed32Field &IWAMessage::fixed32(const std::size_t field) const
{
  return getField<IWAFixed32Field>(field, WIRE_TYPE_32_BIT, IWAField::TAG_FIXED32);
}

const IWAFloatField &IWAMessage::float_(const std::size_t field) const
{
  return getField<IWAFloatField>(field, WIRE_TYPE_32_BIT, IWAField::TAG_FLOAT);
}

template<typename FieldT>
const FieldT &IWAMessage::getField(const std::size_t field, const WireType wireType, const IWAField::Tag tag) const
{
  const FieldList_t::iterator fieldIt = m_fields.find((unsigned) field);

  if (fieldIt == m_fields.end())
  {
    static FieldT dummy;
    return dummy;
  }

  if (fieldIt->second.m_wireType != wireType)
  {
    if (fieldIt->second.m_wireType != WIRE_TYPE_LENGTH_DELIMITED)
      throw AccessError();
  }

  if (bool(fieldIt->second.m_realField))
  {
    if (fieldIt->second.m_realField->tag() != tag)
      throw AccessError();
  }
  else
  {
    fieldIt->second.m_realField = std::make_shared<FieldT>();
    for (std::deque<InputRange_t>::const_iterator it = fieldIt->second.m_pieces.begin(); it != fieldIt->second.m_pieces.end(); ++it)
    {
      assert(bool(m_input));
      m_input->seek(it->first, librevenge::RVNG_SEEK_SET);
      fieldIt->second.m_realField->parse(m_input, static_cast<unsigned long>(it->second - m_input->tell()), wireType == WIRE_TYPE_LENGTH_DELIMITED);
    }
  }

  return static_cast<FieldT &>(*fieldIt->second.m_realField);
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>move assert to the beginning of the function<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libetonyek project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "IWAMessage.h"

#include <cassert>
#include <memory>

namespace libetonyek
{

using std::make_pair;

namespace
{

struct AccessError {};
struct ParseError {};

}

IWAMessage::Field::Field(const IWAMessage::WireType wireType)
  : m_wireType(wireType)
  , m_pieces()
  , m_realField()
{
}

IWAMessage::IWAMessage()
  : m_input()
  , m_fields()
{
}

IWAMessage::IWAMessage(const RVNGInputStreamPtr_t &input, unsigned long length)
  : m_input(input)
  , m_fields()
{
  if (length == 0)
    return;

  parse(length);
}

IWAMessage::IWAMessage(const RVNGInputStreamPtr_t &input, const long start, const long end)
  : m_input(input)
  , m_fields()
{
  assert(end >= start);

  if (end==start) return; // rare, but ok

  if (input->seek(start, librevenge::RVNG_SEEK_SET) == 0)
    parse(static_cast<unsigned long>(end - start));
}

void IWAMessage::parse(const unsigned long length) try
{
  assert(bool(m_input));

  const long startPos = m_input->tell();
  while (!m_input->isEnd() && (length > static_cast<unsigned long>(m_input->tell() - startPos)))
  {
    const auto spec = unsigned(readUVar(m_input));
    const unsigned wireType = spec & 0x7;

    long start = m_input->tell();

    switch (wireType)
    {
    case 0:
      readUVar(m_input);
      break;
    case 1:
      readU64(m_input);
      break;
    case 2:
    {
      const uint64_t len = readUVar(m_input);
      start = m_input->tell(); // the field parser expects just the actual data
      if (m_input->seek((long) len, librevenge::RVNG_SEEK_CUR) != 0)
        throw ParseError();
      break;
    }
    case 5:
      readU32(m_input);
      break;
    default:
      ETONYEK_DEBUG_MSG(("IWAMessage::IWAMessage: unexpected wire type %d\n", wireType));
      throw ParseError();
    }

    const long end = m_input->tell();
    if (length >= static_cast<unsigned long>(end - startPos))
    {
      const unsigned field = spec >> 3;
      auto it = m_fields.find(field);
      if ((it != m_fields.end()) && (it->second.m_wireType != WireType(wireType)))
      {
        ETONYEK_DEBUG_MSG(("IWAMessage::IWAMessage: wire type %d of field %d does not match previously seen %d\n", wireType, field, it->second.m_wireType));
        continue;
      }
      if (it == m_fields.end())
        it = m_fields.insert(make_pair(field, Field(WireType(wireType)))).first;
      assert(it != m_fields.end());
      it->second.m_pieces.push_back(make_pair(start, end));
    }
  }
}
catch (...)
{
  // The format is quite robust: a small damage like a bit flip
  // cannot break more than a single message and there is a good
  // chance that it will not affect parsing significantly. So we try
  // to get as much data as possible, ignoring parsing errors.
}

const IWAUInt32Field &IWAMessage::uint32(const std::size_t field) const
{
  return getField<IWAUInt32Field>(field, WIRE_TYPE_VARINT, IWAField::TAG_UINT32);
}

const IWAUInt64Field &IWAMessage::uint64(const std::size_t field) const
{
  return getField<IWAUInt64Field>(field, WIRE_TYPE_VARINT, IWAField::TAG_UINT64);
}

const IWASInt32Field &IWAMessage::sint32(const std::size_t field) const
{
  return getField<IWASInt32Field>(field, WIRE_TYPE_VARINT, IWAField::TAG_SINT32);
}

const IWASInt64Field &IWAMessage::sint64(const std::size_t field) const
{
  return getField<IWASInt64Field>(field, WIRE_TYPE_VARINT, IWAField::TAG_SINT64);
}

const IWABoolField &IWAMessage::bool_(const std::size_t field) const
{
  return getField<IWABoolField>(field, WIRE_TYPE_VARINT, IWAField::TAG_BOOL);
}

const IWAFixed64Field &IWAMessage::fixed64(const std::size_t field) const
{
  return getField<IWAFixed64Field>(field, WIRE_TYPE_64_BIT, IWAField::TAG_FIXED64);
}

const IWADoubleField &IWAMessage::double_(const std::size_t field) const
{
  return getField<IWADoubleField>(field, WIRE_TYPE_64_BIT, IWAField::TAG_DOUBLE);
}

const IWAStringField &IWAMessage::string(const std::size_t field) const
{
  return getField<IWAStringField>(field, WIRE_TYPE_LENGTH_DELIMITED, IWAField::TAG_STRING);
}

const IWABytesField &IWAMessage::bytes(const std::size_t field) const
{
  return getField<IWABytesField>(field, WIRE_TYPE_LENGTH_DELIMITED, IWAField::TAG_BYTES);
}

const IWAMessageField &IWAMessage::message(const std::size_t field) const
{
  return getField<IWAMessageField>(field, WIRE_TYPE_LENGTH_DELIMITED, IWAField::TAG_MESSAGE);
}

const IWAFixed32Field &IWAMessage::fixed32(const std::size_t field) const
{
  return getField<IWAFixed32Field>(field, WIRE_TYPE_32_BIT, IWAField::TAG_FIXED32);
}

const IWAFloatField &IWAMessage::float_(const std::size_t field) const
{
  return getField<IWAFloatField>(field, WIRE_TYPE_32_BIT, IWAField::TAG_FLOAT);
}

template<typename FieldT>
const FieldT &IWAMessage::getField(const std::size_t field, const WireType wireType, const IWAField::Tag tag) const
{
  const FieldList_t::iterator fieldIt = m_fields.find((unsigned) field);

  if (fieldIt == m_fields.end())
  {
    static FieldT dummy;
    return dummy;
  }

  if (fieldIt->second.m_wireType != wireType)
  {
    if (fieldIt->second.m_wireType != WIRE_TYPE_LENGTH_DELIMITED)
      throw AccessError();
  }

  if (bool(fieldIt->second.m_realField))
  {
    if (fieldIt->second.m_realField->tag() != tag)
      throw AccessError();
  }
  else
  {
    fieldIt->second.m_realField = std::make_shared<FieldT>();
    for (std::deque<InputRange_t>::const_iterator it = fieldIt->second.m_pieces.begin(); it != fieldIt->second.m_pieces.end(); ++it)
    {
      assert(bool(m_input));
      m_input->seek(it->first, librevenge::RVNG_SEEK_SET);
      fieldIt->second.m_realField->parse(m_input, static_cast<unsigned long>(it->second - m_input->tell()), wireType == WIRE_TYPE_LENGTH_DELIMITED);
    }
  }

  return static_cast<FieldT &>(*fieldIt->second.m_realField);
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libpagemaker project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <libpagemaker/libpagemaker.h>

#include "PMDCollector.h"
#include "PMDParser.h"
#include "libpagemaker_utils.h"

namespace libpagemaker
{

bool PMDocument::isSupported(librevenge::RVNGInputStream * /*input*/) try
{
  // TODO: Fix this.
  return true;
}
catch (...)
{
  return false;
}

bool PMDocument::parse(librevenge::RVNGInputStream *input, librevenge::RVNGDrawingInterface *painter)
{
  PMDCollector collector;
  PMD_DEBUG_MSG(("About to start parsing...\n"));
  PMDParser(input->getSubStreamByName("PageMaker"), &collector).parse();
  PMD_DEBUG_MSG(("About to start drawing...\n"));
  collector.draw(painter);
  return true;
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>Take ownership of the RVNGInputStream so it's not leaked.<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libpagemaker project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <libpagemaker/libpagemaker.h>

#include <boost/scoped_ptr.hpp>

#include "PMDCollector.h"
#include "PMDParser.h"
#include "libpagemaker_utils.h"

namespace libpagemaker
{

bool PMDocument::isSupported(librevenge::RVNGInputStream * /*input*/) try
{
  // TODO: Fix this.
  return true;
}
catch (...)
{
  return false;
}

bool PMDocument::parse(librevenge::RVNGInputStream *input, librevenge::RVNGDrawingInterface *painter)
{
  PMDCollector collector;
  PMD_DEBUG_MSG(("About to start parsing...\n"));
  boost::scoped_ptr<librevenge::RVNGInputStream>
    pmdStream(input->getSubStreamByName("PageMaker"));
  PMDParser(pmdStream.get(), &collector).parse();
  PMD_DEBUG_MSG(("About to start drawing...\n"));
  collector.draw(painter);
  return true;
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>