<commit_before>/*************************************************************************
 *
 *  $RCSfile: multi.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-18 13:28:47 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef INCLUDED_testtools_source_bridgetest_multi_hxx
#define INCLUDED_testtools_source_bridgetest_multi_hxx

#include "sal/config.h"

#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "cppuhelper/implbase1.hxx"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "test/testtools/bridgetest/XMulti.hpp"

namespace testtools { namespace bridgetest {

class Multi: public cppu::WeakImplHelper1< test::testtools::bridgetest::XMulti >
{
public:
    Multi(): m_attribute1(0.0), m_attribute3(0.0) {}

    virtual double SAL_CALL getatt1()
        throw (com::sun::star::uno::RuntimeException)
    { return m_attribute1; }

    virtual void SAL_CALL setatt1(double value)
        throw (com::sun::star::uno::RuntimeException)
    { m_attribute1 = value; }

    virtual sal_Int32 SAL_CALL fn11(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 11 * arg; }

    virtual rtl::OUString SAL_CALL fn12(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("12") + arg; }

    virtual sal_Int32 SAL_CALL fn21(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 21 * arg; }

    virtual rtl::OUString SAL_CALL fn22(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("22") + arg; }

    virtual double SAL_CALL getatt3()
        throw (com::sun::star::uno::RuntimeException)
    { return m_attribute3; }

    virtual void SAL_CALL setatt3(double value)
        throw (com::sun::star::uno::RuntimeException)
    { m_attribute3 = value; }

    virtual sal_Int32 SAL_CALL fn31(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 31 * arg; }

    virtual rtl::OUString SAL_CALL fn32(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("32") + arg; }

    virtual sal_Int32 SAL_CALL fn33()
        throw (com::sun::star::uno::RuntimeException)
    { return 33; }

    virtual sal_Int32 SAL_CALL fn41(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 41 * arg; }

    virtual sal_Int32 SAL_CALL fn61(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 61 * arg; }

    virtual rtl::OUString SAL_CALL fn62(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("62") + arg; }

    virtual sal_Int32 SAL_CALL fn71(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 71 * arg; }

    virtual rtl::OUString SAL_CALL fn72(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("72") + arg; }

    virtual sal_Int32 SAL_CALL fn73()
        throw (com::sun::star::uno::RuntimeException)
    { return 73; }

private:
    double m_attribute1;
    double m_attribute3;
};

rtl::OUString testMulti(
    com::sun::star::uno::Reference< test::testtools::bridgetest::XMulti >
    const & multi);

} }

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.18); FILE MERGED 2005/09/05 17:00:53 rt 1.3.18.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: multi.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 12:22:54 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef INCLUDED_testtools_source_bridgetest_multi_hxx
#define INCLUDED_testtools_source_bridgetest_multi_hxx

#include "sal/config.h"

#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "cppuhelper/implbase1.hxx"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "test/testtools/bridgetest/XMulti.hpp"

namespace testtools { namespace bridgetest {

class Multi: public cppu::WeakImplHelper1< test::testtools::bridgetest::XMulti >
{
public:
    Multi(): m_attribute1(0.0), m_attribute3(0.0) {}

    virtual double SAL_CALL getatt1()
        throw (com::sun::star::uno::RuntimeException)
    { return m_attribute1; }

    virtual void SAL_CALL setatt1(double value)
        throw (com::sun::star::uno::RuntimeException)
    { m_attribute1 = value; }

    virtual sal_Int32 SAL_CALL fn11(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 11 * arg; }

    virtual rtl::OUString SAL_CALL fn12(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("12") + arg; }

    virtual sal_Int32 SAL_CALL fn21(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 21 * arg; }

    virtual rtl::OUString SAL_CALL fn22(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("22") + arg; }

    virtual double SAL_CALL getatt3()
        throw (com::sun::star::uno::RuntimeException)
    { return m_attribute3; }

    virtual void SAL_CALL setatt3(double value)
        throw (com::sun::star::uno::RuntimeException)
    { m_attribute3 = value; }

    virtual sal_Int32 SAL_CALL fn31(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 31 * arg; }

    virtual rtl::OUString SAL_CALL fn32(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("32") + arg; }

    virtual sal_Int32 SAL_CALL fn33()
        throw (com::sun::star::uno::RuntimeException)
    { return 33; }

    virtual sal_Int32 SAL_CALL fn41(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 41 * arg; }

    virtual sal_Int32 SAL_CALL fn61(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 61 * arg; }

    virtual rtl::OUString SAL_CALL fn62(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("62") + arg; }

    virtual sal_Int32 SAL_CALL fn71(sal_Int32 arg)
        throw (com::sun::star::uno::RuntimeException)
    { return 71 * arg; }

    virtual rtl::OUString SAL_CALL fn72(rtl::OUString const & arg)
        throw (com::sun::star::uno::RuntimeException)
    { return rtl::OUString::createFromAscii("72") + arg; }

    virtual sal_Int32 SAL_CALL fn73()
        throw (com::sun::star::uno::RuntimeException)
    { return 73; }

private:
    double m_attribute1;
    double m_attribute3;
};

rtl::OUString testMulti(
    com::sun::star::uno::Reference< test::testtools::bridgetest::XMulti >
    const & multi);

} }

#endif
<|endoftext|>


<commit_before>#include <chrono>
#include <thread>

#include "bulk_test_common.hpp"
#include "set_backend.hpp"
#include <bulk/bulk.hpp>

extern environment env;

void test_communication() {
    env.spawn(env.available_processors(), [](auto& world) {
        int s = world.processor_id();
        int p = world.active_processors();

        BULK_SKIP_SECTION_IF("Communication", p < 1);

        BULK_SECTION("Put") {
            // test `put` to single variable
            bulk::var<int> a(world, 3);

            BULK_CHECK(a.value() == 3,
                            "correct initial value for variable");

            bulk::put(world.next_processor(), s, a);
            world.sync();

            BULK_CHECK(a.value() == ((s + p - 1) % p),
                            "receive correct value after putting");
        }

        BULK_SECTION("Broadcast") {
            // test `put` to single variable
            bulk::var<int> a(world, 3);

            if (world.processor_id() == 1) {
                a.broadcast(2);
            }
            world.sync();

            BULK_CHECK(a.value() == 2,
                            "receive correct value after broadcasting");
        }

        BULK_SECTION("Put is delayed") {
            using namespace std::chrono_literals;

            // test `put` to single variable
            bulk::var<int> a(world, s);

            bulk::put(world.next_processor(), s, a);

            // sleep
            std::this_thread::sleep_for(20ms);

            BULK_CHECK(a.value() == s, "local copy untouched before sync");

            world.sync();

            BULK_CHECK(a.value() == world.prev_processor(), "receive data after sync");
        }

        BULK_SECTION("Sugarized put") {
            // test `put` to single variable
            bulk::var<int> a(world);

            a(world.next_processor()) = s;
            world.sync();

            BULK_CHECK(a.value() == ((s + p - 1) % p),
                            "receive correct value after sugarized putting");
        }

        BULK_SECTION("Put to self") {
            bulk::var<int> a(world);

            bulk::put(s, s, a);
            world.sync();

            BULK_CHECK(a.value() == s,
                            "receive correct value after putting to self");
        }

        BULK_SECTION("Get from self") {
            bulk::var<int> a(world);
            a = s;
            auto b = bulk::get(s, a);
            world.sync();

            BULK_CHECK(b.value() == s,
                            "receive correct value after getting from self");
        }

        BULK_SECTION("Put non-int") {
            // test `put` float to single variable
            bulk::var<float> a(world, 5.0f);

            bulk::put(world.next_processor(), 1.0f, a);
            world.sync();

            BULK_CHECK(a.value() == 1.0f,
                            "receive correct value after putting float");
        }

        BULK_SECTION("Put custom struct") {
            struct custom_struct {
                int x;
                float y;
            };
            bulk::var<custom_struct> a(world, {4, 8.0f});

            bulk::put(world.next_processor(), {3, 2.0f}, a);
            world.sync();

            BULK_CHECK(a.value().x == 3 && a.value().y == 2.0f,
                       "receive correct value after putting custom struct");
        }

        BULK_SECTION("Put multiple") {
            int size = 5;

            // test `put` to multiple variables
            std::vector<bulk::var<int>> xs;
            for (int i = 0; i < size; ++i)
                xs.emplace_back(world);

            for (int i = 0; i < size; ++i) {
                bulk::put(world.next_processor(), s + i, xs[i]);
            }

            world.sync();

            for (int i = 0; i < size; ++i) {
                BULK_CHECK(xs[i].value() == ((s + p - 1) % p) + i,
                                "receive correct value after multiple puts to "
                                "array of variables");
            }
        }

        BULK_SECTION("Put unequal") {
            int size = 5;

            // test `put` to multiple variables
            std::vector<bulk::var<int>> xs;
            for (int i = 0; i < size; ++i)
                xs.emplace_back(world);

            if (s == 0)
                for (int i = 1; i < p; ++i) {
                    for (int j = 0; j < size; ++j) {
                        bulk::put(i, i, xs[j]);
                    }
                }

            world.sync();

            bulk::future<int> a(world);
            if (s == 0)
                a = bulk::get(p - 1, xs[size - 1]);

            world.sync();

            BULK_CHECK(
                a.value() == p - 1,
                "receive correct value after heterogeneous puts and getting");
        }

        BULK_SECTION("Get") {
            bulk::var<int> b(world);
            b.value() = s;
            world.sync();

            auto c = bulk::get(world.next_processor(), b);
            world.sync();

            BULK_CHECK(c.value() == world.next_processor(),
                            "receive correct value after getting");
        }

        BULK_SECTION("Sugarized get") {
            bulk::var<int> b(world);
            b.value() = s;
            world.sync();

            auto c = b(world.next_processor()).get();
            world.sync();

            BULK_CHECK(c.value() == world.next_processor(),
                            "receive correct value after sugarized getting");
        }

        BULK_SECTION("Get multiple") {
            int size = 5;
            bulk::var<int> x(world);
            x.value() = s;

            world.sync();

            std::vector<bulk::future<int>> ys;
            for (int i = 0; i < size; ++i) {
                ys.push_back(bulk::get(world.next_processor(), x));
            }

            world.sync();

            for (auto& y : ys) {
                BULK_CHECK(y.value() == world.next_processor(),
                                "receive correct value after getting multiple");
            }
        }

        BULK_SECTION("Put array") {
            std::vector<int> test(10);
            std::iota(test.begin(), test.end(), 1);

            bulk::coarray<int> xs(world, 10, 5);
            xs.put(world.next_processor(), test.begin(), test.end());
            world.sync();

            BULK_CHECK(xs[5] == 6, "put iterator range");
        }

        BULK_SECTION("Coarray") {
            bulk::coarray<int> zs(world, 10);

            BULK_CHECK(zs.size() == 10,
                            "can obtain the size of a coarray");
            BULK_CHECK(zs.empty() == false, "can check for emptyness");

            zs(world.next_processor())[1] = s;

            world.sync();

            BULK_CHECK(
                zs[1] == world.prev_processor(),
                "putting to remote coarray image gives correct result");

            zs[3] = 2;

            BULK_CHECK(zs[3] == 2,
                            "writing to local coarray gives correct result");

            auto a = zs(2)[1].get();
            world.sync();

            BULK_CHECK(a.value() == 1,
                            "getting from coarray gives correct result");
        }

        BULK_SECTION("Coarray iteration") {
            auto xs = bulk::gather_all(world, s);
            int t = 0;
            for (auto x : xs) {
                BULK_CHECK(x == t++, "gather operation succeeded");
            }
        }

        BULK_SECTION("Coarray slicing") {
            bulk::coarray<int> zs(world, 10, 0);
            zs(world.next_processor())[{2, 5}] = s;
            zs(world.next_processor())[{0, 2}] = {s - 1, s - 2};

            world.sync();

            for (int i = 2; i < 5; ++i) {
                BULK_CHECK(zs[i] == world.prev_processor(),
                                "setting slice to constant");
            }
            BULK_CHECK(zs[5] == 0,
                            "outside the slice values are untouched");
            BULK_CHECK(zs[0] == world.prev_processor() - 1,
                            "individual slice setting");
            BULK_CHECK(zs[1] == world.prev_processor() - 2,
                            "individual slice setting");
        }

        BULK_SECTION("Single message passing") {
            bulk::queue<int, int> q(world);
            q(world.next_processor()).send(123, 1337);
            world.sync();
            for (auto& msg : q) {
                BULK_CHECK(std::get<0>(msg) == 123 &&
                                    std::get<1>(msg) == 1337,
                                "message passed succesfully");
            }
        }

        BULK_SECTION("Message to self") {
            bulk::queue<int, int> q(world);

            q(world.processor_id()).send(123, 1337);
            world.sync();
            int tag = 0;
            int content = 0;
            for (auto msg : q) {
                tag = std::get<0>(msg);
                content = std::get<1>(msg);
            }
            BULK_CHECK(tag == 123 && content == 1337,
                            "message passed succesfully");
        }

        BULK_SECTION("Multiple messages to self") {
            auto q = bulk::queue<int, int>(world);

            q(world.processor_id()).send(123, 1337);
            world.sync();
            int tag = 0;
            int content = 0;
            for (auto msg : q) {
                tag = std::get<0>(msg);
                content = std::get<1>(msg);
            }
            BULK_CHECK(tag == 123 && content == 1337,
                            "message passed succesfully");
        }

        BULK_SECTION("Multiple message passing") {
            std::vector<int> contents = {1337, 12345, 1230519, 5, 8};

            bulk::queue<int, int> q(world);
            for (size_t i = 0; i < contents.size(); ++i) {
                q(world.next_processor()).send(s, contents[i]);
            }

            world.sync();

            int k = 0;
            BULK_CHECK(!q.empty(), "multiple messages arrived");
            for (auto msg : q) {
                BULK_CHECK(std::get<0>(msg) == world.prev_processor() &&
                                    std::get<1>(msg) == contents[k++],
                                "multiple messages passed succesfully");
            }
        }

        BULK_SECTION("Multiple queue and types message passing") {
            std::vector<int> contents = {1337, 12345, 1230519, 5, 8};
            std::vector<float> contents2 = {1.0f, 2.0f, 3.0f, 4.0f};

            bulk::queue<int> q(world);
            bulk::queue<int, float> q2(world);

            for (size_t i = 0; i < contents.size(); ++i) {
                q(world.next_processor()).send(contents[i]);
            }
            for (size_t i = 0; i < contents2.size(); ++i) {
                q2(world.next_processor()).send(s, contents2[i]);
            }

            world.sync();

            int k = 0;
            BULK_CHECK(!q.empty() && !q2.empty(), "queues are non-empty");
            for (auto& msg : q) {
                BULK_CHECK(msg == contents[k++],
                                "received correct result on q");
            }

            int l = 0;
            BULK_CHECK(q.size() == contents.size(),
                            "first queue correct number of messages");

            BULK_CHECK(q2.size() == contents2.size(),
                            "second queue correct number of messages");

            for (auto& msg : q2) {
                BULK_CHECK(std::get<0>(msg) == world.prev_processor() &&
                                    std::get<1>(msg) == contents2[l++],
                                "received correct result on q2");
            }

            world.sync();

            BULK_CHECK(q.empty(), "first queue gets emptied");
            BULK_CHECK(q2.empty(), "second queue gets emptied");
        }
    });
}
<commit_msg>Add delayed get unittest<commit_after>#include <chrono>
#include <thread>

#include "bulk_test_common.hpp"
#include "set_backend.hpp"
#include <bulk/bulk.hpp>

extern environment env;

void test_communication() {
    env.spawn(env.available_processors(), [](auto& world) {
        int s = world.processor_id();
        int p = world.active_processors();

        BULK_SKIP_SECTION_IF("Communication", p < 1);

        BULK_SECTION("Put") {
            // test `put` to single variable
            bulk::var<int> a(world, 3);

            BULK_CHECK(a.value() == 3,
                            "correct initial value for variable");

            bulk::put(world.next_processor(), s, a);
            world.sync();

            BULK_CHECK(a.value() == ((s + p - 1) % p),
                            "receive correct value after putting");
        }

        BULK_SECTION("Broadcast") {
            // test `put` to single variable
            bulk::var<int> a(world, 3);

            if (world.processor_id() == 1) {
                a.broadcast(2);
            }
            world.sync();

            BULK_CHECK(a.value() == 2,
                            "receive correct value after broadcasting");
        }

        BULK_SECTION("Put and get delayed") {
            using namespace std::chrono_literals;

            // test `put` to single variable
            bulk::var<int> a(world, s);

            bulk::put(world.next_processor(), s, a);

            // sleep
            std::this_thread::sleep_for(20ms);

            BULK_CHECK(a.value() == s, "local copy untouched before sync");

            world.sync();

            BULK_CHECK(a.value() == world.prev_processor(), "receive data after sync");

            a.value() = 42;

            world.sync();

            auto b = bulk::get(world.next_processor(), a);

            std::this_thread::sleep_for(20ms);

            a.value() = 45;

            world.sync();

            BULK_CHECK(b.value() == 45, "receive correct value after get");
        }

        BULK_SECTION("Sugarized put") {
            // test `put` to single variable
            bulk::var<int> a(world);

            a(world.next_processor()) = s;
            world.sync();

            BULK_CHECK(a.value() == ((s + p - 1) % p),
                            "receive correct value after sugarized putting");
        }

        BULK_SECTION("Put to self") {
            bulk::var<int> a(world);

            bulk::put(s, s, a);
            world.sync();

            BULK_CHECK(a.value() == s,
                            "receive correct value after putting to self");
        }

        BULK_SECTION("Get from self") {
            bulk::var<int> a(world);
            a = s;
            auto b = bulk::get(s, a);
            world.sync();

            BULK_CHECK(b.value() == s,
                            "receive correct value after getting from self");
        }

        BULK_SECTION("Put non-int") {
            // test `put` float to single variable
            bulk::var<float> a(world, 5.0f);

            bulk::put(world.next_processor(), 1.0f, a);
            world.sync();

            BULK_CHECK(a.value() == 1.0f,
                            "receive correct value after putting float");
        }

        BULK_SECTION("Put custom struct") {
            struct custom_struct {
                int x;
                float y;
            };
            bulk::var<custom_struct> a(world, {4, 8.0f});

            bulk::put(world.next_processor(), {3, 2.0f}, a);
            world.sync();

            BULK_CHECK(a.value().x == 3 && a.value().y == 2.0f,
                       "receive correct value after putting custom struct");
        }

        BULK_SECTION("Put multiple") {
            int size = 5;

            // test `put` to multiple variables
            std::vector<bulk::var<int>> xs;
            for (int i = 0; i < size; ++i)
                xs.emplace_back(world);

            for (int i = 0; i < size; ++i) {
                bulk::put(world.next_processor(), s + i, xs[i]);
            }

            world.sync();

            for (int i = 0; i < size; ++i) {
                BULK_CHECK(xs[i].value() == ((s + p - 1) % p) + i,
                                "receive correct value after multiple puts to "
                                "array of variables");
            }
        }

        BULK_SECTION("Put unequal") {
            int size = 5;

            // test `put` to multiple variables
            std::vector<bulk::var<int>> xs;
            for (int i = 0; i < size; ++i)
                xs.emplace_back(world);

            if (s == 0)
                for (int i = 1; i < p; ++i) {
                    for (int j = 0; j < size; ++j) {
                        bulk::put(i, i, xs[j]);
                    }
                }

            world.sync();

            BULK_CHECK(xs[2].value() == s,
                       "receive correct value after heterogeneous puts");

            bulk::future<int> a(world);
            if (s == 0)
                a = bulk::get(p - 1, xs[size - 1]);

            world.sync();

            BULK_CHECK_ONCE(a.value() == p - 1,
                            "receive correct value after getting");
        }

        BULK_SECTION("Get") {
            bulk::var<int> b(world);
            b.value() = s;
            world.sync();

            auto c = bulk::get(world.next_processor(), b);
            world.sync();

            BULK_CHECK(c.value() == world.next_processor(),
                            "receive correct value after getting");
        }

        BULK_SECTION("Sugarized get") {
            bulk::var<int> b(world);
            b.value() = s;
            world.sync();

            auto c = b(world.next_processor()).get();
            world.sync();

            BULK_CHECK(c.value() == world.next_processor(),
                            "receive correct value after sugarized getting");
        }

        BULK_SECTION("Get multiple") {
            int size = 5;
            bulk::var<int> x(world);
            x.value() = s;

            world.sync();

            std::vector<bulk::future<int>> ys;
            for (int i = 0; i < size; ++i) {
                ys.push_back(bulk::get(world.next_processor(), x));
            }

            world.sync();

            for (auto& y : ys) {
                BULK_CHECK(y.value() == world.next_processor(),
                                "receive correct value after getting multiple");
            }
        }

        BULK_SECTION("Put array") {
            std::vector<int> test(10);
            std::iota(test.begin(), test.end(), 1);

            bulk::coarray<int> xs(world, 10, 5);
            xs.put(world.next_processor(), test.begin(), test.end());
            world.sync();

            BULK_CHECK(xs[5] == 6, "put iterator range");
        }

        BULK_SECTION("Coarray") {
            bulk::coarray<int> zs(world, 10);

            BULK_CHECK(zs.size() == 10,
                            "can obtain the size of a coarray");
            BULK_CHECK(zs.empty() == false, "can check for emptyness");

            zs(world.next_processor())[1] = s;

            world.sync();

            BULK_CHECK(
                zs[1] == world.prev_processor(),
                "putting to remote coarray image gives correct result");

            zs[3] = 2;

            BULK_CHECK(zs[3] == 2,
                            "writing to local coarray gives correct result");

            auto a = zs(2)[1].get();
            world.sync();

            BULK_CHECK(a.value() == 1,
                            "getting from coarray gives correct result");
        }

        BULK_SECTION("Coarray iteration") {
            auto xs = bulk::gather_all(world, s);
            int t = 0;
            for (auto x : xs) {
                BULK_CHECK(x == t++, "gather operation succeeded");
            }
        }

        BULK_SECTION("Coarray slicing") {
            bulk::coarray<int> zs(world, 10, 0);
            zs(world.next_processor())[{2, 5}] = s;
            zs(world.next_processor())[{0, 2}] = {s - 1, s - 2};

            world.sync();

            for (int i = 2; i < 5; ++i) {
                BULK_CHECK(zs[i] == world.prev_processor(),
                                "setting slice to constant");
            }
            BULK_CHECK(zs[5] == 0,
                            "outside the slice values are untouched");
            BULK_CHECK(zs[0] == world.prev_processor() - 1,
                            "individual slice setting");
            BULK_CHECK(zs[1] == world.prev_processor() - 2,
                            "individual slice setting");
        }

        BULK_SECTION("Single message passing") {
            bulk::queue<int, int> q(world);
            q(world.next_processor()).send(123, 1337);
            world.sync();
            for (auto& msg : q) {
                BULK_CHECK(std::get<0>(msg) == 123 &&
                                    std::get<1>(msg) == 1337,
                                "message passed succesfully");
            }
        }

        BULK_SECTION("Message to self") {
            bulk::queue<int, int> q(world);

            q(world.processor_id()).send(123, 1337);
            world.sync();
            int tag = 0;
            int content = 0;
            for (auto msg : q) {
                tag = std::get<0>(msg);
                content = std::get<1>(msg);
            }
            BULK_CHECK(tag == 123 && content == 1337,
                            "message passed succesfully");
        }

        BULK_SECTION("Multiple messages to self") {
            auto q = bulk::queue<int, int>(world);

            q(world.processor_id()).send(123, 1337);
            world.sync();
            int tag = 0;
            int content = 0;
            for (auto msg : q) {
                tag = std::get<0>(msg);
                content = std::get<1>(msg);
            }
            BULK_CHECK(tag == 123 && content == 1337,
                            "message passed succesfully");
        }

        BULK_SECTION("Multiple message passing") {
            std::vector<int> contents = {1337, 12345, 1230519, 5, 8};

            bulk::queue<int, int> q(world);
            for (size_t i = 0; i < contents.size(); ++i) {
                q(world.next_processor()).send(s, contents[i]);
            }

            world.sync();

            int k = 0;
            BULK_CHECK(!q.empty(), "multiple messages arrived");
            for (auto msg : q) {
                BULK_CHECK(std::get<0>(msg) == world.prev_processor() &&
                                    std::get<1>(msg) == contents[k++],
                                "multiple messages passed succesfully");
            }
        }

        BULK_SECTION("Multiple queue and types message passing") {
            std::vector<int> contents = {1337, 12345, 1230519, 5, 8};
            std::vector<float> contents2 = {1.0f, 2.0f, 3.0f, 4.0f};

            bulk::queue<int> q(world);
            bulk::queue<int, float> q2(world);

            for (size_t i = 0; i < contents.size(); ++i) {
                q(world.next_processor()).send(contents[i]);
            }
            for (size_t i = 0; i < contents2.size(); ++i) {
                q2(world.next_processor()).send(s, contents2[i]);
            }

            world.sync();

            int k = 0;
            BULK_CHECK(!q.empty() && !q2.empty(), "queues are non-empty");
            for (auto& msg : q) {
                BULK_CHECK(msg == contents[k++],
                                "received correct result on q");
            }

            int l = 0;
            BULK_CHECK(q.size() == contents.size(),
                            "first queue correct number of messages");

            BULK_CHECK(q2.size() == contents2.size(),
                            "second queue correct number of messages");

            for (auto& msg : q2) {
                BULK_CHECK(std::get<0>(msg) == world.prev_processor() &&
                                    std::get<1>(msg) == contents2[l++],
                                "received correct result on q2");
            }

            world.sync();

            BULK_CHECK(q.empty(), "first queue gets emptied");
            BULK_CHECK(q2.empty(), "second queue gets emptied");
        }
    });
}
<|endoftext|>


<commit_before>/*
 * Quantum++
 *
 * Copyright (c) 2013 - 2015 Vlad Gheorghiu (vgheorgh@gmail.com)
 *
 * This file is part of Quantum++.
 *
 * Quantum++ is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Quantum++ is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Quantum++.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <gtest/gtest.h>

#include <qpp.h>
// #include <MATLAB/matlab.h> // support for MATLAB
// #include <experimental/test.h> // support for testing features

using namespace qpp;

// TODO: write your unit tests here

// ********** qpp::sum() **********
TEST(qpp_sum_test, PositiveNumbers)
{
    std::vector<int> v{0, 1, 2, 3};
    EXPECT_EQ (6, qpp::sum(v.begin(), v.end()));
}

TEST(qpp_sum_test, NegativeNumbers)
{
    std::vector<int> v{0, -1, -2, -3};
    EXPECT_EQ (-6, qpp::sum(v.begin(), v.end()));
}

TEST(qpp_sum_test, MixedNumbers)
{
    std::vector<int> v{ -3, -2, -1, 0, 1, 2};
    EXPECT_EQ (-3, qpp::sum(v.begin(), v.end()));
}
// ********** END qpp::sum() **********

// ********** qpp::prod() **********
TEST(qpp_prod_test, PositiveNumbers)
{
    std::vector<int> v{1, 2, 3, 4};
    EXPECT_EQ (24, qpp::prod(v.begin(), v.end()));
}
// ********** END qpp::prod() **********

// ********** qpp::modpow() **********
TEST(qpp_modpow_test, PositiveNumbers)
{
    EXPECT_EQ (0, qpp::modpow(2, 3, 4));
    EXPECT_EQ (34, qpp::modpow(17, 176, 37));
    EXPECT_EQ (4042, qpp::modpow(178373, 9281623, 6217));
}
// ********** END qpp::modpow() **********

int main(int argc, char** argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>commit<commit_after>/*
 * Quantum++
 *
 * Copyright (c) 2013 - 2015 Vlad Gheorghiu (vgheorgh@gmail.com)
 *
 * This file is part of Quantum++.
 *
 * Quantum++ is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Quantum++ is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Quantum++.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <gtest/gtest.h>

#include <qpp.h>
// #include <MATLAB/matlab.h> // support for MATLAB
// #include <experimental/test.h> // support for testing features

using namespace qpp;

// TODO: write your unit tests here

// ********** qpp::sum() **********
TEST(qpp_sum_test, PositiveNumbers)
{
    std::vector<int> v{0, 1, 2, 3};
    EXPECT_EQ (6, qpp::sum(v.begin(), v.end()));
}

TEST(qpp_sum_test, NegativeNumbers)
{
    std::vector<int> v{0, -1, -2, -3};
    EXPECT_EQ (-6, qpp::sum(v.begin(), v.end()));
}

TEST(qpp_sum_test, MixedNumbers)
{
    std::vector<int> v{ -3, -2, -1, 0, 1, 2};
    EXPECT_EQ (-3, qpp::sum(v.begin(), v.end()));
}
// ********** END qpp::sum() **********

// ********** qpp::prod() **********
TEST(qpp_prod_test, PositiveNumbers)
{
    std::vector<int> v{1, 2, 3, 4};
    EXPECT_EQ (24, qpp::prod(v.begin(), v.end()));
}
// ********** END qpp::prod() **********

// ********** qpp::modpow() **********
TEST(qpp_modpow_test, PositiveNumbers)
{
    EXPECT_EQ (0, qpp::modpow(2, 3, 4));
    EXPECT_EQ (34, qpp::modpow(17, 176, 37));
    EXPECT_EQ (4042, qpp::modpow(178373, 9281623, 6217));
}
// ********** END qpp::modpow() **********

int main(int argc, char** argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#ifndef ITER_CYCLE_H_
#define ITER_CYCLE_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <initializer_list>
#include <iterator>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Container>
    class Cycler;

    using CycleFn = IterToolFn<Cycler>;
  }
  constexpr impl::CycleFn cycle{};
}

template <typename Container>
class iter::impl::Cycler {
 private:
  friend CycleFn;

  Container container_;

  Cycler(Container&& container)
      : container_(std::forward<Container>(container)) {}

 public:
  Cycler(Cycler&&) = default;
  class Iterator : public std::iterator<std::input_iterator_tag,
                       iterator_traits_deref<Container>> {
   private:
    IteratorWrapper<Container> sub_iter_;
    IteratorWrapper<Container> sub_begin_;
    IteratorWrapper<Container> sub_end_;

   public:
    Iterator(IteratorWrapper<Container>&& sub_iter,
        IteratorWrapper<Container>&& sub_end)
        : sub_iter_{sub_iter},
          sub_begin_{sub_iter},
          sub_end_{std::move(sub_end)} {}

    iterator_deref<Container> operator*() {
      return *sub_iter_;
    }

    iterator_arrow<Container> operator->() {
      return apply_arrow(sub_iter_);
    }

    Iterator& operator++() {
      ++sub_iter_;
      // reset to beginning upon reaching the sub_end_
      if (!(sub_iter_ != sub_end_)) {
        sub_iter_ = sub_begin_;
      }
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return sub_iter_ != other.sub_iter_;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }
  };

  Iterator begin() {
    return {get_begin(container_), get_end(container_)};
  }

  Iterator end() {
    return {get_end(container_), get_end(container_)};
  }
};

#endif
<commit_msg>Adds support for const iteration to cycle<commit_after>#ifndef ITER_CYCLE_H_
#define ITER_CYCLE_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <initializer_list>
#include <iterator>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Container>
    class Cycler;

    using CycleFn = IterToolFn<Cycler>;
  }
  constexpr impl::CycleFn cycle{};
}

template <typename Container>
class iter::impl::Cycler {
 private:
  friend CycleFn;

  Container container_;

  Cycler(Container&& container)
      : container_(std::forward<Container>(container)) {}

 public:
  Cycler(Cycler&&) = default;
  template <typename ContainerT>
  class Iterator : public std::iterator<std::input_iterator_tag,
                       iterator_traits_deref<ContainerT>> {
   private:
    template <typename>
    friend class Iterator;
    IteratorWrapper<ContainerT> sub_iter_;
    IteratorWrapper<ContainerT> sub_begin_;
    IteratorWrapper<ContainerT> sub_end_;

   public:
    Iterator(IteratorWrapper<ContainerT>&& sub_iter,
        IteratorWrapper<ContainerT>&& sub_end)
        : sub_iter_{sub_iter},
          sub_begin_{sub_iter},
          sub_end_{std::move(sub_end)} {}

    iterator_deref<ContainerT> operator*() {
      return *sub_iter_;
    }

    iterator_arrow<ContainerT> operator->() {
      return apply_arrow(sub_iter_);
    }

    Iterator& operator++() {
      ++sub_iter_;
      // reset to beginning upon reaching the sub_end_
      if (!(sub_iter_ != sub_end_)) {
        sub_iter_ = sub_begin_;
      }
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    template <typename T>
    bool operator!=(const Iterator<T>& other) const {
      return sub_iter_ != other.sub_iter_;
    }

    template <typename T>
    bool operator==(const Iterator<T>& other) const {
      return !(*this != other);
    }
  };

  Iterator<Container> begin() {
    return {get_begin(container_), get_end(container_)};
  }

  Iterator<Container> end() {
    return {get_end(container_), get_end(container_)};
  }

  Iterator<AsConst<Container>> begin() const {
    return {get_begin(as_const(container_)), get_end(as_const(container_))};
  }

  Iterator<AsConst<Container>> end() const {
    return {get_end(as_const(container_)), get_end(as_const(container_))};
  }
};

#endif
<|endoftext|>


<commit_before>#ifndef ITER_CYCLE_H_
#define ITER_CYCLE_H_

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    //Forward declarations of Cycle and cycle
    template <typename Container>
    class Cycle;

    template <typename Container>
    Cycle<Container> cycle(Container&&);

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T>);

    template <typename Container>
    class Cycle {
        private:
            // The cycle function is the only thing allowed to create a Cycle
            friend Cycle cycle<Container>(Container&&);
            template <typename T>
            friend Cycle<std::initializer_list<T>> cycle(
                    std::initializer_list<T>);

            Container container;

            // Value constructor for use only in the cycle function
            Cycle(Container container)
                : container(std::forward<Container>(container))
            { }

        public:
            class Iterator
                : public std::iterator<std::input_iterator_tag,
                            iterator_traits_deref<Container>>
            {
                private:
                    using iter_type = iterator_type<Container>;
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> begin;
                    iterator_type<Container> end;
                public:
                    Iterator (iterator_type<Container> iter,
                            iterator_type<Container> end)
                        : sub_iter{iter},
                        begin{iter},
                        end{end}
                    { }

                    iterator_deref<Container> operator*() const {
                        return *this->sub_iter;
                    }

                    Iterator& operator++() {
                        ++this->sub_iter;
                        // reset to beginning upon reaching the end
                        if (!(this->sub_iter != this->end)) {
                            // explicit destruction with placement new in order
                            // to support iterators with no operator=
                            this->sub_iter.~iter_type();
                            new(&this->sub_iter) iterator_type<Container>(
                                    this->begin);
                        }
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container)};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container)};
            }

    };

    // Helper function to instantiate a Cycle
    template <typename Container>
    Cycle<Container> cycle(Container&& container) {
        return {std::forward<Container>(container)};
    }

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T> il)
    {
        return {std::move(il)};
    }
}

#endif
<commit_msg>Removes placement new in favor of assignment<commit_after>#ifndef ITER_CYCLE_H_
#define ITER_CYCLE_H_

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    //Forward declarations of Cycle and cycle
    template <typename Container>
    class Cycle;

    template <typename Container>
    Cycle<Container> cycle(Container&&);

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T>);

    template <typename Container>
    class Cycle {
        private:
            // The cycle function is the only thing allowed to create a Cycle
            friend Cycle cycle<Container>(Container&&);
            template <typename T>
            friend Cycle<std::initializer_list<T>> cycle(
                    std::initializer_list<T>);

            Container container;

            // Value constructor for use only in the cycle function
            Cycle(Container container)
                : container(std::forward<Container>(container))
            { }

        public:
            class Iterator
                : public std::iterator<std::input_iterator_tag,
                            iterator_traits_deref<Container>>
            {
                private:
                    using iter_type = iterator_type<Container>;
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> begin;
                    iterator_type<Container> end;
                public:
                    Iterator (iterator_type<Container> iter,
                            iterator_type<Container> end)
                        : sub_iter{iter},
                        begin{iter},
                        end{end}
                    { }

                    iterator_deref<Container> operator*() const {
                        return *this->sub_iter;
                    }

                    Iterator& operator++() {
                        ++this->sub_iter;
                        // reset to beginning upon reaching the end
                        if (!(this->sub_iter != this->end)) {
                            this->sub_iter = this->begin;
                        }
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container)};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container)};
            }

    };

    // Helper function to instantiate a Cycle
    template <typename Container>
    Cycle<Container> cycle(Container&& container) {
        return {std::forward<Container>(container)};
    }

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T> il)
    {
        return {std::move(il)};
    }
}

#endif
<|endoftext|>


<commit_before>#ifndef CYCLE__H__
#define CYCLE__H__

#include <iterbase.hpp>

#include <utility>
#include <iterator>

namespace iter {

    //Forward declarations of Cycle and cycle
    template <typename Container>
    class Cycle;

    template <typename Container>
    Cycle<Container> cycle(Container &);

    template <typename Container>
    class Cycle : public IterBase<Container>{
        private:
            // The cycle function is the only thing allowed to create a Cycle
            friend Cycle cycle<Container>(Container &);

            using typename IterBase<Container>::contained_iter_type;

            using typename IterBase<Container>::contained_iter_ret;

            Container & container;

            // Value constructor for use only in the cycle function
            Cycle(Container & container) : container(container) { }
            Cycle () = delete;
            Cycle & operator=(const Cycle &) = delete;

        public:
            Cycle(const Cycle &) = default;
            class Iterator {
                private:
                    contained_iter_type sub_iter;
                    const contained_iter_type begin;
                    const contained_iter_type end;
                public:
                    Iterator (contained_iter_type iter,
                            contained_iter_type end) :
                        sub_iter(iter),
                        begin(iter),
                        end(end)
                    { }

                    contained_iter_ret operator*() const {
                        return *this->sub_iter;
                    }

                    Iterator & operator++() {
                        ++this->sub_iter;
                        // reset to beginning upon reaching the end
                        if (this->sub_iter == this->end) {
                            this->sub_iter = this->begin;
                        }
                        return *this;
                    }

                    constexpr bool operator!=(const Iterator &) const {
                        return true;
                    }
            };

            Iterator begin() const {
                return Iterator(std::begin(this->container),
                        std::end(this->container));
            }

            Iterator end() const {
                return Iterator(std::end(this->container),
                    std::end(this->container));
            }

    };

    // Helper function to instantiate an Filter
    template <typename Container>
    Cycle<Container> cycle(Container & container) {
        return Cycle<Container>(container);
    }

}

#endif //ifndef CYCLE__H__
<commit_msg>Adds support for initializer_list<commit_after>#ifndef CYCLE__H__
#define CYCLE__H__

#include <iterbase.hpp>

#include <utility>
#include <iterator>

namespace iter {

    //Forward declarations of Cycle and cycle
    template <typename Container>
    class Cycle;

    template <typename Container>
    Cycle<Container> cycle(Container &&);

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(
            std::initializer_list<T> &&);

    template <typename Container>
    class Cycle : public IterBase<Container>{
        public:
            // The cycle function is the only thing allowed to create a Cycle
            friend Cycle cycle<Container>(Container &&);
            template <typename T>
            friend Cycle<std::initializer_list<T>> cycle(
                    std::initializer_list<T> &&);

            using typename IterBase<Container>::contained_iter_type;

            using typename IterBase<Container>::contained_iter_ret;

            Container & container;

            // Value constructor for use only in the cycle function
            Cycle(Container && container) : container(container) { }
            Cycle () = delete;
            Cycle & operator=(const Cycle &) = delete;

        public:
            Cycle(const Cycle &) = default;
            class Iterator {
                private:
                    contained_iter_type sub_iter;
                    const contained_iter_type begin;
                    const contained_iter_type end;
                public:
                    Iterator (contained_iter_type iter,
                            contained_iter_type end) :
                        sub_iter(iter),
                        begin(iter),
                        end(end)
                    { }

                    contained_iter_ret operator*() const {
                        return *this->sub_iter;
                    }

                    Iterator & operator++() {
                        ++this->sub_iter;
                        // reset to beginning upon reaching the end
                        if (this->sub_iter == this->end) {
                            this->sub_iter = this->begin;
                        }
                        return *this;
                    }

                    constexpr bool operator!=(const Iterator &) const {
                        return true;
                    }
            };

            Iterator begin() const {
                return Iterator(std::begin(this->container),
                        std::end(this->container));
            }

            Iterator end() const {
                return Iterator(std::end(this->container),
                    std::end(this->container));
            }

    };

    // Helper function to instantiate an Filter
    template <typename Container>
    Cycle<Container> cycle(Container && container) {
        return Cycle<Container>(std::forward<Container>(container));
    }

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T> && il)
    {
        return Cycle<std::initializer_list<T>>(
                std::forward<std::initializer_list<T>>(il));
    }
}

#endif //ifndef CYCLE__H__
<|endoftext|>


<commit_before>/*
 * SessionBlogdown.cpp
 *
 * Copyright (C) 2020 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionBlogdown.hpp"

#include <shared_core/Error.hpp>
#include <core/system/Process.hpp>
#include <core/system/ShellUtils.hpp>

#include <core/RegexUtils.hpp>
#include <core/ConfigUtils.hpp>

#include <session/SessionModuleContext.hpp>
#include <session/projects/SessionProjects.hpp>

#include "SessionRMarkdown.hpp"

using namespace rstudio::core;
using namespace rstudio::core::shell_utils;
using namespace rstudio::session::module_context;
using namespace rstudio::session::modules::rmarkdown;

namespace rstudio {
namespace session {
namespace modules {
namespace rmarkdown {
namespace blogdown {
namespace {

FilePath hugoRootPath()
{
   return projects::projectContext().config().buildType != r_util::kBuildTypeNone
      ? projects::projectContext().buildTargetPath()
      : projects::projectContext().directory();
}

template <typename Args>
std::string runHugo(const Args& args, bool logErrors = true)
{
   ShellCommand hugo("hugo");

   core::system::ProcessOptions options;

   // use build target path if this project has a build type
   options.workingDir = hugoRootPath();

   // detach the session so there is no terminal
#ifndef _WIN32
   options.detachSession = true;
#endif

   core::system::ProcessResult result;
   Error error = core::system::runCommand(hugo << args, options, &result);
   if (error)
   {
      if (logErrors)
         LOG_ERROR(error);
      return "";
   }
   else if (result.exitStatus != EXIT_SUCCESS)
   {
      if (logErrors)
         LOG_ERROR_MESSAGE("Error running hugo: " + result.stdErr);
      return "";
   }
   else
   {
      return result.stdOut;
   }
}

} // anonymous namespace

core::json::Object blogdownConfig()
{

   const char* const kIsBlogdownProject = "is_blogdown_project";
   const char* const kIsHugoProject = "is_hugo_project";
   const char* const kSiteDir = "site_dir";
   const char* const kStaticDirs = "static_dirs";
   const char* const kMarkdownEngine = "markdown_engine";
   const char* const kMarkdownEngineGoldmark = "goldmark";
   const char* const kMarkdownEngineBlackfriday = "blackfriday";
   const char* const kMarkdownExtensions = "markdown_extensions";

   json::Object config;

   // detect project type(s)
   bool isBlogdownProject = rmarkdown::isSiteProject("blogdown_site");
   bool isHugoProject = isBlogdownProject;

   // if it's not a blogdown project, see if it's a hugo project. note that
   // we don't want to run hugo if we don't need to (startup time impacting
   // IDE startup time), so we gate the check by looking for a few sentinel
   // files + the presence of hugo on the system
   if (!isHugoProject)
   {
      if (projects::projectContext().hasProject())
      {
         FilePath hugoRoot = hugoRootPath();
         if (hugoRoot.completeChildPath("config.toml").exists() ||
             hugoRoot.completeChildPath("config.yaml").exists() ||
             hugoRoot.completeChildPath("config.json").exists() ||
             hugoRoot.completeChildPath("config").exists())
         {
            if (!module_context::findProgram("hugo").isEmpty())
            {
               if (runHugo("config", false).size() > 0)
                  isHugoProject = true;
            }
         }
      }
   }

   // set into config
   config[kIsBlogdownProject] = isBlogdownProject;
   config[kIsHugoProject] = isHugoProject;

   if (isBlogdownProject || isHugoProject)
   {
      // get the site dir
      config[kSiteDir] = module_context::createFileSystemItem(hugoRootPath());

      // set the default static dirs
      json::Array staticDirs;
      staticDirs.push_back("static");
      config[kStaticDirs] = staticDirs;

      // get the hugo version and use it to determine the default markdown engine
      std::string defaultMarkdownEngine = kMarkdownEngineGoldmark;
      std::string version = runHugo("version");
      if (version.size() > 0)
      {
         boost::regex verRegex("(\\d+)\\.(\\d+)(?:.(\\d+))?");
         boost::smatch match;
         if (regex_utils::search(version, match, verRegex))
         {
            int major = safe_convert::stringTo<int>(match[1], 0);
            int minor = safe_convert::stringTo<int>(match[2], 0);
            if (major <= 0 && minor < 60)
               defaultMarkdownEngine = kMarkdownEngineBlackfriday;
         }
      }

      // set defaults to start with
      std::string markdownEngine = defaultMarkdownEngine;
      std::string markdownExtensions = "";

      // get the hugo config
      std::string hugoConfig = runHugo("config");

      // create map of variables
      if (hugoConfig.size() > 0)
      {
         std::map<std::string,std::string> variables;
         boost::regex var("^([A-Za-z0-9_]+\\s*=\\s*[^\n]+)$");
         boost::sregex_token_iterator it(hugoConfig.begin(), hugoConfig.end(), var, 0);
         boost::sregex_token_iterator end;
         while (it != end)
         {
            core::system::Option var;
            if (core::system::parseEnvVar(*it, &var))
            {
               boost::algorithm::trim(var.first);
               boost::algorithm::trim(var.second);
               variables.insert(var);
            }
            it++;
         }

         // see if there is a markup variable
         const std::string markup = variables["markup"];
         if (markup.size() > 0)
         {
            boost::regex handlerRegex("defaultmarkdownhandler\\:(\\w+)");
            boost::smatch handlerMatch;
            if (regex_utils::search(markup, handlerMatch, handlerRegex))
            {
               // get the engine and set it if it's recognized (otherwise just behave as if
               // the default engine is configured)
               std::string matchedEngine = handlerMatch[1];
               if (matchedEngine == kMarkdownEngineBlackfriday || matchedEngine == kMarkdownEngineGoldmark)
                  markdownEngine = matchedEngine;
            }

            // if we are goldmark check to see if unsafe is enabled. in that case
            // add the raw_html extension
            if (markdownEngine == kMarkdownEngineGoldmark)
            {
               boost::regex unsafeRegex("unsafe\\:true");
               boost::smatch unsafeMatch;
               if (regex_utils::search(markup, unsafeMatch, unsafeRegex))
                  markdownExtensions += "+raw_html";
            }
         }

         // see if there is a staticdir variable
         std::string staticdir = variables["staticdir"];
         if (staticdir.size() > 0)
         {
            staticDirs.clear();

            staticdir = string_utils::strippedOfQuotes(staticdir);
            if (boost::algorithm::starts_with(staticdir, "["))
            {
               boost::algorithm::replace_first(staticdir, "[", "");
               boost::algorithm::replace_last(staticdir, "]", "");
               std::vector<std::string> dirs;
               boost::algorithm::split(dirs, staticdir, boost::algorithm::is_any_of(" "));
               staticDirs = core::json::toJsonArray(dirs);
            }
            else
            {
               staticDirs.push_back(staticdir);
            }
            config[kStaticDirs] = staticDirs;
         }
      }

      // populate config
      config[kMarkdownEngine] = markdownEngine;
      config[kMarkdownExtensions] = markdownExtensions;
   }
   else
   {
      config[kIsBlogdownProject] = false;
   }

   return config;
}

} // namespace blogdown
} // namespace rmarkdown
} // namespace modules
} // namespace session
} // namespace rstudio
<commit_msg>detect hugo emojis<commit_after>/*
 * SessionBlogdown.cpp
 *
 * Copyright (C) 2020 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionBlogdown.hpp"

#include <shared_core/Error.hpp>
#include <core/system/Process.hpp>
#include <core/system/ShellUtils.hpp>

#include <core/RegexUtils.hpp>
#include <core/ConfigUtils.hpp>

#include <session/SessionModuleContext.hpp>
#include <session/projects/SessionProjects.hpp>

#include "SessionRMarkdown.hpp"

using namespace rstudio::core;
using namespace rstudio::core::shell_utils;
using namespace rstudio::session::module_context;
using namespace rstudio::session::modules::rmarkdown;

namespace rstudio {
namespace session {
namespace modules {
namespace rmarkdown {
namespace blogdown {
namespace {

FilePath hugoRootPath()
{
   return projects::projectContext().config().buildType != r_util::kBuildTypeNone
      ? projects::projectContext().buildTargetPath()
      : projects::projectContext().directory();
}

template <typename Args>
std::string runHugo(const Args& args, bool logErrors = true)
{
   ShellCommand hugo("hugo");

   core::system::ProcessOptions options;

   // use build target path if this project has a build type
   options.workingDir = hugoRootPath();

   // detach the session so there is no terminal
#ifndef _WIN32
   options.detachSession = true;
#endif

   core::system::ProcessResult result;
   Error error = core::system::runCommand(hugo << args, options, &result);
   if (error)
   {
      if (logErrors)
         LOG_ERROR(error);
      return "";
   }
   else if (result.exitStatus != EXIT_SUCCESS)
   {
      if (logErrors)
         LOG_ERROR_MESSAGE("Error running hugo: " + result.stdErr);
      return "";
   }
   else
   {
      return result.stdOut;
   }
}

} // anonymous namespace

core::json::Object blogdownConfig()
{

   const char* const kIsBlogdownProject = "is_blogdown_project";
   const char* const kIsHugoProject = "is_hugo_project";
   const char* const kSiteDir = "site_dir";
   const char* const kStaticDirs = "static_dirs";
   const char* const kMarkdownEngine = "markdown_engine";
   const char* const kMarkdownEngineGoldmark = "goldmark";
   const char* const kMarkdownEngineBlackfriday = "blackfriday";
   const char* const kMarkdownExtensions = "markdown_extensions";

   json::Object config;

   // detect project type(s)
   bool isBlogdownProject = rmarkdown::isSiteProject("blogdown_site");
   bool isHugoProject = isBlogdownProject;

   // if it's not a blogdown project, see if it's a hugo project. note that
   // we don't want to run hugo if we don't need to (startup time impacting
   // IDE startup time), so we gate the check by looking for a few sentinel
   // files + the presence of hugo on the system
   if (!isHugoProject)
   {
      if (projects::projectContext().hasProject())
      {
         FilePath hugoRoot = hugoRootPath();
         if (hugoRoot.completeChildPath("config.toml").exists() ||
             hugoRoot.completeChildPath("config.yaml").exists() ||
             hugoRoot.completeChildPath("config.json").exists() ||
             hugoRoot.completeChildPath("config").exists())
         {
            if (!module_context::findProgram("hugo").isEmpty())
            {
               if (runHugo("config", false).size() > 0)
                  isHugoProject = true;
            }
         }
      }
   }

   // set into config
   config[kIsBlogdownProject] = isBlogdownProject;
   config[kIsHugoProject] = isHugoProject;

   if (isBlogdownProject || isHugoProject)
   {
      // get the site dir
      config[kSiteDir] = module_context::createFileSystemItem(hugoRootPath());

      // set the default static dirs
      json::Array staticDirs;
      staticDirs.push_back("static");
      config[kStaticDirs] = staticDirs;

      // get the hugo version and use it to determine the default markdown engine
      std::string defaultMarkdownEngine = kMarkdownEngineGoldmark;
      std::string version = runHugo("version");
      if (version.size() > 0)
      {
         boost::regex verRegex("(\\d+)\\.(\\d+)(?:.(\\d+))?");
         boost::smatch match;
         if (regex_utils::search(version, match, verRegex))
         {
            int major = safe_convert::stringTo<int>(match[1], 0);
            int minor = safe_convert::stringTo<int>(match[2], 0);
            if (major <= 0 && minor < 60)
               defaultMarkdownEngine = kMarkdownEngineBlackfriday;
         }
      }

      // set defaults to start with
      std::string markdownEngine = defaultMarkdownEngine;
      std::string markdownExtensions = "";

      // get the hugo config
      std::string hugoConfig = runHugo("config");

      // create map of variables
      if (hugoConfig.size() > 0)
      {
         std::map<std::string,std::string> variables;
         boost::regex var("^([A-Za-z0-9_]+\\s*=\\s*[^\n]+)$");
         boost::sregex_token_iterator it(hugoConfig.begin(), hugoConfig.end(), var, 0);
         boost::sregex_token_iterator end;
         while (it != end)
         {
            core::system::Option var;
            if (core::system::parseEnvVar(*it, &var))
            {
               boost::algorithm::trim(var.first);
               boost::algorithm::trim(var.second);
               variables.insert(var);
            }
            it++;
         }

         // see if there is an enableEmoji variable
         const std::string enableEmoji = variables["enableemoji"];
         if (enableEmoji == "true") {
            markdownExtensions += "+emoji";
         }

         // see if there is a markup variable
         const std::string markup = variables["markup"];
         if (markup.size() > 0)
         {
            boost::regex handlerRegex("defaultmarkdownhandler\\:(\\w+)");
            boost::smatch handlerMatch;
            if (regex_utils::search(markup, handlerMatch, handlerRegex))
            {
               // get the engine and set it if it's recognized (otherwise just behave as if
               // the default engine is configured)
               std::string matchedEngine = handlerMatch[1];
               if (matchedEngine == kMarkdownEngineBlackfriday || matchedEngine == kMarkdownEngineGoldmark)
                  markdownEngine = matchedEngine;
            }

            // if we are goldmark check to see if unsafe is enabled. in that case
            // add the raw_html extension
            if (markdownEngine == kMarkdownEngineGoldmark)
            {
               boost::regex unsafeRegex("unsafe\\:true");
               boost::smatch unsafeMatch;
               if (regex_utils::search(markup, unsafeMatch, unsafeRegex))
                  markdownExtensions += "+raw_html";
            }
         }

         // see if there is a staticdir variable
         std::string staticdir = variables["staticdir"];
         if (staticdir.size() > 0)
         {
            staticDirs.clear();

            staticdir = string_utils::strippedOfQuotes(staticdir);
            if (boost::algorithm::starts_with(staticdir, "["))
            {
               boost::algorithm::replace_first(staticdir, "[", "");
               boost::algorithm::replace_last(staticdir, "]", "");
               std::vector<std::string> dirs;
               boost::algorithm::split(dirs, staticdir, boost::algorithm::is_any_of(" "));
               staticDirs = core::json::toJsonArray(dirs);
            }
            else
            {
               staticDirs.push_back(staticdir);
            }
            config[kStaticDirs] = staticDirs;
         }
      }

      // populate config
      config[kMarkdownEngine] = markdownEngine;
      config[kMarkdownExtensions] = markdownExtensions;
   }
   else
   {
      config[kIsBlogdownProject] = false;
   }

   return config;
}

} // namespace blogdown
} // namespace rmarkdown
} // namespace modules
} // namespace session
} // namespace rstudio
<|endoftext|>


<commit_before>/*
 *  Copyright 2008-2009 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.
 */

