<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2015 Couchbase, Inc
 *
 *   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 "alloc_hooks.h"
#include <stdbool.h>

#include "memcached/visibility.h"
#include <platform/cb_malloc.h>

/* Irrespective of how jemalloc was configured on this platform,
* don't rename je_FOO to FOO.
*/
#define JEMALLOC_NO_RENAME

/*
 * If we are on Windows, we need to declare this to make sure
 * that dllexport is configured correctly
 */
#ifdef WIN32
#define DLLEXPORT
#endif

#include <jemalloc/jemalloc.h>
#include <logger/logger.h>

#if defined(HAVE_MEMALIGN)
#include <malloc.h>
#endif

/* jemalloc checks for this symbol, and it's contents for the config to use. */
JEMALLOC_EXPORT
const char* je_malloc_conf =
        /* Use just one arena, instead of the default based on number of CPUs.
           Helps to minimize heap fragmentation. */
        "narenas:1"
        /* Start with profiling enabled but inactive; this allows us to
           turn it on/off at runtime. */
        ",prof:true,prof_active:false";

static int jemalloc_get_stats_prop(const char* property, size_t* value) {
    size_t size = sizeof(*value);
    return je_mallctl(property, value, &size, NULL, 0);
}

struct write_state {
    char* buffer;
    int remaining;
    bool cropped;
};
static const char cropped_error[] = "=== Exceeded buffer size - output cropped ===\n";

/* Write callback used by jemalloc's malloc_stats_print() below */
static void write_cb(void* opaque, const char* msg) {
    int len;
    struct write_state* st = (struct write_state*) opaque;
    if (st->cropped) {
        /* already cropped output - nothing to do. */
        return;
    }
    len = snprintf(st->buffer, st->remaining, "%s", msg);
    if (len < 0) {
        /*
         * snprintf _FAILED_. Terminate the buffer where it used to be
         * and ignore the rest
         */
        st->buffer[0] = '\0';
        return;
    }
    if (len > st->remaining) {
        /* insufficient space - have to crop output. Note we reserved enough
           space (see below) to be able to write an error if this occurs. */
        sprintf(st->buffer, cropped_error);
        st->cropped = true;
        return;
    }
    st->buffer += len;
    st->remaining -= len;
}

void JemallocHooks::initialize() {
    // No initialization required.
}

bool JemallocHooks::add_new_hook(void (* hook)(const void* ptr, size_t size)) {
    return cb_add_new_hook(hook);
}

bool JemallocHooks::remove_new_hook(void (* hook)(const void* ptr, size_t size)) {
    return cb_remove_new_hook(hook);
}

bool JemallocHooks::add_delete_hook(void (* hook)(const void* ptr)) {
    return cb_add_delete_hook(hook);
}

bool JemallocHooks::remove_delete_hook(void (* hook)(const void* ptr)) {
    return cb_remove_delete_hook(hook);
}

int JemallocHooks::get_extra_stats_size() {
    return 0;
}

void JemallocHooks::get_allocator_stats(allocator_stats* stats) {
    size_t epoch = 1;
    size_t sz = sizeof(epoch);
    /* jemalloc can cache its statistics - force a refresh */
    je_mallctl("epoch", &epoch, &sz, &epoch, sz);

    jemalloc_get_stats_prop("stats.allocated", &(stats->allocated_size));
    jemalloc_get_stats_prop("stats.mapped", &(stats->heap_size));
    jemalloc_get_stats_prop("stats.retained", &stats->retained_size);
    jemalloc_get_stats_prop("stats.resident", &stats->resident_size);
    jemalloc_get_stats_prop("stats.metadata", &stats->metadata_size);

    size_t active_bytes;
    jemalloc_get_stats_prop("stats.active", &active_bytes);
    stats->fragmentation_size = active_bytes - stats->allocated_size;
}

size_t JemallocHooks::get_allocation_size(const void* ptr) {
    /* je_malloc_usable_size on my linux masks this down to
     * malloc_usable_size causing it to omit a compiler warning.
     * Let's just nuke away the const here, as you may always
     * pass a non-const pointer to a function who accepts a
     * const pointer
     */
    return je_malloc_usable_size((void*) ptr);
}

void JemallocHooks::get_detailed_stats(char* buffer, int size) {
    struct write_state st;
    st.buffer = buffer;
    st.cropped = false;
    /* reserve enough space to write out an error if the output is cropped. */
    st.remaining = size - sizeof(cropped_error);
    je_malloc_stats_print(write_cb, &st, "a"/* omit per-arena stats*/);
}

void JemallocHooks::release_free_memory() {
    /* Note: jemalloc doesn't necessarily free this memory
     * immediately, but it will schedule to be freed as soon as is
     * possible.
     *
     * See: http://www.canonware.com/download/jemalloc/jemalloc-latest/doc/jemalloc.html,
     * specifically mallctl() for informaiton how the MIB api works.
     */

    /* lookup current number of arenas, then use that to invoke
     * 'arenas.NARENAS.purge' (replacing the '0' with NARENAS) to
     * release any dirty pages back to the OS.
     */
    unsigned int narenas;
    size_t len = sizeof(narenas);
    int err = je_mallctl("arenas.narenas", &narenas, &len, NULL, 0);
    if (err != 0) {
        LOG_WARNING(
                "jemalloc_release_free_memory() error {} - "
                "could not determine narenas.",
                err);

        return;
    }
    size_t mib[3]; /* Components in "arena.0.purge" MIB. */
    size_t miblen = sizeof(mib) / sizeof(mib[0]);
    err = je_mallctlnametomib("arena.0.purge", mib, &miblen);
    if (err != 0) {
        LOG_WARNING(
                "jemalloc_release_free_memory() error {} - "
                "could not lookup MIB.",
                err);
        return;
    }
    mib[1] = narenas;
    err = je_mallctlbymib(mib, miblen, NULL, 0, NULL, 0);
    if (err != 0) {
        LOG_WARNING(
                "jemalloc_release_free_memory() error {} - "
                "could not invoke arenas.N.purge.",
                err);
    }
}

bool JemallocHooks::enable_thread_cache(bool enable) {
    bool old;
    size_t size = sizeof(old);
    int err = je_mallctl("thread.tcache.enabled", &old, &size, &enable,
                         sizeof(enable));
    if (err != 0) {
        LOG_WARNING("jemalloc_enable_thread_cache({}) error {}",
                    (enable ? "true" : "false"),
                    err);
    }
    return old;
}

bool JemallocHooks::get_allocator_property(const char* name, size_t* value) {
    return jemalloc_get_stats_prop(name, value);
}

int JemallocHooks::set_allocator_property(const char* name,
                                          void* newp,
                                          size_t newlen) {
    return je_mallctl(name, nullptr, 0, newp, newlen);
}
<commit_msg>MB-30029: Enable Jemalloc background threads<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2015 Couchbase, Inc
 *
 *   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 "alloc_hooks.h"
#include <stdbool.h>

#include "memcached/visibility.h"
#include <platform/cb_malloc.h>

/* Irrespective of how jemalloc was configured on this platform,
* don't rename je_FOO to FOO.
*/
#define JEMALLOC_NO_RENAME

/*
 * If we are on Windows, we need to declare this to make sure
 * that dllexport is configured correctly
 */
#ifdef WIN32
#define DLLEXPORT
#endif

#include <jemalloc/jemalloc.h>
#include <logger/logger.h>

#if defined(HAVE_MEMALIGN)
#include <malloc.h>
#endif

/* jemalloc checks for this symbol, and it's contents for the config to use. */
JEMALLOC_EXPORT
const char* je_malloc_conf =
/* Enable background worker thread for asynchronous purging.
 * Background threads are non-functional in jemalloc 5.1.0 on macOS due to
 * implementation discrepancies between the background threads and mutexes.
 */
#ifndef __APPLE__
        "background_thread:true,"
#endif
        /* Use just one arena, instead of the default based on number of CPUs.
           Helps to minimize heap fragmentation. */
        "narenas:1,"
        /* Start with profiling enabled but inactive; this allows us to
           turn it on/off at runtime. */
        "prof:true,prof_active:false";

static int jemalloc_get_stats_prop(const char* property, size_t* value) {
    size_t size = sizeof(*value);
    return je_mallctl(property, value, &size, NULL, 0);
}

struct write_state {
    char* buffer;
    int remaining;
    bool cropped;
};
static const char cropped_error[] = "=== Exceeded buffer size - output cropped ===\n";

/* Write callback used by jemalloc's malloc_stats_print() below */
static void write_cb(void* opaque, const char* msg) {
    int len;
    struct write_state* st = (struct write_state*) opaque;
    if (st->cropped) {
        /* already cropped output - nothing to do. */
        return;
    }
    len = snprintf(st->buffer, st->remaining, "%s", msg);
    if (len < 0) {
        /*
         * snprintf _FAILED_. Terminate the buffer where it used to be
         * and ignore the rest
         */
        st->buffer[0] = '\0';
        return;
    }
    if (len > st->remaining) {
        /* insufficient space - have to crop output. Note we reserved enough
           space (see below) to be able to write an error if this occurs. */
        sprintf(st->buffer, cropped_error);
        st->cropped = true;
        return;
    }
    st->buffer += len;
    st->remaining -= len;
}

void JemallocHooks::initialize() {
    // No initialization required.
}

bool JemallocHooks::add_new_hook(void (* hook)(const void* ptr, size_t size)) {
    return cb_add_new_hook(hook);
}

bool JemallocHooks::remove_new_hook(void (* hook)(const void* ptr, size_t size)) {
    return cb_remove_new_hook(hook);
}

bool JemallocHooks::add_delete_hook(void (* hook)(const void* ptr)) {
    return cb_add_delete_hook(hook);
}

bool JemallocHooks::remove_delete_hook(void (* hook)(const void* ptr)) {
    return cb_remove_delete_hook(hook);
}

int JemallocHooks::get_extra_stats_size() {
    return 0;
}

void JemallocHooks::get_allocator_stats(allocator_stats* stats) {
    size_t epoch = 1;
    size_t sz = sizeof(epoch);
    /* jemalloc can cache its statistics - force a refresh */
    je_mallctl("epoch", &epoch, &sz, &epoch, sz);

    jemalloc_get_stats_prop("stats.allocated", &(stats->allocated_size));
    jemalloc_get_stats_prop("stats.mapped", &(stats->heap_size));
    jemalloc_get_stats_prop("stats.retained", &stats->retained_size);
    jemalloc_get_stats_prop("stats.resident", &stats->resident_size);
    jemalloc_get_stats_prop("stats.metadata", &stats->metadata_size);

    size_t active_bytes;
    jemalloc_get_stats_prop("stats.active", &active_bytes);
    stats->fragmentation_size = active_bytes - stats->allocated_size;
}

size_t JemallocHooks::get_allocation_size(const void* ptr) {
    /* je_malloc_usable_size on my linux masks this down to
     * malloc_usable_size causing it to omit a compiler warning.
     * Let's just nuke away the const here, as you may always
     * pass a non-const pointer to a function who accepts a
     * const pointer
     */
    return je_malloc_usable_size((void*) ptr);
}