/*! \file for_each.inl
 *  \brief Inline file for for_each.h.
 */

#include <thrust/detail/device/dereference.h>
#include <thrust/iterator/iterator_traits.h>
#include <thrust/distance.h>

namespace thrust
{
namespace detail
{
namespace device
{
namespace omp
{

template<typename InputIterator,
         typename UnaryFunction>
void for_each(InputIterator first,
              InputIterator last,
              UnaryFunction f)
{
  typedef typename thrust::iterator_difference<InputIterator>::type difference;
  difference n = thrust::distance(first,last);

#pragma omp parallel for
  for(difference i = 0;
      i < n;
      ++i)
  {
    InputIterator temp = first + i;
    f(dereference(temp));
  }
}

} // end namespace omp
} // end namespace device
} // end namespace detail
} // end namespace thrust

<commit_msg>Guard omp's for_each implementation from non-existence of _OPENMP.<commit_after>/*
 *  Copyright 2008-2009 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.
 */

/*! \file for_each.inl
 *  \brief Inline file for for_each.h.
 */

// do not attempt to compile this code unless the compiler is generating multicore code
// TODO: do this check inside omp::for_each with static_assert
#ifdef _OPENMP

#include <thrust/detail/device/dereference.h>
#include <thrust/iterator/iterator_traits.h>
#include <thrust/distance.h>