void JemallocHooks::get_detailed_stats(char* buffer, int size) {
    struct write_state st;
    st.buffer = buffer;
    st.cropped = false;
    /* reserve enough space to write out an error if the output is cropped. */
    st.remaining = size - sizeof(cropped_error);
    je_malloc_stats_print(write_cb, &st, "a"/* omit per-arena stats*/);
}

void JemallocHooks::release_free_memory() {
    /* Note: jemalloc doesn't necessarily free this memory
     * immediately, but it will schedule to be freed as soon as is
     * possible.
     *
     * See: http://www.canonware.com/download/jemalloc/jemalloc-latest/doc/jemalloc.html,
     * specifically mallctl() for informaiton how the MIB api works.
     */

    /* lookup current number of arenas, then use that to invoke
     * 'arenas.NARENAS.purge' (replacing the '0' with NARENAS) to
     * release any dirty pages back to the OS.
     */
    unsigned int narenas;
    size_t len = sizeof(narenas);
    int err = je_mallctl("arenas.narenas", &narenas, &len, NULL, 0);
    if (err != 0) {
        LOG_WARNING(
                "jemalloc_release_free_memory() error {} - "
                "could not determine narenas.",
                err);

        return;
    }
    size_t mib[3]; /* Components in "arena.0.purge" MIB. */
    size_t miblen = sizeof(mib) / sizeof(mib[0]);
    err = je_mallctlnametomib("arena.0.purge", mib, &miblen);
    if (err != 0) {
        LOG_WARNING(
                "jemalloc_release_free_memory() error {} - "
                "could not lookup MIB.",
                err);
        return;
    }
    mib[1] = narenas;
    err = je_mallctlbymib(mib, miblen, NULL, 0, NULL, 0);
    if (err != 0) {
        LOG_WARNING(
                "jemalloc_release_free_memory() error {} - "
                "could not invoke arenas.N.purge.",
                err);
    }
}

bool JemallocHooks::enable_thread_cache(bool enable) {
    bool old;
    size_t size = sizeof(old);
    int err = je_mallctl("thread.tcache.enabled", &old, &size, &enable,
                         sizeof(enable));
    if (err != 0) {
        LOG_WARNING("jemalloc_enable_thread_cache({}) error {}",
                    (enable ? "true" : "false"),
                    err);
    }
    return old;
}

bool JemallocHooks::get_allocator_property(const char* name, size_t* value) {
    return jemalloc_get_stats_prop(name, value);
}

int JemallocHooks::set_allocator_property(const char* name,
                                          void* newp,
                                          size_t newlen) {
    return je_mallctl(name, nullptr, 0, newp, newlen);
}
<|endoftext|>