namespace thrust
{
namespace detail
{
namespace device
{
namespace omp
{

template<typename InputIterator,
         typename UnaryFunction>
void for_each(InputIterator first,
              InputIterator last,
              UnaryFunction f)
{
  typedef typename thrust::iterator_difference<InputIterator>::type difference;
  difference n = thrust::distance(first,last);

#pragma omp parallel for
  for(difference i = 0;
      i < n;
      ++i)
  {
    InputIterator temp = first + i;
    f(dereference(temp));
  }
}

} // end namespace omp
} // end namespace device
} // end namespace detail
} // end namespace thrust

#endif // _OPENMP

<|endoftext|>


<commit_before>#include <string>
#include <jni.h>
#include <tightdb.hpp>
#include <tightdb/lang_bind_helper.hpp>

#include "util.h"
#include "com_tightdb_Group.h"

using namespace tightdb;

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_createNative__(
	JNIEnv* env, jobject jGroup)
{
	return reinterpret_cast<jlong>(new Group());
}

/* !!! TODO:
    Update interface :

enum GroupMode {
    GROUP_DEFAULT  =  0,
    GROUP_READONLY =  1,
    GROUP_SHARED   =  2,
    GROUP_APPEND   =  4,
    GROUP_ASYNC    =  8,
    GROUP_SWAPONLY = 16
};
*/

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_createNative__Ljava_lang_String_2Z(
	JNIEnv* env, jobject jGroup, jstring jFileName, jboolean readOnly)
{
	const char* fileNameCharPtr = env->GetStringUTFChars(jFileName, NULL);
	if (fileNameCharPtr == NULL)
		return NULL;

	Group* pGroup = new Group(fileNameCharPtr, readOnly != 0 ? GROUP_READONLY : GROUP_DEFAULT);
	if (!pGroup->is_valid()) {
		delete pGroup;
		ThrowException(env, IllegalArgument, "Group(): File is not a valid tightdb database");
		return NULL;
	}
	return reinterpret_cast<jlong>(pGroup);
}

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_createNative___3B(
	JNIEnv* env, jobject jGroup, jbyteArray jData)
{
	jbyte* jbytePtr = env->GetByteArrayElements(jData, NULL);
	if (jbytePtr == NULL) {
		ThrowException(env, IllegalArgument, "Unable to fetch the buffer");
		return NULL;
	}
	jlong byteArrayLength = env->GetArrayLength(jData);     // CHECK, FIXME: Does this return a long?
	Group* pGroup = new Group((const char*)jbytePtr, S(byteArrayLength));
	if (!pGroup->is_valid()) {
	    delete pGroup;
        ThrowException(env, IllegalArgument, "Data is not a valid tightdb database");
	    return NULL;
	}
	return reinterpret_cast<jlong>(pGroup);
}

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_createNative__Ljava_nio_ByteBuffer_2(
	JNIEnv* env, jobject jTableBase, jobject jByteBuffer)
{
    // !!! TODO: Check Buffer for NULL!!!
	Group* pGroup = new Group(static_cast<const char*>(env->GetDirectBufferAddress(jByteBuffer)),
        S(env->GetDirectBufferCapacity(jByteBuffer)));
	if (!(pGroup->is_valid())) {
		delete pGroup;
        ThrowException(env, IllegalArgument, "Data is not a valid tightdb database");
		return NULL;
	}
	return reinterpret_cast<jlong>(pGroup);
}

JNIEXPORT void JNICALL Java_com_tightdb_Group_nativeClose(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	delete G(nativeGroupPtr);
}

JNIEXPORT jboolean JNICALL Java_com_tightdb_Group_nativeIsValid(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	return G(nativeGroupPtr)->is_valid();
}

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_nativeGetTableCount(
	JNIEnv *env, jobject jGroup, jlong nativeGroupPtr)
{
    return static_cast<jlong>( G(nativeGroupPtr)->get_table_count() );
}

JNIEXPORT jboolean JNICALL Java_com_tightdb_Group_nativeHasTable(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr, jstring jTableName)
{
	const char* tableNameCharPtr = env->GetStringUTFChars(jTableName, NULL);
    if (tableNameCharPtr) {
	    bool result = G(nativeGroupPtr)->has_table(tableNameCharPtr);
	    env->ReleaseStringUTFChars(jTableName, tableNameCharPtr);
	    return result;
    }
    // (exception is thrown by GetStringUTFChars if it fails.)
    return NULL;
}

JNIEXPORT jstring JNICALL Java_com_tightdb_Group_nativeGetTableName(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr, jint index)
{
	const char* nameCharPtr = G(nativeGroupPtr)->get_table_name(index);
	return env->NewStringUTF(nameCharPtr);
}

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_nativeGetTableNativePtr(
	JNIEnv *env, jobject jGroup, jlong nativeGroupPtr, jstring name)
{
	const char* tableNameCharPtr = env->GetStringUTFChars(name, NULL);
    if (tableNameCharPtr) {
	    Table* pTable = LangBindHelper::get_table_ptr(G(nativeGroupPtr), tableNameCharPtr);
	    env->ReleaseStringUTFChars(name, tableNameCharPtr);
	    return (jlong)pTable;
    }
    // (exception is thrown by GetStringUTFChars if it fails.)
    return 0;
}