<commit_before>/*
KSync - Client-Server synchronization system using rsync.
Copyright (C) 2014  Matthew Scott Krafczyk

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

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

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

#include <unistd.h>
#include <iostream>
#include <sstream>

#include "ksync/logging.h"
#include "ksync/client.h"
#include "ksync/messages.h"
#include "ksync/socket_ops.h"

#include "ArgParse/ArgParse.h"

int main(int argc, char** argv) {
	char* login_name = getlogin();
	if(login_name == 0) {
		Error("Couldn't get the username!\n");
		return -1;
	}

	std::stringstream ss;
	ss << "ipc:///temp/" << login_name << "/ksync-connect.ipc";

	std::string connect_socket_url = ss.str();

	ArgParse::ArgParser arg_parser("KSync Server - Client side of a Client-Server synchonization system using rsync.");
	arg_parser.AddArgument("connect-socket", "Socket to use to negotiate new client connections. Default is : ipc:///ksync/<user>/ksync-connect.ipc", &connect_socket_url);

	if(arg_parser.ParseArgs(argc, argv) < 0) {
		Error("Problem parsing arguments\n");
		arg_parser.PrintHelp();
		return -1;
	}

	if(arg_parser.HelpPrinted()) {
		return 0;
	}

	int connection_socket = 0;
	int connection_endpoint = 0;

	printf("create and connect\n");

	errno=0;
	Debug("Error: %i (%s)\n", nn_errno(), nn_strerror(nn_errno()));
	if(KSync::SocketOps::Create_And_Connect_Connection_Socket(connection_socket, connection_endpoint, connect_socket_url) < 0) {
		Error("Encountered an error trying to create and connect to the connection socket\n");
		return -1;
	}
	Debug("Error: %i (%s)\n", nn_errno(), nn_strerror(nn_errno()));

	printf("send\n");

	std::string message = "test_message";
	if(KSync::SocketOps::Send_Message(message, connection_socket) < 0) {
		Warning("There was a problem sending a message to the server.\n");
	}

	printf("shutdown\n");

	if(KSync::SocketOps::Shutdown_Socket(connection_socket, connection_endpoint) < 0) {
		Warning("There was a problem shutting down the client side of the connection socket.\n");
	}

	return 0;
}
<commit_msg>Use get_socket_dir for default socket directory in client<commit_after>/*
KSync - Client-Server synchronization system using rsync.
Copyright (C) 2014  Matthew Scott Krafczyk

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

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

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

#include <unistd.h>
#include <iostream>
#include <sstream>

#include "ksync/logging.h"
#include "ksync/client.h"
#include "ksync/messages.h"
#include "ksync/socket_ops.h"
#include "ksync/utilities.h"

#include "ArgParse/ArgParse.h"

int main(int argc, char** argv) {
	std::string connect_socket_url = "";
	bool connect_socket_url_defined = false;

	ArgParse::ArgParser arg_parser("KSync Server - Client side of a Client-Server synchonization system using rsync.");
	arg_parser.AddArgument("connect-socket", "Socket to use to negotiate new client connections. Default is : ipc:///ksync/<user>/ksync-connect.ipc", &connect_socket_url, ArgParse::Argument::Optional, &connect_socket_url_defined);

	if(arg_parser.ParseArgs(argc, argv) < 0) {
		Error("Problem parsing arguments\n");
		arg_parser.PrintHelp();
		return -1;
	}

	if(arg_parser.HelpPrinted()) {
		return 0;
	}

	if(!connect_socket_url_defined){
		std::string socket_dir;
		if(KSync::Utilities::get_socket_dir(socket_dir) < 0) {
			Error("There was a problem getting the default socket directory!\n");
			return -2;
		}
		std::stringstream ss;
		ss << "ipc://" << socket_dir << "/ksync-connect.ipc";
		connect_socket_url = ss.str();
	}

	int connection_socket = 0;
	int connection_endpoint = 0;

	printf("create and connect\n");

	errno=0;
	Debug("Error: %i (%s)\n", nn_errno(), nn_strerror(nn_errno()));
	if(KSync::SocketOps::Create_And_Connect_Connection_Socket(connection_socket, connection_endpoint, connect_socket_url) < 0) {
		Error("Encountered an error trying to create and connect to the connection socket\n");
		return -1;
	}
	Debug("Error: %i (%s)\n", nn_errno(), nn_strerror(nn_errno()));

	printf("send\n");

	std::string message = "test_message";
	if(KSync::SocketOps::Send_Message(message, connection_socket) < 0) {
		Warning("There was a problem sending a message to the server.\n");
	}

	printf("shutdown\n");

	if(KSync::SocketOps::Shutdown_Socket(connection_socket, connection_endpoint) < 0) {
		Warning("There was a problem shutting down the client side of the connection socket.\n");
	}

	return 0;
}
<|endoftext|>


<commit_before>/* dtkComposerNodeControlFor.cpp ---
 *
 * Author: tkloczko
 * Copyright (C) 2011 - Thibaud Kloczko, Inria.
 * Created: Wed Feb 15 09:14:22 2012 (+0100)
 * Version: $Id$
 * Last-Updated: 2012 Thu Nov 15 15:00:57 (+0100)
 *           By: Thibaud Kloczko, Inria.
 *     Update #: 194
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerNodeControlForEach.h"

#include "dtkComposerNodeComposite.h"
#include "dtkComposerNodeProxy.h"

#include "dtkComposerTransmitter.h"
#include "dtkComposerTransmitterEmitter.h"
#include "dtkComposerTransmitterProxy.h"
#include "dtkComposerTransmitterVariant.h"

#include <dtkCore/dtkAbstractData.h>
#include <dtkCore/dtkGlobal.h>

#include <dtkContainer/dtkAbstractContainerWrapper.h>

// /////////////////////////////////////////////////////////////////
// dtkComposerNodeControlForEachPrivate interface
// /////////////////////////////////////////////////////////////////

class dtkComposerNodeControlForEachPrivate
{
public:
    dtkComposerNodeProxy header;
    dtkComposerNodeProxy footer;

    dtkComposerNodeComposite body_block;

public:
    dtkComposerTransmitterVariant header_rcv;

    dtkComposerTransmitterProxy              block_container;
    dtkComposerTransmitterEmitter<qlonglong> block_size;
    dtkComposerTransmitterEmitter<qlonglong> block_index;
    dtkComposerTransmitterVariant            block_item;

public:
    qlonglong counter;
    qlonglong size;

    const dtkAbstractContainerWrapper *container;
};

// /////////////////////////////////////////////////////////////////
// dtkComposerNodeControlForEach implementation
// /////////////////////////////////////////////////////////////////

dtkComposerNodeControlForEach::dtkComposerNodeControlForEach(void) : dtkComposerNodeControl(), d(new dtkComposerNodeControlForEachPrivate)
{
    d->header.removeEmitter(0);
    d->header.removeReceiver(0);
    d->header.appendReceiver(&(d->header_rcv));
    d->header.setInputLabelHint("container", 0);
    d->header.setAsHeader(true);

    d->footer.removeReceiver(0);
    d->footer.removeEmitter(0);
    d->footer.setAsFooter(true);

    d->body_block.setTitleHint("Body");
    d->body_block.setInputLabelHint("container", 0);
    d->body_block.appendReceiver(&(d->block_container));
    d->body_block.setInputLabelHint("size", 1);
    d->body_block.appendReceiver(&(d->block_size));
    d->body_block.setInputLabelHint("index", 2);
    d->body_block.appendReceiver(&(d->block_index));
    d->body_block.setInputLabelHint("item", 3);
    d->body_block.appendReceiver(&(d->block_item));

    d->block_container.appendPrevious(&d->header_rcv);
    d->header_rcv.appendNext(&d->block_container);

    d->counter = 0;
    d->block_index.setData(&d->counter);

    d->size = -1;
    d->block_size.setData(&d->size);

    d->container = NULL;
}

dtkComposerNodeControlForEach::~dtkComposerNodeControlForEach(void)
{
    delete d;

    d = NULL;
}

int dtkComposerNodeControlForEach::blockCount(void)
{
    return 1;
}

dtkComposerNodeLeaf *dtkComposerNodeControlForEach::header(void)
{
    return &(d->header);
}

dtkComposerNodeLeaf *dtkComposerNodeControlForEach::footer(void)
{
    return &(d->footer);
}

dtkComposerNodeComposite *dtkComposerNodeControlForEach::block(int id)
{
    if(id == 0)
        return &(d->body_block);

    return NULL;
}

void dtkComposerNodeControlForEach::setInputs(void)
{
    if (d->header_rcv.isEmpty())
        return;

    d->container = d->header_rcv.constContainer();
    d->counter = 0;
    d->size = d->container->count();

    foreach(dtkComposerTransmitterVariant *v, this->inputTwins()) {
        v->setTwinned(false);
        v->setDataFrom(v);
        v->setTwinned(true);
    }
}

void dtkComposerNodeControlForEach::setOutputs(void)
{
    foreach(dtkComposerTransmitterVariant *v, this->outputTwins()) {
        v->twin()->setDataFrom(v);
    }

    ++(d->counter);
}

void dtkComposerNodeControlForEach::setVariables(void)
{
    d->block_item.setData(d->container->at(d->counter));
}

int dtkComposerNodeControlForEach::selectBranch(void)
{
    return static_cast<int>(!((d->counter) < d->size));
}

void dtkComposerNodeControlForEach::begin(void)
{

}

void dtkComposerNodeControlForEach::end(void)
{

}

QString dtkComposerNodeControlForEach::type(void)
{
    return "foreach";
}

QString dtkComposerNodeControlForEach::titleHint(void)
{
    return "For Each";
}
<commit_msg>check if container is NULL<commit_after>/* dtkComposerNodeControlFor.cpp ---
 *
 * Author: tkloczko
 * Copyright (C) 2011 - Thibaud Kloczko, Inria.
 * Created: Wed Feb 15 09:14:22 2012 (+0100)
 * Version: $Id$
 * Last-Updated: jeu. juil. 11 12:18:14 2013 (+0200)
 *           By: Nicolas Niclausse
 *     Update #: 197
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerNodeControlForEach.h"

#include "dtkComposerNodeComposite.h"
#include "dtkComposerNodeProxy.h"

#include "dtkComposerTransmitter.h"
#include "dtkComposerTransmitterEmitter.h"
#include "dtkComposerTransmitterProxy.h"
#include "dtkComposerTransmitterVariant.h"

#include <dtkCore/dtkAbstractData.h>
#include <dtkCore/dtkGlobal.h>

#include <dtkContainer/dtkAbstractContainerWrapper.h>

// /////////////////////////////////////////////////////////////////
// dtkComposerNodeControlForEachPrivate interface
// /////////////////////////////////////////////////////////////////

class dtkComposerNodeControlForEachPrivate
{
public:
    dtkComposerNodeProxy header;
    dtkComposerNodeProxy footer;

    dtkComposerNodeComposite body_block;

public:
    dtkComposerTransmitterVariant header_rcv;

    dtkComposerTransmitterProxy              block_container;
    dtkComposerTransmitterEmitter<qlonglong> block_size;
    dtkComposerTransmitterEmitter<qlonglong> block_index;
    dtkComposerTransmitterVariant            block_item;

public:
    qlonglong counter;
    qlonglong size;

    const dtkAbstractContainerWrapper *container;
};

// /////////////////////////////////////////////////////////////////
// dtkComposerNodeControlForEach implementation
// /////////////////////////////////////////////////////////////////

dtkComposerNodeControlForEach::dtkComposerNodeControlForEach(void) : dtkComposerNodeControl(), d(new dtkComposerNodeControlForEachPrivate)
{
    d->header.removeEmitter(0);
    d->header.removeReceiver(0);
    d->header.appendReceiver(&(d->header_rcv));
    d->header.setInputLabelHint("container", 0);
    d->header.setAsHeader(true);

    d->footer.removeReceiver(0);
    d->footer.removeEmitter(0);
    d->footer.setAsFooter(true);

    d->body_block.setTitleHint("Body");
    d->body_block.setInputLabelHint("container", 0);
    d->body_block.appendReceiver(&(d->block_container));
    d->body_block.setInputLabelHint("size", 1);
    d->body_block.appendReceiver(&(d->block_size));
    d->body_block.setInputLabelHint("index", 2);
    d->body_block.appendReceiver(&(d->block_index));
    d->body_block.setInputLabelHint("item", 3);
    d->body_block.appendReceiver(&(d->block_item));

    d->block_container.appendPrevious(&d->header_rcv);
    d->header_rcv.appendNext(&d->block_container);

    d->counter = 0;
    d->block_index.setData(&d->counter);

    d->size = -1;
    d->block_size.setData(&d->size);

    d->container = NULL;
}

dtkComposerNodeControlForEach::~dtkComposerNodeControlForEach(void)
{
    delete d;

    d = NULL;
}

int dtkComposerNodeControlForEach::blockCount(void)
{
    return 1;
}

dtkComposerNodeLeaf *dtkComposerNodeControlForEach::header(void)
{
    return &(d->header);
}

dtkComposerNodeLeaf *dtkComposerNodeControlForEach::footer(void)
{
    return &(d->footer);
}

dtkComposerNodeComposite *dtkComposerNodeControlForEach::block(int id)
{
    if(id == 0)
        return &(d->body_block);

    return NULL;
}

void dtkComposerNodeControlForEach::setInputs(void)
{
    if (d->header_rcv.isEmpty())
        return;

    d->container = d->header_rcv.constContainer();

    if (!d->container)
        return;

    d->counter = 0;
    d->size = d->container->count();

    foreach(dtkComposerTransmitterVariant *v, this->inputTwins()) {
        v->setTwinned(false);
        v->setDataFrom(v);
        v->setTwinned(true);
    }
}

void dtkComposerNodeControlForEach::setOutputs(void)
{
    foreach(dtkComposerTransmitterVariant *v, this->outputTwins()) {
        v->twin()->setDataFrom(v);
    }

    ++(d->counter);
}

void dtkComposerNodeControlForEach::setVariables(void)
{
    d->block_item.setData(d->container->at(d->counter));
}

int dtkComposerNodeControlForEach::selectBranch(void)
{
    return static_cast<int>(!((d->counter) < d->size));
}

void dtkComposerNodeControlForEach::begin(void)
{

}

void dtkComposerNodeControlForEach::end(void)
{

}

QString dtkComposerNodeControlForEach::type(void)
{
    return "foreach";
}

QString dtkComposerNodeControlForEach::titleHint(void)
{
    return "For Each";
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include "eventql/config/config_directory_standalone.h"

namespace eventql {

StandaloneConfigDirectory::StandaloneConfigDirectory(
    const String& datadir,
    const String& listen_addr) :
    listen_addr_(listen_addr) {
  cluster_config_.set_replication_factor(1);

  mdb::MDBOptions opts;
  opts.data_filename = "standalone.db";
  opts.lock_filename = "standalone.db.lck";
  db_ = mdb::MDB::open(datadir, opts);
}

Status StandaloneConfigDirectory::start() {
  if (db_.get()) {
    auto txn = db_->startTransaction(false);
    auto cursor = txn->getCursor();

    for (int i = 0; ; ++i) {
      Buffer key;
      Buffer value;
      if (i == 0) {
        if (!cursor->getFirst(&key, &value)) {
          break;
        }
      } else {
        if (!cursor->getNext(&key, &value)) {
          break;
        }
      }

      auto db_key = key.toString();

      if (StringUtil::beginsWith(db_key, "db~")) {
        auto cfg = msg::decode<NamespaceConfig>(value);
        namespaces_.emplace(cfg.customer(), cfg);
      }

      if (StringUtil::beginsWith(db_key, "tbl~")) {
        auto cfg = msg::decode<TableDefinition>(value);
        tables_.emplace(
            StringUtil::format("$0~$1", cfg.customer(), cfg.table_name()),
            cfg);
      }
    }

    cursor->close();
    txn->abort();
  }

  return Status::success();
}

void StandaloneConfigDirectory::stop() {}

ClusterConfig StandaloneConfigDirectory::getClusterConfig() const {
  std::unique_lock<std::mutex> lk(mutex_);
  return cluster_config_;
}

void StandaloneConfigDirectory::updateClusterConfig(ClusterConfig config) {
  std::unique_lock<std::mutex> lk(mutex_);
  cluster_config_ = config;
  auto callbacks = on_cluster_change_;
  lk.unlock();
  for (const auto& cb : callbacks) {
    cb(config);
  }
}

void StandaloneConfigDirectory::setClusterConfigChangeCallback(
    Function<void (const ClusterConfig& cfg)> fn) {
  std::unique_lock<std::mutex> lk(mutex_);
  on_cluster_change_.emplace_back(fn);
}

String StandaloneConfigDirectory::getServerID() const {
  return "localhost";
}

ServerConfig StandaloneConfigDirectory::getServerConfig(
    const String& server_name) const {
  if (server_name != "localhost") {
    RAISEF(kNotFoundError, "server not found: $0", server_name);
  }

  ServerConfig c;
  c.set_server_id("localhost");
  c.set_server_addr(listen_addr_);
  c.set_server_status(SERVER_UP);
  return c;
}

Vector<ServerConfig> StandaloneConfigDirectory::listServers() const {
  Vector<ServerConfig> servers;
  servers.emplace_back(getServerConfig("localhost"));
  return servers;
}

void StandaloneConfigDirectory::setServerConfigChangeCallback(
    Function<void (const ServerConfig& cfg)> fn) {
  // void
}

void StandaloneConfigDirectory::updateServerConfig(ServerConfig cfg) {
  // void
}

RefPtr<NamespaceConfigRef> StandaloneConfigDirectory::getNamespaceConfig(
    const String& customer_key) const {
  std::unique_lock<std::mutex> lk(mutex_);
  auto iter = namespaces_.find(customer_key);
  if (iter == namespaces_.end()) {
    RAISEF(kNotFoundError, "namespace not found: $0", customer_key);
  }

  return mkRef(new NamespaceConfigRef(iter->second));
}

void StandaloneConfigDirectory::listNamespaces(
    Function<void (const NamespaceConfig& cfg)> fn) const {
  std::unique_lock<std::mutex> lk(mutex_);
  for (const auto& ns : namespaces_) {
    fn(ns.second);
  }
}

void StandaloneConfigDirectory::setNamespaceConfigChangeCallback(
    Function<void (const NamespaceConfig& cfg)> fn) {
  std::unique_lock<std::mutex> lk(mutex_);
  on_namespace_change_.emplace_back(fn);
}

void StandaloneConfigDirectory::updateNamespaceConfig(NamespaceConfig cfg) {
  std::unique_lock<std::mutex> lk(mutex_);
  namespaces_.emplace(cfg.customer(), cfg);
  auto callbacks = on_namespace_change_;

  if (db_.get()) {
    auto db_key = StringUtil::format("db~$0", cfg.customer());
    auto db_val = *msg::encode(cfg);
    auto txn = db_->startTransaction(false);
    txn->update(
        db_key.data(),
        db_key.size(),
        db_val.data(),
        db_val.size());

    txn->commit();
  }

  lk.unlock();
  for (const auto& cb : callbacks) {
    cb(cfg);
  }
}

TableDefinition StandaloneConfigDirectory::getTableConfig(
    const String& db_namespace,
    const String& table_name) const {
  std::unique_lock<std::mutex> lk(mutex_);
  auto iter = tables_.find(db_namespace + "~" + table_name);
  if (iter == tables_.end()) {
    RAISEF(kNotFoundError, "table not found: $0", table_name);
  }

  return iter->second;
}

void StandaloneConfigDirectory::updateTableConfig(
    const TableDefinition& table,
    bool force /* = false */) {
  std::unique_lock<std::mutex> lk(mutex_);
  auto table_id = table.customer() + "~" + table.table_name();
  if (tables_.find(table_id) != tables_.end()) {
    RAISEF(
        kIllegalArgumentError,
        "table already exists: $0",
        table.table_name());
  }

  tables_.emplace(table_id, table);
  auto callbacks = on_table_change_;

  if (db_.get()) {
    auto db_key = StringUtil::format(
        "tbl~$0~$1",
        table.customer(),
        table.table_name());

    auto db_val = *msg::encode(table);
    auto txn = db_->startTransaction(false);
    txn->update(
        db_key.data(),
        db_key.size(),
        db_val.data(),
        db_val.size());

    txn->commit();
  }

  lk.unlock();
  for (const auto& cb : callbacks) {
    cb(table);
  }
}

void StandaloneConfigDirectory::listTables(
    Function<void (const TableDefinition& table)> fn) const {
  std::unique_lock<std::mutex> lk(mutex_);
  for (const auto& tbl : tables_) {
    fn(tbl.second);
  }
}

void StandaloneConfigDirectory::setTableConfigChangeCallback(
    Function<void (const TableDefinition& tbl)> fn) {
  std::unique_lock<std::mutex> lk(mutex_);
  on_table_change_.emplace_back(fn);
}

} // namespace eventql

<commit_msg>StandaloneConfigDirectory::{is,get}Leader<commit_after>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include "eventql/config/config_directory_standalone.h"

namespace eventql {

StandaloneConfigDirectory::StandaloneConfigDirectory(
    const String& datadir,
    const String& listen_addr) :
    listen_addr_(listen_addr) {
  cluster_config_.set_replication_factor(1);

  mdb::MDBOptions opts;
  opts.data_filename = "standalone.db";
  opts.lock_filename = "standalone.db.lck";
  db_ = mdb::MDB::open(datadir, opts);
}

Status StandaloneConfigDirectory::start() {
  if (db_.get()) {
    auto txn = db_->startTransaction(false);
    auto cursor = txn->getCursor();

    for (int i = 0; ; ++i) {
      Buffer key;
      Buffer value;
      if (i == 0) {
        if (!cursor->getFirst(&key, &value)) {
          break;
        }
      } else {
        if (!cursor->getNext(&key, &value)) {
          break;
        }
      }

      auto db_key = key.toString();

      if (StringUtil::beginsWith(db_key, "db~")) {
        auto cfg = msg::decode<NamespaceConfig>(value);
        namespaces_.emplace(cfg.customer(), cfg);
      }

      if (StringUtil::beginsWith(db_key, "tbl~")) {
        auto cfg = msg::decode<TableDefinition>(value);
        tables_.emplace(
            StringUtil::format("$0~$1", cfg.customer(), cfg.table_name()),
            cfg);
      }
    }

    cursor->close();
    txn->abort();
  }

  return Status::success();
}

void StandaloneConfigDirectory::stop() {}

ClusterConfig StandaloneConfigDirectory::getClusterConfig() const {
  std::unique_lock<std::mutex> lk(mutex_);
  return cluster_config_;
}

void StandaloneConfigDirectory::updateClusterConfig(ClusterConfig config) {
  std::unique_lock<std::mutex> lk(mutex_);
  cluster_config_ = config;
  auto callbacks = on_cluster_change_;
  lk.unlock();
  for (const auto& cb : callbacks) {
    cb(config);
  }
}

void StandaloneConfigDirectory::setClusterConfigChangeCallback(
    Function<void (const ClusterConfig& cfg)> fn) {
  std::unique_lock<std::mutex> lk(mutex_);
  on_cluster_change_.emplace_back(fn);
}

String StandaloneConfigDirectory::getServerID() const {
  return "localhost";
}

bool StandaloneConfigDirectory::isLeader() const {
  return true;
}

String StandaloneConfigDirectory::getLeader() const {
  return "localhost";
}

ServerConfig StandaloneConfigDirectory::getServerConfig(
    const String& server_name) const {
  if (server_name != "localhost") {
    RAISEF(kNotFoundError, "server not found: $0", server_name);
  }

  ServerConfig c;
  c.set_server_id("localhost");
  c.set_server_addr(listen_addr_);
  c.set_server_status(SERVER_UP);
  return c;
}

Vector<ServerConfig> StandaloneConfigDirectory::listServers() const {
  Vector<ServerConfig> servers;
  servers.emplace_back(getServerConfig("localhost"));
  return servers;
}

void StandaloneConfigDirectory::setServerConfigChangeCallback(
    Function<void (const ServerConfig& cfg)> fn) {
  // void
}

void StandaloneConfigDirectory::updateServerConfig(ServerConfig cfg) {
  // void
}

RefPtr<NamespaceConfigRef> StandaloneConfigDirectory::getNamespaceConfig(
    const String& customer_key) const {
  std::unique_lock<std::mutex> lk(mutex_);
  auto iter = namespaces_.find(customer_key);
  if (iter == namespaces_.end()) {
    RAISEF(kNotFoundError, "namespace not found: $0", customer_key);
  }

  return mkRef(new NamespaceConfigRef(iter->second));
}

void StandaloneConfigDirectory::listNamespaces(
    Function<void (const NamespaceConfig& cfg)> fn) const {
  std::unique_lock<std::mutex> lk(mutex_);
  for (const auto& ns : namespaces_) {
    fn(ns.second);
  }
}

void StandaloneConfigDirectory::setNamespaceConfigChangeCallback(
    Function<void (const NamespaceConfig& cfg)> fn) {
  std::unique_lock<std::mutex> lk(mutex_);
  on_namespace_change_.emplace_back(fn);
}

void StandaloneConfigDirectory::updateNamespaceConfig(NamespaceConfig cfg) {
  std::unique_lock<std::mutex> lk(mutex_);
  namespaces_.emplace(cfg.customer(), cfg);
  auto callbacks = on_namespace_change_;

  if (db_.get()) {
    auto db_key = StringUtil::format("db~$0", cfg.customer());
    auto db_val = *msg::encode(cfg);
    auto txn = db_->startTransaction(false);
    txn->update(
        db_key.data(),
        db_key.size(),
        db_val.data(),
        db_val.size());

    txn->commit();
  }

  lk.unlock();
  for (const auto& cb : callbacks) {
    cb(cfg);
  }
}

TableDefinition StandaloneConfigDirectory::getTableConfig(
    const String& db_namespace,
    const String& table_name) const {
  std::unique_lock<std::mutex> lk(mutex_);
  auto iter = tables_.find(db_namespace + "~" + table_name);
  if (iter == tables_.end()) {
    RAISEF(kNotFoundError, "table not found: $0", table_name);
  }

  return iter->second;
}

void StandaloneConfigDirectory::updateTableConfig(
    const TableDefinition& table,
    bool force /* = false */) {
  std::unique_lock<std::mutex> lk(mutex_);
  auto table_id = table.customer() + "~" + table.table_name();
  if (tables_.find(table_id) != tables_.end()) {
    RAISEF(
        kIllegalArgumentError,
        "table already exists: $0",
        table.table_name());
  }

  tables_.emplace(table_id, table);
  auto callbacks = on_table_change_;

  if (db_.get()) {
    auto db_key = StringUtil::format(
        "tbl~$0~$1",
        table.customer(),
        table.table_name());

    auto db_val = *msg::encode(table);
    auto txn = db_->startTransaction(false);
    txn->update(
        db_key.data(),
        db_key.size(),
        db_val.data(),
        db_val.size());

    txn->commit();
  }

  lk.unlock();
  for (const auto& cb : callbacks) {
    cb(table);
  }
}

void StandaloneConfigDirectory::listTables(
    Function<void (const TableDefinition& table)> fn) const {
  std::unique_lock<std::mutex> lk(mutex_);
  for (const auto& tbl : tables_) {
    fn(tbl.second);
  }
}

void StandaloneConfigDirectory::setTableConfigChangeCallback(
    Function<void (const TableDefinition& tbl)> fn) {
  std::unique_lock<std::mutex> lk(mutex_);
  on_table_change_.emplace_back(fn);
}

} // namespace eventql

<|endoftext|>


<commit_before>//
// Copyright 2012 Francisco Jerez
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#include "api/util.hpp"
#include "core/program.hpp"

using namespace clover;

PUBLIC cl_program
clCreateProgramWithSource(cl_context ctx, cl_uint count,
                          const char **strings, const size_t *lengths,
                          cl_int *errcode_ret) try {
   std::string source;

   if (!ctx)
      throw error(CL_INVALID_CONTEXT);

   if (!count || !strings ||
       any_of(is_zero<const char *>(), strings, strings + count))
      throw error(CL_INVALID_VALUE);

   // Concatenate all the provided fragments together
   for (unsigned i = 0; i < count; ++i)
         source += (lengths && lengths[i] ?
                    std::string(strings[i], strings[i] + lengths[i]) :
                    std::string(strings[i]));

   // ...and create a program object for them.
   ret_error(errcode_ret, CL_SUCCESS);
   return new program(*ctx, source);

} catch (error &e) {
   ret_error(errcode_ret, e);
   return NULL;
}

PUBLIC cl_program
clCreateProgramWithBinary(cl_context ctx, cl_uint count,
                          const cl_device_id *devs, const size_t *lengths,
                          const unsigned char **binaries, cl_int *status_ret,
                          cl_int *errcode_ret) try {
   if (!ctx)
      throw error(CL_INVALID_CONTEXT);

   if (!count || !devs || !lengths || !binaries)
      throw error(CL_INVALID_VALUE);

   if (any_of([&](const cl_device_id dev) {
            return !ctx->has_device(dev);
         }, devs, devs + count))
      throw error(CL_INVALID_DEVICE);

   // Deserialize the provided binaries,
   auto modules = map(
      [](const unsigned char *p, size_t l) -> std::pair<cl_int, module> {
         if (!p || !l)
            return { CL_INVALID_VALUE, {} };

         try {
            compat::istream::buffer_t bin(p, l);
            compat::istream s(bin);

            return { CL_SUCCESS, module::deserialize(s) };

         } catch (compat::istream::error &e) {
            return { CL_INVALID_BINARY, {} };
         }
      },
      binaries, binaries + count, lengths);

   // update the status array,
   if (status_ret)
      std::transform(modules.begin(), modules.end(), status_ret,
                     keys<cl_int, module>);

   if (any_of(key_equals<cl_int, module>(CL_INVALID_VALUE),
              modules.begin(), modules.end()))
      throw error(CL_INVALID_VALUE);

   if (any_of(key_equals<cl_int, module>(CL_INVALID_BINARY),
              modules.begin(), modules.end()))
      throw error(CL_INVALID_BINARY);

   // initialize a program object with them.
   ret_error(errcode_ret, CL_SUCCESS);
   return new program(*ctx, { devs, devs + count },
                      map(values<cl_int, module>,
                          modules.begin(), modules.end()));

} catch (error &e) {
   ret_error(errcode_ret, e);
   return NULL;
}