JNIEXPORT void JNICALL Java_com_tightdb_Group_nativeWriteToFile(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr, jstring jFileName)
{
	const char* fileNameCharPtr = env->GetStringUTFChars(jFileName, NULL);
	if (fileNameCharPtr) {
	    bool success = G(nativeGroupPtr)->write(fileNameCharPtr);
        if (!success)
            ThrowException(env, IOFailed, fileNameCharPtr);
	    env->ReleaseStringUTFChars(jFileName, fileNameCharPtr);
    }
    // (exception is thrown by GetStringUTFChars if it fails.)
}

JNIEXPORT jbyteArray JNICALL Java_com_tightdb_Group_nativeWriteToMem(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	size_t len;
	char* memValue = G(nativeGroupPtr)->write_to_mem(len);
    jbyteArray jByteArray;
    if (len <= MAX_JSIZE) {
        jsize jlen = static_cast<jsize>(len);
        jByteArray = env->NewByteArray(jlen);
	    env->SetByteArrayRegion(jByteArray, 0, jlen, (const jbyte*)memValue);
    } else {
        jByteArray = NULL;
        ThrowException(env, IndexOutOfBounds, "Group too big to write.");
    }
    free(memValue); // Data was copied to array - so we can free data.
	return jByteArray;
}

JNIEXPORT jobject JNICALL Java_com_tightdb_Group_nativeWriteToByteBuffer(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	size_t len;
	char* memValue = G(nativeGroupPtr)->write_to_mem(len);
	if (len <= MAX_JLONG) {
        return env->NewDirectByteBuffer(static_cast<void*>(memValue), static_cast<jlong>(len));
        // Data is NOT copied in DirectByteBuffer - so we can't free it.
    } else {
        ThrowException(env, IndexOutOfBounds, "Group too big to write.");
        return NULL;
    }
}