PUBLIC cl_int
clRetainProgram(cl_program prog) {
   if (!prog)
      return CL_INVALID_PROGRAM;

   prog->retain();
   return CL_SUCCESS;
}

PUBLIC cl_int
clReleaseProgram(cl_program prog) {
   if (!prog)
      return CL_INVALID_PROGRAM;

   if (prog->release())
      delete prog;

   return CL_SUCCESS;
}

PUBLIC cl_int
clBuildProgram(cl_program prog, cl_uint count, const cl_device_id *devs,
               const char *opts, void (*pfn_notify)(cl_program, void *),
               void *user_data) try {
   if (!prog)
      throw error(CL_INVALID_PROGRAM);

   if (bool(count) != bool(devs) ||
       (!pfn_notify && user_data))
      throw error(CL_INVALID_VALUE);

   if (any_of([&](const cl_device_id dev) {
            return !prog->ctx.has_device(dev);
         }, devs, devs + count))
      throw error(CL_INVALID_DEVICE);

   prog->build({ devs, devs + count });
   return CL_SUCCESS;

} catch (error &e) {
   return e.get();
}

PUBLIC cl_int
clUnloadCompiler() {
   return CL_SUCCESS;
}

PUBLIC cl_int
clGetProgramInfo(cl_program prog, cl_program_info param,
                 size_t size, void *buf, size_t *size_ret) {
   if (!prog)
      return CL_INVALID_PROGRAM;

   switch (param) {
   case CL_PROGRAM_REFERENCE_COUNT:
      return scalar_property<cl_uint>(buf, size, size_ret,
                                      prog->ref_count());

   case CL_PROGRAM_CONTEXT:
      return scalar_property<cl_context>(buf, size, size_ret,
                                         &prog->ctx);

   case CL_PROGRAM_NUM_DEVICES:
      return scalar_property<cl_uint>(buf, size, size_ret,
                                      prog->binaries().size());

   case CL_PROGRAM_DEVICES:
      return vector_property<cl_device_id>(
         buf, size, size_ret,
         map(keys<device *, module>,
             prog->binaries().begin(), prog->binaries().end()));

   case CL_PROGRAM_SOURCE:
      return string_property(buf, size, size_ret, prog->source());

   case CL_PROGRAM_BINARY_SIZES:
      return vector_property<size_t>(
         buf, size, size_ret,
         map([](const std::pair<device *, module> &ent) {
               compat::ostream::buffer_t bin;
               compat::ostream s(bin);
               ent.second.serialize(s);
               return bin.size();
            },
            prog->binaries().begin(), prog->binaries().end()));

   case CL_PROGRAM_BINARIES:
      return matrix_property<unsigned char>(
         buf, size, size_ret,
         map([](const std::pair<device *, module> &ent) {
               compat::ostream::buffer_t bin;
               compat::ostream s(bin);
               ent.second.serialize(s);
               return bin;
            },
            prog->binaries().begin(), prog->binaries().end()));

   default:
      return CL_INVALID_VALUE;
   }
}

PUBLIC cl_int
clGetProgramBuildInfo(cl_program prog, cl_device_id dev,
                      cl_program_build_info param,
                      size_t size, void *buf, size_t *size_ret) {
   if (!prog)
      return CL_INVALID_PROGRAM;

   if (!prog->ctx.has_device(dev))
      return CL_INVALID_DEVICE;

   switch (param) {
   case CL_PROGRAM_BUILD_STATUS:
      return scalar_property<cl_build_status>(buf, size, size_ret,
                                              prog->build_status(dev));

   case CL_PROGRAM_BUILD_OPTIONS:
      return string_property(buf, size, size_ret, prog->build_opts(dev));

   case CL_PROGRAM_BUILD_LOG:
      return string_property(buf, size, size_ret, prog->build_log(dev));

   default:
      return CL_INVALID_VALUE;
   }
}
<commit_msg>clover: Handle NULL devs argument in clBuildProgram<commit_after>//
// Copyright 2012 Francisco Jerez
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#include "api/util.hpp"
#include "core/program.hpp"

using namespace clover;

PUBLIC cl_program
clCreateProgramWithSource(cl_context ctx, cl_uint count,
                          const char **strings, const size_t *lengths,
                          cl_int *errcode_ret) try {
   std::string source;

   if (!ctx)
      throw error(CL_INVALID_CONTEXT);

   if (!count || !strings ||
       any_of(is_zero<const char *>(), strings, strings + count))
      throw error(CL_INVALID_VALUE);

   // Concatenate all the provided fragments together
   for (unsigned i = 0; i < count; ++i)
         source += (lengths && lengths[i] ?
                    std::string(strings[i], strings[i] + lengths[i]) :
                    std::string(strings[i]));

   // ...and create a program object for them.
   ret_error(errcode_ret, CL_SUCCESS);
   return new program(*ctx, source);

} catch (error &e) {
   ret_error(errcode_ret, e);
   return NULL;
}

PUBLIC cl_program
clCreateProgramWithBinary(cl_context ctx, cl_uint count,
                          const cl_device_id *devs, const size_t *lengths,
                          const unsigned char **binaries, cl_int *status_ret,
                          cl_int *errcode_ret) try {
   if (!ctx)
      throw error(CL_INVALID_CONTEXT);

   if (!count || !devs || !lengths || !binaries)
      throw error(CL_INVALID_VALUE);

   if (any_of([&](const cl_device_id dev) {
            return !ctx->has_device(dev);
         }, devs, devs + count))
      throw error(CL_INVALID_DEVICE);

   // Deserialize the provided binaries,
   auto modules = map(
      [](const unsigned char *p, size_t l) -> std::pair<cl_int, module> {
         if (!p || !l)
            return { CL_INVALID_VALUE, {} };

         try {
            compat::istream::buffer_t bin(p, l);
            compat::istream s(bin);

            return { CL_SUCCESS, module::deserialize(s) };

         } catch (compat::istream::error &e) {
            return { CL_INVALID_BINARY, {} };
         }
      },
      binaries, binaries + count, lengths);

   // update the status array,
   if (status_ret)
      std::transform(modules.begin(), modules.end(), status_ret,
                     keys<cl_int, module>);

   if (any_of(key_equals<cl_int, module>(CL_INVALID_VALUE),
              modules.begin(), modules.end()))
      throw error(CL_INVALID_VALUE);

   if (any_of(key_equals<cl_int, module>(CL_INVALID_BINARY),
              modules.begin(), modules.end()))
      throw error(CL_INVALID_BINARY);

   // initialize a program object with them.
   ret_error(errcode_ret, CL_SUCCESS);
   return new program(*ctx, { devs, devs + count },
                      map(values<cl_int, module>,
                          modules.begin(), modules.end()));

} catch (error &e) {
   ret_error(errcode_ret, e);
   return NULL;
}

PUBLIC cl_int
clRetainProgram(cl_program prog) {
   if (!prog)
      return CL_INVALID_PROGRAM;

   prog->retain();
   return CL_SUCCESS;
}

PUBLIC cl_int
clReleaseProgram(cl_program prog) {
   if (!prog)
      return CL_INVALID_PROGRAM;

   if (prog->release())
      delete prog;

   return CL_SUCCESS;
}

PUBLIC cl_int
clBuildProgram(cl_program prog, cl_uint count, const cl_device_id *devs,
               const char *opts, void (*pfn_notify)(cl_program, void *),
               void *user_data) try {
   if (!prog)
      throw error(CL_INVALID_PROGRAM);

   if (bool(count) != bool(devs) ||
       (!pfn_notify && user_data))
      throw error(CL_INVALID_VALUE);

   if (devs) {
      if (any_of([&](const cl_device_id dev) {
               return !prog->ctx.has_device(dev);
            }, devs, devs + count))
         throw error(CL_INVALID_DEVICE);

      prog->build({ devs, devs + count });
   } else {
      prog->build(prog->ctx.devs);
   }

   return CL_SUCCESS;

} catch (error &e) {
   return e.get();
}

PUBLIC cl_int
clUnloadCompiler() {
   return CL_SUCCESS;
}

PUBLIC cl_int
clGetProgramInfo(cl_program prog, cl_program_info param,
                 size_t size, void *buf, size_t *size_ret) {
   if (!prog)
      return CL_INVALID_PROGRAM;

   switch (param) {
   case CL_PROGRAM_REFERENCE_COUNT:
      return scalar_property<cl_uint>(buf, size, size_ret,
                                      prog->ref_count());

   case CL_PROGRAM_CONTEXT:
      return scalar_property<cl_context>(buf, size, size_ret,
                                         &prog->ctx);

   case CL_PROGRAM_NUM_DEVICES:
      return scalar_property<cl_uint>(buf, size, size_ret,
                                      prog->binaries().size());

   case CL_PROGRAM_DEVICES:
      return vector_property<cl_device_id>(
         buf, size, size_ret,
         map(keys<device *, module>,
             prog->binaries().begin(), prog->binaries().end()));

   case CL_PROGRAM_SOURCE:
      return string_property(buf, size, size_ret, prog->source());

   case CL_PROGRAM_BINARY_SIZES:
      return vector_property<size_t>(
         buf, size, size_ret,
         map([](const std::pair<device *, module> &ent) {
               compat::ostream::buffer_t bin;
               compat::ostream s(bin);
               ent.second.serialize(s);
               return bin.size();
            },
            prog->binaries().begin(), prog->binaries().end()));

   case CL_PROGRAM_BINARIES:
      return matrix_property<unsigned char>(
         buf, size, size_ret,
         map([](const std::pair<device *, module> &ent) {
               compat::ostream::buffer_t bin;
               compat::ostream s(bin);
               ent.second.serialize(s);
               return bin;
            },
            prog->binaries().begin(), prog->binaries().end()));

   default:
      return CL_INVALID_VALUE;
   }
}

PUBLIC cl_int
clGetProgramBuildInfo(cl_program prog, cl_device_id dev,
                      cl_program_build_info param,
                      size_t size, void *buf, size_t *size_ret) {
   if (!prog)
      return CL_INVALID_PROGRAM;

   if (!prog->ctx.has_device(dev))
      return CL_INVALID_DEVICE;

   switch (param) {
   case CL_PROGRAM_BUILD_STATUS:
      return scalar_property<cl_build_status>(buf, size, size_ret,
                                              prog->build_status(dev));

   case CL_PROGRAM_BUILD_OPTIONS:
      return string_property(buf, size, size_ret, prog->build_opts(dev));

   case CL_PROGRAM_BUILD_LOG:
      return string_property(buf, size, size_ret, prog->build_log(dev));

   default:
      return CL_INVALID_VALUE;
   }
}
<|endoftext|>