JNIEXPORT jboolean JNICALL Java_com_tightdb_Group_nativeCommit(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	return G(nativeGroupPtr)->commit();
}<commit_msg>Better error check in Group()<commit_after>#include <string>
#include <jni.h>
#include <tightdb.hpp>
#include <tightdb/lang_bind_helper.hpp>

#include "util.h"
#include "com_tightdb_Group.h"

using namespace tightdb;

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_createNative__(
	JNIEnv* env, jobject jGroup)
{
	return reinterpret_cast<jlong>(new Group());
}

/* !!! TODO:
    Update interface :

enum GroupMode {
    GROUP_DEFAULT  =  0,
    GROUP_READONLY =  1,
    GROUP_SHARED   =  2,
    GROUP_APPEND   =  4,
    GROUP_ASYNC    =  8,
    GROUP_SWAPONLY = 16
};
*/

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_createNative__Ljava_lang_String_2Z(
	JNIEnv* env, jobject jGroup, jstring jFileName, jboolean readOnly)
{
	const char* fileNameCharPtr = env->GetStringUTFChars(jFileName, NULL);
	if (fileNameCharPtr == NULL)
		return NULL;        // Exception is thrown by GetStringUTFChars()

	Group* pGroup = new Group(fileNameCharPtr, readOnly != 0 ? GROUP_READONLY : GROUP_DEFAULT);
	if (!pGroup->is_valid()) {
		delete pGroup;
		ThrowException(env, IllegalArgument, "Group(): File is not a valid tightdb database");
		return NULL;
	}
	return reinterpret_cast<jlong>(pGroup);
}

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_createNative___3B(
	JNIEnv* env, jobject jGroup, jbyteArray jData)
{
	jbyte* jbytePtr = env->GetByteArrayElements(jData, NULL);
	if (jbytePtr == NULL) {
		ThrowException(env, IllegalArgument, "Unable to fetch the buffer");
		return NULL;
	}
	jlong byteArrayLength = env->GetArrayLength(jData);     // CHECK, FIXME: Does this return a long?
	Group* pGroup = new Group((const char*)jbytePtr, S(byteArrayLength));
	if (!pGroup->is_valid()) {
	    delete pGroup;
        ThrowException(env, IllegalArgument, "Data is not a valid tightdb database");
	    return NULL;
	}
	return reinterpret_cast<jlong>(pGroup);
}

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_createNative__Ljava_nio_ByteBuffer_2(
	JNIEnv* env, jobject jTableBase, jobject jByteBuffer)
{
    BinaryData data;
    if (!GetBinaryData(env, jByteBuffer, data))
        return 0;

	Group* pGroup = new Group(data.pointer, data.len);
	if (!(pGroup->is_valid())) {
		delete pGroup;
        ThrowException(env, IllegalArgument, "Data is not a valid tightdb database");
		return 0;
	}
	return reinterpret_cast<jlong>(pGroup);
}

JNIEXPORT void JNICALL Java_com_tightdb_Group_nativeClose(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	delete G(nativeGroupPtr);
}

JNIEXPORT jboolean JNICALL Java_com_tightdb_Group_nativeIsValid(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	return G(nativeGroupPtr)->is_valid();
}

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_nativeGetTableCount(
	JNIEnv *env, jobject jGroup, jlong nativeGroupPtr)
{
    return static_cast<jlong>( G(nativeGroupPtr)->get_table_count() );
}

JNIEXPORT jboolean JNICALL Java_com_tightdb_Group_nativeHasTable(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr, jstring jTableName)
{
	const char* tableNameCharPtr = env->GetStringUTFChars(jTableName, NULL);
    if (tableNameCharPtr) {
	    bool result = G(nativeGroupPtr)->has_table(tableNameCharPtr);
	    env->ReleaseStringUTFChars(jTableName, tableNameCharPtr);
	    return result;
    }
    // (exception is thrown by GetStringUTFChars if it fails.)
    return NULL;
}

JNIEXPORT jstring JNICALL Java_com_tightdb_Group_nativeGetTableName(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr, jint index)
{
	const char* nameCharPtr = G(nativeGroupPtr)->get_table_name(index);
	return env->NewStringUTF(nameCharPtr);
}