<commit_before>// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#include <google/protobuf/compiler/cpp/cpp_extension.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {

ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
                                       const string& dllexport_decl)
  : descriptor_(descriptor),
    dllexport_decl_(dllexport_decl) {
  // Construct type_traits_.
  if (descriptor_->is_repeated()) {
    type_traits_ = "Repeated";
  }

  switch (descriptor_->cpp_type()) {
    case FieldDescriptor::CPPTYPE_ENUM:
      type_traits_.append("EnumTypeTraits< ");
      type_traits_.append(ClassName(descriptor_->enum_type(), true));
      type_traits_.append(", ");
      type_traits_.append(ClassName(descriptor_->enum_type(), true));
      type_traits_.append("_IsValid>");
      break;
    case FieldDescriptor::CPPTYPE_STRING:
      type_traits_.append("StringTypeTraits");
      break;
    case FieldDescriptor::CPPTYPE_MESSAGE:
      type_traits_.append("MessageTypeTraits< ");
      type_traits_.append(ClassName(descriptor_->message_type(), true));
      type_traits_.append(" >");
      break;
    default:
      type_traits_.append("PrimitiveTypeTraits< ");
      type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type()));
      type_traits_.append(" >");
      break;
  }
}

ExtensionGenerator::~ExtensionGenerator() {}

void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
  map<string, string> vars;
  vars["extendee"     ] = ClassName(descriptor_->containing_type(), true);
  vars["number"       ] = SimpleItoa(descriptor_->number());
  vars["type_traits"  ] = type_traits_;
  vars["name"         ] = descriptor_->name();
  vars["field_type"   ] = SimpleItoa(static_cast<int>(descriptor_->type()));
  vars["packed"       ] = descriptor_->options().packed() ? "true" : "false";
  vars["constant_name"] = FieldConstantName(descriptor_);

  // If this is a class member, it needs to be declared "static".  Otherwise,
  // it needs to be "extern".
  vars["qualifier"] =
    (descriptor_->extension_scope() == NULL) ? "extern" : "static";

  if (!dllexport_decl_.empty()) {
    vars["qualifier"] = dllexport_decl_ + " " + vars["qualifier"];
  }

  printer->Print(vars,
    "static const int $constant_name$ = $number$;\n"
    "$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
    "    ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
    "  $name$;\n"
    );
}

void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
  // If this is a class member, it needs to be declared in its class scope.
  string scope = (descriptor_->extension_scope() == NULL) ? "" :
    ClassName(descriptor_->extension_scope(), false) + "::";
  string name = scope + descriptor_->name();

  map<string, string> vars;
  vars["extendee"     ] = ClassName(descriptor_->containing_type(), true);
  vars["type_traits"  ] = type_traits_;
  vars["name"         ] = name;
  vars["constant_name"] = FieldConstantName(descriptor_);
  vars["default"      ] = DefaultValue(descriptor_);
  vars["field_type"   ] = SimpleItoa(static_cast<int>(descriptor_->type()));
  vars["packed"       ] = descriptor_->options().packed() ? "true" : "false";
  vars["scope"        ] = scope;

  if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
    // We need to declare a global string which will contain the default value.
    // We cannot declare it at class scope because that would require exposing
    // it in the header which would be annoying for other reasons.  So we
    // replace :: with _ in the name and declare it as a global.
    string global_name = StringReplace(name, "::", "_", true);
    vars["global_name"] = global_name;
    printer->Print(vars,
      "const ::std::string $global_name$_default($default$);\n");
    // Update the default to refer to the string global.
    vars["default"] = global_name + "_default";
  }

  // Likewise, class members need to declare the field constant variable.
  if (descriptor_->extension_scope() != NULL) {
    printer->Print(vars,
      "#ifndef _MSC_VER\n"
      "const int $scope$$constant_name$;\n"
      "#endif\n");
  }

  printer->Print(vars,
    "::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
    "    ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
    "  $name$($constant_name$, $default$);\n");
}

void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
  map<string, string> vars;
  vars["extendee"   ] = ClassName(descriptor_->containing_type(), true);
  vars["number"     ] = SimpleItoa(descriptor_->number());
  vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
  vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
  vars["is_packed"  ] = (descriptor_->is_repeated() &&
                         descriptor_->options().packed())
                        ? "true" : "false";

  switch (descriptor_->cpp_type()) {
    case FieldDescriptor::CPPTYPE_ENUM:
      printer->Print(vars,
        "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
        "  &$extendee$::default_instance(),\n"
        "  $number$, $field_type$, $is_repeated$, $is_packed$,\n");
      printer->Print(
        "  &$type$_IsValid);\n",
        "type", ClassName(descriptor_->enum_type(), true));
      break;
    case FieldDescriptor::CPPTYPE_MESSAGE:
      printer->Print(vars,
        "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
        "  &$extendee$::default_instance(),\n"
        "  $number$, $field_type$, $is_repeated$, $is_packed$,\n");
      printer->Print(
        "  &$type$::default_instance());\n",
        "type", ClassName(descriptor_->message_type(), true));
      break;
    default:
      printer->Print(vars,
        "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
        "  &$extendee$::default_instance(),\n"
        "  $number$, $field_type$, $is_repeated$, $is_packed$);\n");
      break;
  }
}

}  // namespace cpp
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
<commit_msg>Don't use dll-export declspec on class-nested extensions.<commit_after>// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#include <google/protobuf/compiler/cpp/cpp_extension.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {

ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
                                       const string& dllexport_decl)
  : descriptor_(descriptor),
    dllexport_decl_(dllexport_decl) {
  // Construct type_traits_.
  if (descriptor_->is_repeated()) {
    type_traits_ = "Repeated";
  }

  switch (descriptor_->cpp_type()) {
    case FieldDescriptor::CPPTYPE_ENUM:
      type_traits_.append("EnumTypeTraits< ");
      type_traits_.append(ClassName(descriptor_->enum_type(), true));
      type_traits_.append(", ");
      type_traits_.append(ClassName(descriptor_->enum_type(), true));
      type_traits_.append("_IsValid>");
      break;
    case FieldDescriptor::CPPTYPE_STRING:
      type_traits_.append("StringTypeTraits");
      break;
    case FieldDescriptor::CPPTYPE_MESSAGE:
      type_traits_.append("MessageTypeTraits< ");
      type_traits_.append(ClassName(descriptor_->message_type(), true));
      type_traits_.append(" >");
      break;
    default:
      type_traits_.append("PrimitiveTypeTraits< ");
      type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type()));
      type_traits_.append(" >");
      break;
  }
}

ExtensionGenerator::~ExtensionGenerator() {}

void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
  map<string, string> vars;
  vars["extendee"     ] = ClassName(descriptor_->containing_type(), true);
  vars["number"       ] = SimpleItoa(descriptor_->number());
  vars["type_traits"  ] = type_traits_;
  vars["name"         ] = descriptor_->name();
  vars["field_type"   ] = SimpleItoa(static_cast<int>(descriptor_->type()));
  vars["packed"       ] = descriptor_->options().packed() ? "true" : "false";
  vars["constant_name"] = FieldConstantName(descriptor_);

  // If this is a class member, it needs to be declared "static".  Otherwise,
  // it needs to be "extern".  In the latter case, it also needs the DLL
  // export/import specifier.
  if (descriptor_->extension_scope() == NULL) {
    vars["qualifier"] = "extern";
    if (!dllexport_decl_.empty()) {
      vars["qualifier"] = dllexport_decl_ + " " + vars["qualifier"];
    }
  } else {
    vars["qualifier"] = "static";
  }

  printer->Print(vars,
    "static const int $constant_name$ = $number$;\n"
    "$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
    "    ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
    "  $name$;\n"
    );
}

void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
  // If this is a class member, it needs to be declared in its class scope.
  string scope = (descriptor_->extension_scope() == NULL) ? "" :
    ClassName(descriptor_->extension_scope(), false) + "::";
  string name = scope + descriptor_->name();

  map<string, string> vars;
  vars["extendee"     ] = ClassName(descriptor_->containing_type(), true);
  vars["type_traits"  ] = type_traits_;
  vars["name"         ] = name;
  vars["constant_name"] = FieldConstantName(descriptor_);
  vars["default"      ] = DefaultValue(descriptor_);
  vars["field_type"   ] = SimpleItoa(static_cast<int>(descriptor_->type()));
  vars["packed"       ] = descriptor_->options().packed() ? "true" : "false";
  vars["scope"        ] = scope;

  if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
    // We need to declare a global string which will contain the default value.
    // We cannot declare it at class scope because that would require exposing
    // it in the header which would be annoying for other reasons.  So we
    // replace :: with _ in the name and declare it as a global.
    string global_name = StringReplace(name, "::", "_", true);
    vars["global_name"] = global_name;
    printer->Print(vars,
      "const ::std::string $global_name$_default($default$);\n");
    // Update the default to refer to the string global.
    vars["default"] = global_name + "_default";
  }

  // Likewise, class members need to declare the field constant variable.
  if (descriptor_->extension_scope() != NULL) {
    printer->Print(vars,
      "#ifndef _MSC_VER\n"
      "const int $scope$$constant_name$;\n"
      "#endif\n");
  }

  printer->Print(vars,
    "::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
    "    ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
    "  $name$($constant_name$, $default$);\n");
}

void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
  map<string, string> vars;
  vars["extendee"   ] = ClassName(descriptor_->containing_type(), true);
  vars["number"     ] = SimpleItoa(descriptor_->number());
  vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
  vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
  vars["is_packed"  ] = (descriptor_->is_repeated() &&
                         descriptor_->options().packed())
                        ? "true" : "false";

  switch (descriptor_->cpp_type()) {
    case FieldDescriptor::CPPTYPE_ENUM:
      printer->Print(vars,
        "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
        "  &$extendee$::default_instance(),\n"
        "  $number$, $field_type$, $is_repeated$, $is_packed$,\n");
      printer->Print(
        "  &$type$_IsValid);\n",
        "type", ClassName(descriptor_->enum_type(), true));
      break;
    case FieldDescriptor::CPPTYPE_MESSAGE:
      printer->Print(vars,
        "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
        "  &$extendee$::default_instance(),\n"
        "  $number$, $field_type$, $is_repeated$, $is_packed$,\n");
      printer->Print(
        "  &$type$::default_instance());\n",
        "type", ClassName(descriptor_->message_type(), true));
      break;
    default:
      printer->Print(vars,
        "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
        "  &$extendee$::default_instance(),\n"
        "  $number$, $field_type$, $is_repeated$, $is_packed$);\n");
      break;
  }
}

}  // namespace cpp
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
<|endoftext|>


<commit_before>/* Copyright 2015 Samsung Electronics Co., LTD
 *
 * 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 "util/jni_utils.h"
#include "objects/hybrid_object.h"
#include "objects/scene.h"
#include "objects/components/render_data.h"
#include "gl/gl_material.h"

namespace gvr {

RenderData::~RenderData() {
}

void RenderData::add_pass(RenderPass* render_pass) {
    render_pass_list_.push_back(render_pass);
    render_pass->add_dirty_flag(dirty_flag_);
    *dirty_flag_ |= (1 << RENDER_PASS);
}

const RenderPass* RenderData::pass(int pass) const {
    if (pass >= 0 && pass < render_pass_list_.size()) {
        return render_pass_list_[pass];
    }
}

void RenderData::set_mesh(Mesh* mesh) {
    mesh_ = mesh;
    mesh->add_dirty_flag(dirty_flag_);
    *dirty_flag_ |= (1 << NEW_MESH);
}

void RenderData::setDirty(u_short dirty){
    *dirty_flag_ = dirty;
}
    void RenderData::clearDirtyBits(u_short bits){
        *dirty_flag_ &= bits;
    }
bool RenderData::cull_face(int pass) const {
    if (pass >= 0 && pass < render_pass_list_.size()) {
        return render_pass_list_[pass]->cull_face();
    }
}

ShaderData* RenderData::material(int pass) const {
    if (pass >= 0 && pass < render_pass_list_.size()) {
        return render_pass_list_[pass]->material();
    }
}

void RenderData::setCameraDistanceLambda(std::function<float()> func)
{
    cameraDistanceLambda_ = func;
}

JNIEnv *RenderData::set_java(jobject javaObj, JavaVM *javaVM)
{
    JNIEnv *env = JavaComponent::set_java(javaObj, javaVM);
    if (env)
    {
        jclass renderDataClass = env->GetObjectClass(javaObj);
        bindShaderMethod_ = env->GetMethodID(renderDataClass, "bindShaderNative",
                                             "(Lorg/gearvrf/GVRScene;)V");
        if (bindShaderMethod_ == 0)
        {
            LOGE("RenderData::bindShader ERROR cannot find 'GVRRenderData.bindShaderNative()' Java method");
        }
    }
}

void RenderData::setStencilFunc(int func, int ref, int mask) {
    stencilFuncFunc_= func;
    stencilFuncRef_ = ref;
    stencilFuncMask_ = mask;
}

void RenderData::setStencilOp(int sfail, int dpfail, int dppass) {
    stencilOpSfail_ = sfail;
    stencilOpDpfail_ = dpfail;
    stencilOpDppass_ = dppass;
}

void RenderData::setStencilMask(unsigned int mask) {
    stencilMaskMask_ = mask;
}

void RenderData::setStencilTest(bool flag) {
    stencilTestFlag_ = flag;
}

/**
 * Called when the shader for a RenderData needs to be generated on the Java side.
 * This function spawns a Java task on the Framework thread which generates the shader.
 */
void RenderData::bindShader(Scene *scene)
{
    if ((bindShaderMethod_ == NULL) || (javaObj_ == NULL))
    {
        LOGE("SHADER: RenderData::bindShader could not call bindShaderNative");
    }

    JNIEnv* env = NULL;
    int rc = scene->get_java_env(&env);
    if (env && (rc >= 0))
    {
        LOGD("SHADER: Calling GVRRenderData.bindShaderNative(%p)", this);
        env->CallVoidMethod(javaObj_, bindShaderMethod_, scene->getJavaObj());
        if (rc > 0)
        {
            scene->getJavaVM()->DetachCurrentThread();
        }
    }
}

bool compareRenderDataByShader(RenderData *i, RenderData *j)
{
    // Compare renderData by their material's shader type
    // Note: multi-pass renderData is skipped for now and put to later position,
    // since each of the passes has a separate material (and shader as well).
    // An advanced sorting may be added later to take multi-pass into account
    if (j->pass_count() > 1) {
        return true;
    }

    if (i->pass_count() > 1) {
        return false;
    }

    return i->get_shader(0) < j->get_shader(0);
}

bool compareRenderDataByOrderShaderDistance(RenderData *i, RenderData *j) {
    //1. rendering order needs to be sorted first to guarantee specified correct order
    if (i->rendering_order() == j->rendering_order())
    {
        if (i->get_shader(0) == j->get_shader(0))
        {
            int no_passes1 = i->pass_count();
            int no_passes2 = j->pass_count();

            if (no_passes1 == no_passes2)
            {
                // if it is a transparent object, sort by camera distance from back to front
                if (i->rendering_order() >= RenderData::Transparent
                    && i->rendering_order() < RenderData::Overlay)
                {
                    return i->camera_distance() > j->camera_distance();
                }

                //@todo what about the other passes

                //this is pointer comparison; assumes batching is on; if the materials are not
                //the same then comparing the pointers further is an arbitrary decision; hence
                //falling back to camera distance.
                if (i->material(0) == j->material(0))
                {
                    if (i->cull_face(0) == j->cull_face(0))
                    {
                        if (i->getHashCode().compare(j->getHashCode()) == 0)
                        {
                            // otherwise sort from front to back
                            return i->camera_distance() < j->camera_distance();
                        }
                        return i->getHashCode() < j->getHashCode();
                    }
                    return i->cull_face(0) < j->cull_face(0);
                }
                return i->material(0) < j->material(0);
            }
            return no_passes1 < no_passes2;
        }
        return i->get_shader() < j->get_shader();
    }
    return i->rendering_order() < j->rendering_order();
}

std::string RenderData::getHashCode()
{
    if (hash_code_dirty_)
    {
        std::string render_data_string;
        render_data_string.append(to_string(use_light_));
        render_data_string.append(to_string(getComponentType()));
        render_data_string.append(to_string(use_lightmap_));
        render_data_string.append(to_string(render_mask_));
        render_data_string.append(to_string(offset_));
        render_data_string.append(to_string(offset_factor_));
        render_data_string.append(to_string(offset_units_));
        render_data_string.append(to_string(depth_test_));
        render_data_string.append(to_string(alpha_blend_));
        render_data_string.append(to_string(alpha_to_coverage_));
        render_data_string.append(to_string(sample_coverage_));
        render_data_string.append(to_string(invert_coverage_mask_));
        render_data_string.append(to_string(draw_mode_));
        render_data_string.append(to_string(stencilTestFlag_));
        render_data_string.append(to_string(stencilMaskMask_));
        render_data_string.append(to_string(stencilFuncFunc_));
        render_data_string.append(to_string(stencilFuncRef_));
        render_data_string.append(to_string(stencilFuncMask_));
        render_data_string.append(to_string(stencilOpSfail_));
        render_data_string.append(to_string(stencilOpDpfail_));
        render_data_string.append(to_string(stencilOpDppass_));
        hash_code = render_data_string;
        hash_code_dirty_ = false;

    }
    return hash_code;
}

bool RenderData::updateGPU(Renderer* renderer, Shader* shader)
{
    if (mesh_->hasBones())
    {
        if (bones_ubo_ == NULL)
        {
            bones_ubo_ = renderer->createUniformBlock("mat4 u_bone_matrix[60];", BONES_UBO_INDEX, "Bones_ubo");
        }
        const std::vector<glm::mat4>& bone_matrices = mesh_->getVertexBoneData().getBoneMatrices();
        bones_ubo_->setFloatVec("u_bone_matrix", &bone_matrices[0][0][0], bone_matrices.size() * 16);
        bones_ubo_->updateGPU(renderer);
    }

    mesh_->getVertexBuffer()->updateGPU(renderer, mesh_->getIndexBuffer(), shader);
    return true;
}
}
<commit_msg>Use UniformArray for bones<commit_after>/* Copyright 2015 Samsung Electronics Co., LTD
 *
 * 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 "util/jni_utils.h"
#include "objects/hybrid_object.h"
#include "objects/scene.h"
#include "objects/components/render_data.h"
#include "gl/gl_material.h"

namespace gvr {

RenderData::~RenderData() {
}

void RenderData::add_pass(RenderPass* render_pass) {
    render_pass_list_.push_back(render_pass);
    render_pass->add_dirty_flag(dirty_flag_);
    *dirty_flag_ |= (1 << RENDER_PASS);
}

const RenderPass* RenderData::pass(int pass) const {
    if (pass >= 0 && pass < render_pass_list_.size()) {
        return render_pass_list_[pass];
    }
}

void RenderData::set_mesh(Mesh* mesh) {
    mesh_ = mesh;
    mesh->add_dirty_flag(dirty_flag_);
    *dirty_flag_ |= (1 << NEW_MESH);
}

void RenderData::setDirty(u_short dirty){
    *dirty_flag_ = dirty;
}
    void RenderData::clearDirtyBits(u_short bits){
        *dirty_flag_ &= bits;
    }
bool RenderData::cull_face(int pass) const {
    if (pass >= 0 && pass < render_pass_list_.size()) {
        return render_pass_list_[pass]->cull_face();
    }
}

ShaderData* RenderData::material(int pass) const {
    if (pass >= 0 && pass < render_pass_list_.size()) {
        return render_pass_list_[pass]->material();
    }
}

void RenderData::setCameraDistanceLambda(std::function<float()> func)
{
    cameraDistanceLambda_ = func;
}

JNIEnv *RenderData::set_java(jobject javaObj, JavaVM *javaVM)
{
    JNIEnv *env = JavaComponent::set_java(javaObj, javaVM);
    if (env)
    {
        jclass renderDataClass = env->GetObjectClass(javaObj);
        bindShaderMethod_ = env->GetMethodID(renderDataClass, "bindShaderNative",
                                             "(Lorg/gearvrf/GVRScene;)V");
        if (bindShaderMethod_ == 0)
        {
            LOGE("RenderData::bindShader ERROR cannot find 'GVRRenderData.bindShaderNative()' Java method");
        }
    }
}

void RenderData::setStencilFunc(int func, int ref, int mask) {
    stencilFuncFunc_= func;
    stencilFuncRef_ = ref;
    stencilFuncMask_ = mask;
}

void RenderData::setStencilOp(int sfail, int dpfail, int dppass) {
    stencilOpSfail_ = sfail;
    stencilOpDpfail_ = dpfail;
    stencilOpDppass_ = dppass;
}

void RenderData::setStencilMask(unsigned int mask) {
    stencilMaskMask_ = mask;
}

void RenderData::setStencilTest(bool flag) {
    stencilTestFlag_ = flag;
}

/**
 * Called when the shader for a RenderData needs to be generated on the Java side.
 * This function spawns a Java task on the Framework thread which generates the shader.
 */
void RenderData::bindShader(Scene *scene)
{
    if ((bindShaderMethod_ == NULL) || (javaObj_ == NULL))
    {
        LOGE("SHADER: RenderData::bindShader could not call bindShaderNative");
    }

    JNIEnv* env = NULL;
    int rc = scene->get_java_env(&env);
    if (env && (rc >= 0))
    {
        LOGD("SHADER: Calling GVRRenderData.bindShaderNative(%p)", this);
        env->CallVoidMethod(javaObj_, bindShaderMethod_, scene->getJavaObj());
        if (rc > 0)
        {
            scene->getJavaVM()->DetachCurrentThread();
        }
    }
}

bool compareRenderDataByShader(RenderData *i, RenderData *j)
{
    // Compare renderData by their material's shader type
    // Note: multi-pass renderData is skipped for now and put to later position,
    // since each of the passes has a separate material (and shader as well).
    // An advanced sorting may be added later to take multi-pass into account
    if (j->pass_count() > 1) {
        return true;
    }

    if (i->pass_count() > 1) {
        return false;
    }

    return i->get_shader(0) < j->get_shader(0);
}