JNIEXPORT jlong JNICALL Java_com_tightdb_Group_nativeGetTableNativePtr(
	JNIEnv *env, jobject jGroup, jlong nativeGroupPtr, jstring name)
{
	const char* tableNameCharPtr = env->GetStringUTFChars(name, NULL);
    if (tableNameCharPtr) {
	    Table* pTable = LangBindHelper::get_table_ptr(G(nativeGroupPtr), tableNameCharPtr);
	    env->ReleaseStringUTFChars(name, tableNameCharPtr);
	    return (jlong)pTable;
    }
    // (exception is thrown by GetStringUTFChars if it fails.)
    return 0;
}

JNIEXPORT void JNICALL Java_com_tightdb_Group_nativeWriteToFile(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr, jstring jFileName)
{
	const char* fileNameCharPtr = env->GetStringUTFChars(jFileName, NULL);
	if (fileNameCharPtr) {
	    bool success = G(nativeGroupPtr)->write(fileNameCharPtr);
        if (!success)
            ThrowException(env, IOFailed, fileNameCharPtr);
	    env->ReleaseStringUTFChars(jFileName, fileNameCharPtr);
    }
    // (exception is thrown by GetStringUTFChars if it fails.)
}

JNIEXPORT jbyteArray JNICALL Java_com_tightdb_Group_nativeWriteToMem(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	size_t len;
	char* memValue = G(nativeGroupPtr)->write_to_mem(len);
    jbyteArray jByteArray;
    if (len <= MAX_JSIZE) {
        jsize jlen = static_cast<jsize>(len);
        jByteArray = env->NewByteArray(jlen);
	    env->SetByteArrayRegion(jByteArray, 0, jlen, (const jbyte*)memValue);
    } else {
        jByteArray = NULL;
        ThrowException(env, IndexOutOfBounds, "Group too big to write.");
    }
    free(memValue); // Data was copied to array - so we can free data.
	return jByteArray;
}

JNIEXPORT jobject JNICALL Java_com_tightdb_Group_nativeWriteToByteBuffer(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	size_t len;
	char* memValue = G(nativeGroupPtr)->write_to_mem(len);
	if (len <= MAX_JLONG) {
        return env->NewDirectByteBuffer(static_cast<void*>(memValue), static_cast<jlong>(len));
        // Data is NOT copied in DirectByteBuffer - so we can't free it.
    } else {
        ThrowException(env, IndexOutOfBounds, "Group too big to write.");
        return NULL;
    }
}

JNIEXPORT jboolean JNICALL Java_com_tightdb_Group_nativeCommit(
	JNIEnv* env, jobject jGroup, jlong nativeGroupPtr)
{
	return G(nativeGroupPtr)->commit();
}<|endoftext|>