bool compareRenderDataByOrderShaderDistance(RenderData *i, RenderData *j) {
    //1. rendering order needs to be sorted first to guarantee specified correct order
    if (i->rendering_order() == j->rendering_order())
    {
        if (i->get_shader(0) == j->get_shader(0))
        {
            int no_passes1 = i->pass_count();
            int no_passes2 = j->pass_count();

            if (no_passes1 == no_passes2)
            {
                // if it is a transparent object, sort by camera distance from back to front
                if (i->rendering_order() >= RenderData::Transparent
                    && i->rendering_order() < RenderData::Overlay)
                {
                    return i->camera_distance() > j->camera_distance();
                }

                //@todo what about the other passes

                //this is pointer comparison; assumes batching is on; if the materials are not
                //the same then comparing the pointers further is an arbitrary decision; hence
                //falling back to camera distance.
                if (i->material(0) == j->material(0))
                {
                    if (i->cull_face(0) == j->cull_face(0))
                    {
                        if (i->getHashCode().compare(j->getHashCode()) == 0)
                        {
                            // otherwise sort from front to back
                            return i->camera_distance() < j->camera_distance();
                        }
                        return i->getHashCode() < j->getHashCode();
                    }
                    return i->cull_face(0) < j->cull_face(0);
                }
                return i->material(0) < j->material(0);
            }
            return no_passes1 < no_passes2;
        }
        return i->get_shader() < j->get_shader();
    }
    return i->rendering_order() < j->rendering_order();
}

std::string RenderData::getHashCode()
{
    if (hash_code_dirty_)
    {
        std::string render_data_string;
        render_data_string.append(to_string(use_light_));
        render_data_string.append(to_string(getComponentType()));
        render_data_string.append(to_string(use_lightmap_));
        render_data_string.append(to_string(render_mask_));
        render_data_string.append(to_string(offset_));
        render_data_string.append(to_string(offset_factor_));
        render_data_string.append(to_string(offset_units_));
        render_data_string.append(to_string(depth_test_));
        render_data_string.append(to_string(alpha_blend_));
        render_data_string.append(to_string(alpha_to_coverage_));
        render_data_string.append(to_string(sample_coverage_));
        render_data_string.append(to_string(invert_coverage_mask_));
        render_data_string.append(to_string(draw_mode_));
        render_data_string.append(to_string(stencilTestFlag_));
        render_data_string.append(to_string(stencilMaskMask_));
        render_data_string.append(to_string(stencilFuncFunc_));
        render_data_string.append(to_string(stencilFuncRef_));
        render_data_string.append(to_string(stencilFuncMask_));
        render_data_string.append(to_string(stencilOpSfail_));
        render_data_string.append(to_string(stencilOpDpfail_));
        render_data_string.append(to_string(stencilOpDppass_));
        hash_code = render_data_string;
        hash_code_dirty_ = false;

    }
    return hash_code;
}

bool RenderData::updateGPU(Renderer* renderer, Shader* shader)
{
    VertexBuffer* vbuf = mesh_->getVertexBuffer();

    if (mesh_->hasBones())
    {
        VertexBoneData& vbd = mesh_->getVertexBoneData();
        const std::vector<glm::mat4>& bone_matrices = vbd.getBoneMatrices();
        int numBones = bone_matrices.size();

        if ((bones_ubo_ == NULL) && (numBones > 0))
        {
            bones_ubo_ = renderer->createUniformBlock("mat4 u_bone_matrix", BONES_UBO_INDEX, "Bones_ubo", 60);
            bones_ubo_->setNumElems(numBones);
        }
        bones_ubo_->setRange(0, bone_matrices.data(), numBones);
        bones_ubo_->updateGPU(renderer);
    }
    vbuf->updateGPU(renderer, mesh_->getIndexBuffer(), shader);
    return true;
}
}
<|endoftext|>


<commit_before>/*
 * This file is part of the Yildiz-Engine project, licenced under the MIT License  (MIT)
 *
 * Copyright (c) 2018 Grégory Van den Borre
 *
 * More infos available: https://www.yildiz-games.be
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  SOFTWARE.
 */

/**
*@author Grégory Van den Borre
*/

#include "../includes/Query.hpp"
#include "../includes/JniQuery.h"

JNIEXPORT jfloatArray JNICALL Java_jni_JniQuery_computeMoveDestinationGroundIntersect(
    JNIEnv* env,
    jobject,
    POINTER pointer,
    jfloat x,
    jfloat y) {
    LOG_FUNCTION
    return vectorToArray(env, reinterpret_cast<yz::Query*>(pointer)->throwRayPos(x, y));
}

JNIEXPORT POINTER JNICALL Java_jni_JniQuery_throwRay(
    JNIEnv* env,
    jobject,
    POINTER pointer,
    jfloat x,
    jfloat y,
    jboolean poly) {
    LOG_FUNCTION
    return reinterpret_cast<yz::Query*>(pointer)->throwRay(x, y, poly)->value();
}

JNIEXPORT jlongArray JNICALL Java_jni_JniQuery_throwPlaneRay(
    JNIEnv* env,
    jobject,
    POINTER pointer,
    jfloat left,
    jfloat top,
    jfloat right,
    jfloat bottom) {
    LOG_FUNCTION
    try {
        std::vector<yz::Id*> list = reinterpret_cast<yz::Query*>(pointer)->throwPlaneRay(left, right, top, bottom);

        if (list.empty()) {
            jlong buf[1];
            jlongArray result = env->NewLongArray(0);
            env->SetLongArrayRegion(result, 0, 0, buf);
            return result;
        }
        const int size = list.size();

        jlong* buf;
        buf = new jlong[size];
        for (int i = 0; i < size; i++) {
            buf[i] = list[i]->value();
        }
        jlongArray result = env->NewLongArray(size);
        env->SetLongArrayRegion(result, 0, size, buf);
        return result;
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
    return env->NewLongArray(1);
}
<commit_msg>[YE-0] Fix for camera.<commit_after>/*
 * This file is part of the Yildiz-Engine project, licenced under the MIT License  (MIT)
 *
 * Copyright (c) 2018 Grégory Van den Borre
 *
 * More infos available: https://www.yildiz-games.be
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  SOFTWARE.
 */

/**
*@author Grégory Van den Borre
*/

#include "../includes/Query.hpp"
#include "../includes/JniQuery.h"
#include "../includes/JniUtil.h"

JNIEXPORT jfloatArray JNICALL Java_jni_JniQuery_computeMoveDestinationGroundIntersect(
    JNIEnv* env,
    jobject,
    POINTER pointer,
    jfloat x,
    jfloat y) {
    LOG_FUNCTION
    return vectorToArray(env, reinterpret_cast<yz::Query*>(pointer)->throwRayPos(x, y));
}

JNIEXPORT POINTER JNICALL Java_jni_JniQuery_throwRay(
    JNIEnv* env,
    jobject,
    POINTER pointer,
    jfloat x,
    jfloat y,
    jboolean poly) {
    LOG_FUNCTION
    return reinterpret_cast<yz::Query*>(pointer)->throwRay(x, y, poly)->value();
}

JNIEXPORT jlongArray JNICALL Java_jni_JniQuery_throwPlaneRay(
    JNIEnv* env,
    jobject,
    POINTER pointer,
    jfloat left,
    jfloat top,
    jfloat right,
    jfloat bottom) {
    LOG_FUNCTION
    try {
        std::vector<yz::Id*> list = reinterpret_cast<yz::Query*>(pointer)->throwPlaneRay(left, right, top, bottom);

        if (list.empty()) {
            jlong buf[1];
            jlongArray result = env->NewLongArray(0);
            env->SetLongArrayRegion(result, 0, 0, buf);
            return result;
        }
        const int size = list.size();

        jlong* buf;
        buf = new jlong[size];
        for (int i = 0; i < size; i++) {
            buf[i] = list[i]->value();
        }
        jlongArray result = env->NewLongArray(size);
        env->SetLongArrayRegion(result, 0, size, buf);
        return result;
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
    return env->NewLongArray(1);
}
<|endoftext|>


<commit_before>#include "generator.h"

#include <iostream>
#include <vector>

void func(size_t start, size_t stop, size_t step)
{
	for (size_t i = start; i < stop; i += step)
		yield(i);
}

template<typename T>
gen_wrapper<T> range(T start, T stop, T step = 1)
{
	return make_generator<T>([=]
	{
		for (size_t i = start; i < stop; i += step)
			yield(i);
	}, 1024 * 1024);
}

int main(int argc, char** argv)
{
	auto gen = range<size_t>(0, 100, 1).gen;
	if (!gen->complete())
	{
		do
		{
			std::cout << (gen->value()) << '\n';
		} while (gen->next());
	}

	std::cout << std::endl;

}
<commit_msg>Made stack cause page fault in case of overflow<commit_after>#include "generator.h"

#include <iostream>
#include <vector>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

void* alloc_stack(size_t size)
{
	LPVOID mem = VirtualAlloc(nullptr, size + 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	VirtualAlloc((char*)mem + size, 4096, MEM_DECOMMIT, PAGE_NOACCESS);
	return mem;
}

void func(size_t start, size_t stop, size_t step)
{
	for (size_t i = start; i < stop; i += step)
		yield(i);
}

template<typename T>
gen_wrapper<T> range(T start, T stop, T step = 1)
{
	static constexpr size_t stack_size = 4096;
	return make_generator<T>([=]
	{
		for (size_t i = start; i < stop; i += step)
			yield(i);
	}, stack_size, alloc_stack(stack_size));
}

int main(int argc, char** argv)
{
	for (auto val : range<size_t>(0, 100))
	{
		std::cout << val << '\n';
	}

	std::cout << std::endl;

}
<|endoftext|>


<commit_before>// demo_list.cpp

#include "list.h"
#include <iostream>

using namespace std;

int main()
{
	List <int> list;
	cout << list.getSize() << endl;
	list.add(15);
	list.add(5616);
	list.add(516,1);
	cout << list.getSize() << endl;
	cout << list[0] << "    " << list[1] << "    " << list[2];
	return 0;
}<commit_msg>improved demo presentation, added build demo<commit_after>// demo_list.cpp

#include "list.h"
#include <iostream>

using namespace std;

int main()
{
	List <int> list;

	cout << "\n-- initial --\n";
	cout << "List size: " << list.getSize() << endl;

	list.add(15);
	list.add(13);
	list.add(516,1);
	cout << "\n-- adding three elements --\n";
	cout << "List: ";
	for(int i=0; i<=list.end(); i++)
	{
		cout << list.getData(i) << " ";
	}
	cout << endl;
	cout << "New list size: " << list.getSize() << endl;

	list.build(3);
	cout << "\n-- after using build --\n";
	cout << "List: ";
	for(int i=0; i<=list.end(); i++)
	{
		cout << list.getData(i) << " ";
	}
	cout << endl;
	cout << "New list size: " << list.getSize() << endl;

	return 0;
}
<|endoftext|>