<commit_before>/*
 * Copyright 2014-2020 Real Logic Limited.
 *
 * 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
 *
 * https://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 <cinttypes>
#include <array>
#include <cstdint>
#include <thread>
#include <exception>
#include <functional>

#include <gtest/gtest.h>

extern "C"
{
#include "aeronc.h"
#include "aeron_context.h"
#include "aeron_cnc_file_descriptor.h"
#include "concurrent/aeron_mpsc_rb.h"
#include "concurrent/aeron_broadcast_transmitter.h"
#include "concurrent/aeron_counters_manager.h"
#include "aeron_client_conductor.h"
#include "util/aeron_fileutil.h"
}

#define CAPACITY (1024)
#define TO_DRIVER_RING_BUFFER_LENGTH (CAPACITY + AERON_RB_TRAILER_LENGTH)
#define TO_CLIENTS_BUFFER_LENGTH (CAPACITY + AERON_BROADCAST_BUFFER_TRAILER_LENGTH)
#define COUNTER_VALUES_BUFFER_LENGTH (1024 * 1024)
#define COUNTER_METADATA_BUFFER_LENGTH (AERON_COUNTERS_METADATA_BUFFER_LENGTH(COUNTER_VALUES_BUFFER_LENGTH))
#define ERROR_BUFFER_LENGTH (CAPACITY)
#define FILE_PAGE_SIZE (4 * 1024)

#define CLIENT_LIVENESS_TIMEOUT (5 * 1000 * 1000 * 1000LL)

#define PUB_URI "aeron:udp?endpoint=localhost:24567"
#define STREAM_ID (101)
#define SESSION_ID (110)

class ClientConductorTest : public testing::Test
{
public:

    ClientConductorTest() :
        m_logFileName(tempFileName())
    {
        if (aeron_context_init(&m_context) < 0)
        {
            throw std::runtime_error("could not init context: " + std::string(aeron_errmsg()));
        }

        m_context->cnc_map.length = aeron_cnc_computed_length(
            TO_DRIVER_RING_BUFFER_LENGTH +
            TO_CLIENTS_BUFFER_LENGTH +
            COUNTER_VALUES_BUFFER_LENGTH +
            COUNTER_METADATA_BUFFER_LENGTH +
            ERROR_BUFFER_LENGTH,
            FILE_PAGE_SIZE);
        m_cnc = std::unique_ptr<uint8_t[]>(new uint8_t[m_context->cnc_map.length]);
        m_context->cnc_map.addr = m_cnc.get();
        memset(m_context->cnc_map.addr, 0, m_context->cnc_map.length);

        m_context->use_conductor_agent_invoker = true;

        aeron_cnc_metadata_t *metadata = (aeron_cnc_metadata_t *)m_context->cnc_map.addr;
        metadata->to_driver_buffer_length = (int32_t)TO_DRIVER_RING_BUFFER_LENGTH;
        metadata->to_clients_buffer_length = (int32_t)TO_CLIENTS_BUFFER_LENGTH;
        metadata->counter_metadata_buffer_length = (int32_t)COUNTER_METADATA_BUFFER_LENGTH;
        metadata->counter_values_buffer_length = (int32_t)COUNTER_VALUES_BUFFER_LENGTH;
        metadata->error_log_buffer_length = (int32_t)ERROR_BUFFER_LENGTH;
        metadata->client_liveness_timeout = (int64_t)CLIENT_LIVENESS_TIMEOUT;
        metadata->start_timestamp = m_context->epoch_clock();
        metadata->pid = 101;
        AERON_PUT_VOLATILE(metadata->cnc_version, AERON_CNC_VERSION);

        if (aeron_mpsc_rb_init(
            &m_to_driver, aeron_cnc_to_driver_buffer(metadata), TO_DRIVER_RING_BUFFER_LENGTH) < 0)
        {
            throw std::runtime_error("could not init to_driver: " + std::string(aeron_errmsg()));
        }

        if (aeron_broadcast_transmitter_init(
            &m_to_clients, aeron_cnc_to_clients_buffer(metadata), TO_CLIENTS_BUFFER_LENGTH) < 0)
        {
            throw std::runtime_error("could not init to_clients: " + std::string(aeron_errmsg()));
        }

        if (aeron_client_conductor_init(&m_conductor, m_context) < 0)
        {
            throw std::runtime_error("could not init conductor: " + std::string(aeron_errmsg()));
        }
    }

    virtual ~ClientConductorTest()
    {
        aeron_client_conductor_on_close(&m_conductor);
        m_context->cnc_map.addr = NULL;
        aeron_context_close(m_context);

        ::unlink(m_logFileName.c_str());
    }

    static std::string tempFileName()
    {
        char filename[AERON_MAX_PATH];

        aeron_temp_filename(filename, sizeof(filename));
        return std::string(filename);
    }

    static void createLogFile(std::string &filename)
    {
        aeron_mapped_file_t mappedFile = {
            NULL,
            AERON_LOGBUFFER_TERM_MIN_LENGTH * 3 + AERON_LOGBUFFER_META_DATA_LENGTH };

        if (aeron_map_new_file(&mappedFile, filename.c_str(), false) < 0)
        {
            throw std::runtime_error("could not create log file: " + std::string(aeron_errmsg()));
        }

        auto metadata = reinterpret_cast<aeron_logbuffer_metadata_t *>((uint8_t *)mappedFile.addr +
            (mappedFile.length - AERON_LOGBUFFER_META_DATA_LENGTH));

        metadata->term_length = AERON_LOGBUFFER_TERM_MIN_LENGTH;
        metadata->page_size = FILE_PAGE_SIZE;

        aeron_unmap(&mappedFile);
    }

    static void ToDriverHandler(int32_t type_id, const void *buffer, size_t length, void *clientd)
    {
        auto conductorTest = reinterpret_cast<ClientConductorTest *>(clientd);

        conductorTest->m_to_driver_handler(type_id, buffer, length);
    }

    size_t readToDriver(std::function<void(int32_t, const void *, size_t)>& handler)
    {
        m_to_driver_handler = handler;
        return aeron_mpsc_rb_read(&m_to_driver, ToDriverHandler, this, 1);
    }

    int doWork()
    {
        int work_count;

        if ((work_count = aeron_client_conductor_do_work(&m_conductor)) < 0)
        {
            throw std::runtime_error("error from do_work: " + std::string(aeron_errmsg()));
        }

        return work_count;
    }

    void transmitOnPublicationReady(aeron_async_add_publication_t *async, const std::string &logFile)
    {
        char response_buffer[sizeof(aeron_publication_buffers_ready_t) + AERON_MAX_PATH];
        auto response = reinterpret_cast<aeron_publication_buffers_ready_t *>(response_buffer);
        int32_t position_limit_counter_id = 10, channel_status_indicator_id = 11;

        response->correlation_id = async->registration_id;
        response->registration_id = async->registration_id;
        response->stream_id = async->stream_id;
        response->session_id = SESSION_ID;
        response->position_limit_counter_id = position_limit_counter_id;
        response->channel_status_indicator_id = channel_status_indicator_id;
        response->log_file_length = static_cast<int32_t>(logFile.length());
        memcpy(response_buffer + sizeof(aeron_publication_buffers_ready_t), logFile.c_str(), logFile.length());

        if (aeron_broadcast_transmitter_transmit(
            &m_to_clients,
            AERON_RESPONSE_ON_PUBLICATION_READY,
            response_buffer,
            sizeof(aeron_publication_buffers_ready_t) + logFile.length()) < 0)
        {
            throw std::runtime_error("error transmitting ON_PUBLICATION_READY: " + std::string(aeron_errmsg()));
        }
    }

    void transmitOnError(aeron_async_add_publication_t *async, int32_t errorCode, const std::string &errorMessage)
    {
        char response_buffer[sizeof(aeron_error_response_t) + AERON_MAX_PATH];
        auto response = reinterpret_cast<aeron_error_response_t *>(response_buffer);

        response->offending_command_correlation_id = async->registration_id;
        response->error_code = errorCode;
        response->error_message_length = static_cast<int32_t>(errorMessage.length());
        memcpy(response_buffer + sizeof(aeron_error_response_t), errorMessage.c_str(), errorMessage.length());

        if (aeron_broadcast_transmitter_transmit(
            &m_to_clients,
            AERON_RESPONSE_ON_ERROR,
            response_buffer,
            sizeof(aeron_error_response_t) + errorMessage.length()) < 0)
        {
            throw std::runtime_error("error transmitting ON_ERROR: " + std::string(aeron_errmsg()));
        }
    }

protected:
    aeron_context_t *m_context = NULL;
    aeron_client_conductor_t m_conductor;
    std::unique_ptr<uint8_t[]> m_cnc;
    aeron_mpsc_rb_t m_to_driver;
    aeron_broadcast_transmitter_t m_to_clients;
    std::string m_logFileName;

    std::function<void(int32_t, const void *, size_t)> m_to_driver_handler;
};

TEST_F(ClientConductorTest, shouldInitAndClose)
{
    // nothing to do
}

TEST_F(ClientConductorTest, shouldAddPublicationSuccessfully)
{
    aeron_async_add_publication_t *async = NULL;
    aeron_publication_t *publication = NULL;

    ASSERT_EQ(aeron_client_conductor_async_add_publication(&async, &m_conductor, PUB_URI, STREAM_ID), 0);
    doWork();

    // poll unsuccessfully
    ASSERT_EQ(aeron_async_add_publication_poll(&publication, async), 0) << aeron_errmsg();
    ASSERT_TRUE(NULL == publication);

    // send buffers ready
    transmitOnPublicationReady(async, m_logFileName);
    createLogFile(m_logFileName);
    doWork();

    // poll successfully
    ASSERT_GT(aeron_async_add_publication_poll(&publication, async), 0) << aeron_errmsg();
    ASSERT_TRUE(NULL != publication);

    // close
    ASSERT_EQ(aeron_publication_close(publication), 0);
    doWork();
}

TEST_F(ClientConductorTest, shouldErrorOnAddPublicationWithErrorFromDriver)
{
    aeron_async_add_publication_t *async = NULL;
    aeron_publication_t *publication = NULL;

    ASSERT_EQ(aeron_client_conductor_async_add_publication(&async, &m_conductor, PUB_URI, STREAM_ID), 0);
    doWork();

    // poll unsuccessfully
    ASSERT_EQ(aeron_async_add_publication_poll(&publication, async), 0) << aeron_errmsg();
    ASSERT_TRUE(NULL == publication);

    // error from driver.
    transmitOnError(async, AERON_ERROR_CODE_INVALID_CHANNEL, "invalid channel");
    doWork();

    ASSERT_EQ(aeron_async_add_publication_poll(&publication, async), -1);
}

// TODO: test timeout from driver
<commit_msg>[C]: add timeout test and setup clock for test fixture.<commit_after>/*
 * Copyright 2014-2020 Real Logic Limited.
 *
 * 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
 *
 * https://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 <cinttypes>
#include <array>
#include <cstdint>
#include <thread>
#include <exception>
#include <functional>

#include <gtest/gtest.h>

extern "C"
{
#include "aeronc.h"
#include "aeron_context.h"
#include "aeron_cnc_file_descriptor.h"
#include "concurrent/aeron_mpsc_rb.h"
#include "concurrent/aeron_broadcast_transmitter.h"
#include "concurrent/aeron_counters_manager.h"
#include "aeron_client_conductor.h"
#include "util/aeron_fileutil.h"
}

#define CAPACITY (1024)
#define TO_DRIVER_RING_BUFFER_LENGTH (CAPACITY + AERON_RB_TRAILER_LENGTH)
#define TO_CLIENTS_BUFFER_LENGTH (CAPACITY + AERON_BROADCAST_BUFFER_TRAILER_LENGTH)
#define COUNTER_VALUES_BUFFER_LENGTH (1024 * 1024)
#define COUNTER_METADATA_BUFFER_LENGTH (AERON_COUNTERS_METADATA_BUFFER_LENGTH(COUNTER_VALUES_BUFFER_LENGTH))
#define ERROR_BUFFER_LENGTH (CAPACITY)
#define FILE_PAGE_SIZE (4 * 1024)

#define CLIENT_LIVENESS_TIMEOUT (5 * 1000 * 1000 * 1000LL)

#define TIME_ADVANCE_INTERVAL_NS (1000 * 1000LL)

#define PUB_URI "aeron:udp?endpoint=localhost:24567"
#define STREAM_ID (101)
#define SESSION_ID (110)

static int64_t now_ms = 0;
static int64_t now_ns = 0;

static int64_t test_epoch_clock()
{
    return now_ms;
}

static int64_t test_nano_clock()
{
    return now_ns;
}

class ClientConductorTest : public testing::Test
{
public:

    ClientConductorTest() :
        m_logFileName(tempFileName())
    {
        now_ns = 0;
        now_ms = 0;

        if (aeron_context_init(&m_context) < 0)
        {
            throw std::runtime_error("could not init context: " + std::string(aeron_errmsg()));
        }

        m_context->cnc_map.length = aeron_cnc_computed_length(
            TO_DRIVER_RING_BUFFER_LENGTH +
            TO_CLIENTS_BUFFER_LENGTH +
            COUNTER_VALUES_BUFFER_LENGTH +
            COUNTER_METADATA_BUFFER_LENGTH +
            ERROR_BUFFER_LENGTH,
            FILE_PAGE_SIZE);
        m_cnc = std::unique_ptr<uint8_t[]>(new uint8_t[m_context->cnc_map.length]);
        m_context->cnc_map.addr = m_cnc.get();
        memset(m_context->cnc_map.addr, 0, m_context->cnc_map.length);

        m_context->epoch_clock = test_epoch_clock;
        m_context->nano_clock = test_nano_clock;
        m_context->use_conductor_agent_invoker = true;

        aeron_cnc_metadata_t *metadata = (aeron_cnc_metadata_t *)m_context->cnc_map.addr;
        metadata->to_driver_buffer_length = (int32_t)TO_DRIVER_RING_BUFFER_LENGTH;
        metadata->to_clients_buffer_length = (int32_t)TO_CLIENTS_BUFFER_LENGTH;
        metadata->counter_metadata_buffer_length = (int32_t)COUNTER_METADATA_BUFFER_LENGTH;
        metadata->counter_values_buffer_length = (int32_t)COUNTER_VALUES_BUFFER_LENGTH;
        metadata->error_log_buffer_length = (int32_t)ERROR_BUFFER_LENGTH;
        metadata->client_liveness_timeout = (int64_t)CLIENT_LIVENESS_TIMEOUT;
        metadata->start_timestamp = test_epoch_clock();
        metadata->pid = 101;
        AERON_PUT_VOLATILE(metadata->cnc_version, AERON_CNC_VERSION);

        if (aeron_mpsc_rb_init(
            &m_to_driver, aeron_cnc_to_driver_buffer(metadata), TO_DRIVER_RING_BUFFER_LENGTH) < 0)
        {
            throw std::runtime_error("could not init to_driver: " + std::string(aeron_errmsg()));
        }

        if (aeron_broadcast_transmitter_init(
            &m_to_clients, aeron_cnc_to_clients_buffer(metadata), TO_CLIENTS_BUFFER_LENGTH) < 0)
        {
            throw std::runtime_error("could not init to_clients: " + std::string(aeron_errmsg()));
        }

        if (aeron_client_conductor_init(&m_conductor, m_context) < 0)
        {
            throw std::runtime_error("could not init conductor: " + std::string(aeron_errmsg()));
        }
    }

    virtual ~ClientConductorTest()
    {
        aeron_client_conductor_on_close(&m_conductor);
        m_context->cnc_map.addr = NULL;
        aeron_context_close(m_context);

        ::unlink(m_logFileName.c_str());
    }

    static std::string tempFileName()
    {
        char filename[AERON_MAX_PATH];

        aeron_temp_filename(filename, sizeof(filename));
        return std::string(filename);
    }

    static void createLogFile(std::string &filename)
    {
        aeron_mapped_file_t mappedFile = {
            NULL,
            AERON_LOGBUFFER_TERM_MIN_LENGTH * 3 + AERON_LOGBUFFER_META_DATA_LENGTH };

        if (aeron_map_new_file(&mappedFile, filename.c_str(), false) < 0)
        {
            throw std::runtime_error("could not create log file: " + std::string(aeron_errmsg()));
        }

        auto metadata = reinterpret_cast<aeron_logbuffer_metadata_t *>((uint8_t *)mappedFile.addr +
            (mappedFile.length - AERON_LOGBUFFER_META_DATA_LENGTH));

        metadata->term_length = AERON_LOGBUFFER_TERM_MIN_LENGTH;
        metadata->page_size = FILE_PAGE_SIZE;

        aeron_unmap(&mappedFile);
    }

    static void ToDriverHandler(int32_t type_id, const void *buffer, size_t length, void *clientd)
    {
        auto conductorTest = reinterpret_cast<ClientConductorTest *>(clientd);

        conductorTest->m_to_driver_handler(type_id, buffer, length);
    }

    size_t readToDriver(std::function<void(int32_t, const void *, size_t)>& handler)
    {
        m_to_driver_handler = handler;
        return aeron_mpsc_rb_read(&m_to_driver, ToDriverHandler, this, 1);
    }

    int doWork(bool updateDriverHeartbeat = true)
    {
        int work_count;

        if (updateDriverHeartbeat)
        {
            aeron_mpsc_rb_consumer_heartbeat_time(&m_to_driver, test_epoch_clock());
        }

        if ((work_count = aeron_client_conductor_do_work(&m_conductor)) < 0)
        {
            throw std::runtime_error("error from do_work: " + std::string(aeron_errmsg()));
        }

        return work_count;
    }

    int doWorkForNs(
        int64_t interval_ns, bool updateDriverHeatbeat= true, int64_t advance_interval_ns = TIME_ADVANCE_INTERVAL_NS)
    {
        int work_count = 0;
        int64_t target_ns = now_ns + interval_ns;

        do
        {
            now_ns += advance_interval_ns;
            now_ms = now_ns / 1000000LL;
            work_count += doWork(updateDriverHeatbeat);
        }
        while (now_ns < target_ns);

        return work_count;
    }

    void transmitOnPublicationReady(aeron_async_add_publication_t *async, const std::string &logFile)
    {
        char response_buffer[sizeof(aeron_publication_buffers_ready_t) + AERON_MAX_PATH];
        auto response = reinterpret_cast<aeron_publication_buffers_ready_t *>(response_buffer);
        int32_t position_limit_counter_id = 10, channel_status_indicator_id = 11;

        response->correlation_id = async->registration_id;
        response->registration_id = async->registration_id;
        response->stream_id = async->stream_id;
        response->session_id = SESSION_ID;
        response->position_limit_counter_id = position_limit_counter_id;
        response->channel_status_indicator_id = channel_status_indicator_id;
        response->log_file_length = static_cast<int32_t>(logFile.length());
        memcpy(response_buffer + sizeof(aeron_publication_buffers_ready_t), logFile.c_str(), logFile.length());

        if (aeron_broadcast_transmitter_transmit(
            &m_to_clients,
            AERON_RESPONSE_ON_PUBLICATION_READY,
            response_buffer,
            sizeof(aeron_publication_buffers_ready_t) + logFile.length()) < 0)
        {
            throw std::runtime_error("error transmitting ON_PUBLICATION_READY: " + std::string(aeron_errmsg()));
        }
    }

    void transmitOnError(aeron_async_add_publication_t *async, int32_t errorCode, const std::string &errorMessage)
    {
        char response_buffer[sizeof(aeron_error_response_t) + AERON_MAX_PATH];
        auto response = reinterpret_cast<aeron_error_response_t *>(response_buffer);

        response->offending_command_correlation_id = async->registration_id;
        response->error_code = errorCode;
        response->error_message_length = static_cast<int32_t>(errorMessage.length());
        memcpy(response_buffer + sizeof(aeron_error_response_t), errorMessage.c_str(), errorMessage.length());

        if (aeron_broadcast_transmitter_transmit(
            &m_to_clients,
            AERON_RESPONSE_ON_ERROR,
            response_buffer,
            sizeof(aeron_error_response_t) + errorMessage.length()) < 0)
        {
            throw std::runtime_error("error transmitting ON_ERROR: " + std::string(aeron_errmsg()));
        }
    }

protected:
    aeron_context_t *m_context = NULL;
    aeron_client_conductor_t m_conductor;
    std::unique_ptr<uint8_t[]> m_cnc;
    aeron_mpsc_rb_t m_to_driver;
    aeron_broadcast_transmitter_t m_to_clients;
    std::string m_logFileName;

    std::function<void(int32_t, const void *, size_t)> m_to_driver_handler;
};

TEST_F(ClientConductorTest, shouldInitAndClose)
{
    // nothing to do
}

TEST_F(ClientConductorTest, shouldAddPublicationSuccessfully)
{
    aeron_async_add_publication_t *async = NULL;
    aeron_publication_t *publication = NULL;

    ASSERT_EQ(aeron_client_conductor_async_add_publication(&async, &m_conductor, PUB_URI, STREAM_ID), 0);
    doWork();

    // poll unsuccessfully
    ASSERT_EQ(aeron_async_add_publication_poll(&publication, async), 0) << aeron_errmsg();
    ASSERT_TRUE(NULL == publication);

    // send buffers ready
    transmitOnPublicationReady(async, m_logFileName);
    createLogFile(m_logFileName);
    doWork();

    // poll successfully
    ASSERT_GT(aeron_async_add_publication_poll(&publication, async), 0) << aeron_errmsg();
    ASSERT_TRUE(NULL != publication);

    // close
    ASSERT_EQ(aeron_publication_close(publication), 0);
    doWork();
}

TEST_F(ClientConductorTest, shouldErrorOnAddPublicationFromDriverError)
{
    aeron_async_add_publication_t *async = NULL;
    aeron_publication_t *publication = NULL;

    ASSERT_EQ(aeron_client_conductor_async_add_publication(&async, &m_conductor, PUB_URI, STREAM_ID), 0);
    doWork();

    // poll unsuccessfully
    ASSERT_EQ(aeron_async_add_publication_poll(&publication, async), 0) << aeron_errmsg();
    ASSERT_TRUE(NULL == publication);

    // error from driver.
    transmitOnError(async, AERON_ERROR_CODE_INVALID_CHANNEL, "invalid channel");
    doWork();

    ASSERT_EQ(aeron_async_add_publication_poll(&publication, async), -1);
}

TEST_F(ClientConductorTest, shouldErrorOnAddPublicationFromDriverTimeout)
{
    aeron_async_add_publication_t *async = NULL;
    aeron_publication_t *publication = NULL;

    ASSERT_EQ(aeron_client_conductor_async_add_publication(&async, &m_conductor, PUB_URI, STREAM_ID), 0);
    doWork();

    // poll unsuccessfully
    ASSERT_EQ(aeron_async_add_publication_poll(&publication, async), 0) << aeron_errmsg();
    ASSERT_TRUE(NULL == publication);

    doWorkForNs((m_context->driver_timeout_ms + 1000) * 1000000LL);

    ASSERT_EQ(aeron_async_add_publication_poll(&publication, async), -1);
}
<|endoftext|>


<commit_before>//
// Created by Sam on 9/25/2017.
//

#include "../../../include/Game/Python/Factory.h"
#include <iostream>

Card *Factory::createCard(std::string name)
{
    return nullptr;
}

Factory::Factory()
        : version(""), interpreter()
{
    std::cout << "Factory Started" << std::endl;
    std::cout << "Using Python: " << Py_GetVersion() << std::endl;

    updateVersion();
}

/* Once the interpreter is started, automatically detect and fill the version */
void Factory::updateVersion()
{
    pybind11::module platform  = pybind11::module::import("platform");
    auto python_version = platform.attr("python_version")();

    auto version_string = python_version.cast<std::__cxx11::string>();
    version = Version(version_string);
}

Factory::~Factory()
= default;
<commit_msg>Initalize the interpreter the same way it is initialized in the card unit test<commit_after>//
// Created by Sam on 9/25/2017.
//

#include "../../../include/Game/Python/Factory.h"
#include <iostream>

Card *Factory::createCard(std::string name)
{
    return nullptr;
}

Factory::Factory()
        : version(""), interpreter{}
{
    std::cout << "Factory Started" << std::endl;
    std::cout << "Using Python: " << Py_GetVersion() << std::endl;

    updateVersion();
}

/* Once the interpreter is started, automatically detect and fill the version */
void Factory::updateVersion()
{
    pybind11::module platform  = pybind11::module::import("platform");
    auto python_version = platform.attr("python_version")();

    auto version_string = python_version.cast<std::__cxx11::string>();
    version = Version(version_string);
}

Factory::~Factory()
= default;
<|endoftext|>


<commit_before>/*
 * File:   RbmLayer.cpp
 * Author: janvojt
 *
 * Created on November 11, 2015, 8:43 PM
 */

#include "RbmLayer.h"
#include "../../common.h"
#include "../LayerFactory.h"
#include "../../util/cudaHelpers.h"

#include "../../log/LoggerFactory.h"
#include "log4cpp/Category.hh"

RbmLayer::RbmLayer() {
}

RbmLayer::RbmLayer(const RbmLayer& orig) {
}

RbmLayer::~RbmLayer() {
}

void RbmLayer::setup(string confString) {

    processConfString(confString);

    outputsCount = conf.outputSize;

    inputSize = previousLayer->getOutputsCount();
    genuineWeightsCount = inputSize * outputsCount;

    if (conf.useBias) {
        weightsCount = genuineWeightsCount + inputSize + outputsCount;
    } else {
        weightsCount = genuineWeightsCount;
    }

    // arrays for storing sampled input and output
    checkCudaErrors(cudaMalloc(&sInputs, inputSize * sizeof(data_t)));
    checkCudaErrors(cudaMalloc(&sOutputs, outputsCount * sizeof(data_t)));

    // arrays for storing original potentials
    checkCudaErrors(cudaMalloc(&ovPotentials, inputSize * sizeof(data_t)));
    checkCudaErrors(cudaMalloc(&ohPotentials, outputsCount * sizeof(data_t)));

    // arrays for storing sampled potentials
    checkCudaErrors(cudaMalloc(&svPotentials, inputSize * sizeof(data_t)));
    checkCudaErrors(cudaMalloc(&shPotentials, outputsCount * sizeof(data_t)));

    int memCount = outputsCount > inputSize ? outputsCount : inputSize;
    checkCudaErrors(cudaMalloc(&randomData, memCount * sizeof(data_t)));

    // store for computing parallel array reduction
    checkCudaErrors(cudaMalloc(&tempReduce, outputsCount * sizeof(data_t)));
}

void RbmLayer::forwardCpu() {
    LOG()->error("Forward run on CPU is not yet implemented for RBM layer.");
}

void RbmLayer::forwardGpu() {
    propagateForwardGpu(previousLayer->getOutputs(), ohPotentials, outputs);
}

void RbmLayer::backwardCpu() {
    LOG()->error("Backward run on CPU is not yet implemented for RBM layer.");
}

void RbmLayer::backwardGpu() {
    propagateBackwardGpu(outputs, ovPotentials, sInputs);
}

void RbmLayer::propagateForwardCpu(data_t* visibles, data_t* potentials, data_t* hiddens) {
    LOG()->error("RBM layer does not implement CPU support in this version.");
}

void RbmLayer::propagateForwardGpu(data_t* visibles, data_t* potentials, data_t* hiddens) {

    data_t *hbias = weights + inputSize * outputsCount + inputSize;

    //note cuBLAS is column primary!
    //need to transpose the order
    k_gemm(this->cublasHandle,
            CblasTrans, CblasNoTrans,
            /*n*/outputsCount,/*m*/ 1,/*k*/ inputSize,
            (data_t) 1., weights,
            visibles, (data_t) 0., potentials);

    if (conf.useBias) {
        k_sumVectors(potentials, hbias, outputsCount);
    }

    k_computeSigmoid(potentials, hiddens, outputsCount);
}

void RbmLayer::propagateBackwardCpu(data_t* hiddens, data_t* potentials, data_t* visibles) {
    LOG()->error("RBM layer does not implement CPU support in this version.");
}

void RbmLayer::propagateBackwardGpu(data_t* hiddens, data_t* potentials, data_t* visibles) {

    data_t *vbias = weights + inputSize * outputsCount;

    //note cuBLAS is column primary!
    //need to transpose the order
    k_gemm(this->cublasHandle,
            CblasTrans, CblasNoTrans,
            /*n*/inputSize,/*m*/ 1,/*k*/ outputsCount,
            (data_t) 1., weights,
            hiddens, (data_t) 0., potentials);

    if (conf.useBias) {
        k_sumVectors(potentials, vbias, inputSize);
    }

    k_computeSigmoid(potentials, visibles, inputSize);
}

void RbmLayer::pretrainCpu() {
    LOG()->error("Pretraining RBM layer on CPU is not supported in this version. Please pretrain on GPU.");
}

void RbmLayer::pretrainGpu() {

    data_t *inputs =  previousLayer->getOutputs();

    // single forward run will compute original results
    // needed to compute the differentials
    forwardGpu();

    // Reset the parameters sampled from previous training
    if (!conf.isPersistent || !samplesInitialized) {
        int memSize = inputSize * sizeof(data_t);
        checkCudaErrors(cudaMemcpy(sInputs, inputs, memSize, cudaMemcpyDeviceToDevice));
        sample_vh_gpu();
    }

    // perform CD-k
    gibbs_hvh(conf.gibbsSteps);

    // COMPUTE THE DIFFERENTIALS

    // First we will compute the matrix for sampled data,
    // then for real data and subtract the sampled matrix.
    k_gemm(cublasHandle, CblasNoTrans, CblasNoTrans,
            outputsCount, inputSize, 1,
            lr, sOutputs, sInputs, (data_t) 0., weightDiffs);

    k_gemm(cublasHandle, CblasNoTrans, CblasNoTrans,
            outputsCount, inputSize, 1,
            lr, outputs, inputs, (data_t) -1., weightDiffs);

    if (conf.useBias) {

        data_t *vdiffs = weightDiffs + genuineWeightsCount;
        data_t *hdiffs = vdiffs + inputSize;

        // clear the bias diffs just before working with them
        checkCudaErrors(cudaMemset(vdiffs, 0, (inputSize + outputsCount) * sizeof(data_t)));

        // compute bias for visible neurons
        k_axpy(cublasHandle, inputSize, (data_t) lr, inputs, 1, vdiffs, 1);
        k_axpy(cublasHandle, inputSize, (data_t) -lr, sInputs, 1, vdiffs, 1);

        // compute bias for hidden neurons
        k_axpy(cublasHandle, outputsCount, (data_t) lr, outputs, 1, hdiffs, 1);
        k_axpy(cublasHandle, outputsCount, (data_t) -lr, sOutputs, 1, hdiffs, 1);
    }

    // adjust RBM parameters according to computed diffs
    k_sumVectors(weights, weightDiffs, weightsCount);
}

void RbmLayer::sample_vh_gpu() {

    propagateForwardGpu(sInputs, shPotentials, sOutputs);

    k_generateUniform(*curandGen, randomData, outputsCount);
    k_uniformToCoinFlip(sOutputs, randomData, outputsCount);
}

void RbmLayer::sample_hv_gpu() {

    propagateBackwardGpu(sOutputs, svPotentials, sInputs);

    k_generateUniform(*curandGen, randomData, inputSize);
    k_uniformToCoinFlip(sInputs, randomData, inputSize);
}

void RbmLayer::gibbs_hvh(int steps) {

    for (int i = 0; i<steps; i++) {
        sample_hv_gpu();
        sample_vh_gpu();
    }
}

void RbmLayer::gibbs_vhv(int steps) {

    for (int i = 0; i<steps; i++) {
        sample_vh_gpu();
        sample_hv_gpu();
    }
}

data_t RbmLayer::freeEnergy() {

    data_t *vbias = weights + inputSize * outputsCount;

    data_t vbiasTerm = 0;
    k_dotProduct(cublasHandle, inputSize, sInputs, 1, vbias, 1, &vbiasTerm);

    data_t hiddenTerm = k_logPlusExpReduce(1., shPotentials, tempReduce, outputsCount);

    return -hiddenTerm - vbiasTerm;
}

void RbmLayer::costUpdates() {

    data_t *inputs = previousLayer->getOutputs();

    // Reset the parameters sampled from previous training
    if (!conf.isPersistent || !samplesInitialized) {
        int memSize = inputSize * sizeof(data_t);
        checkCudaErrors(cudaMemcpy(sInputs, inputs, memSize, cudaMemcpyDeviceToDevice));
        sample_vh_gpu();
    } else {
        // TODO ???
    }

    data_t oEnergy = freeEnergy();

    gibbs_hvh(conf.gibbsSteps);

    data_t cost = oEnergy - freeEnergy();
    // TODO what to do with cost?
}

void RbmLayer::backwardLastCpu(data_t* expectedOutput) {
    LOG()->error("Backpropagation based on expected output is not implemented in RBM layer. This error happens when RBM layer is the last network layer.");
}

void RbmLayer::backwardLastGpu(data_t* expectedOutput) {
    LOG()->error("Backpropagation based on expected output is not implemented in RBM layer. This error happens when RBM layer is the last network layer.");
}

void RbmLayer::processConfString(string confString) {
    // dummy variable for delimiters
    char sep;
    istringstream iss (confString);

    if (!(iss >> conf.outputSize)) {
        LOG()->error("Could not read output size for RBM layer.");
    }

    iss >> sep;

//    if (!(iss >> boolalpha >> conf.isPersistent)) {
//        LOG()->warn("Could not read whether to use CD or PCD for RBM layer from configuration. Using CD...");
//        conf.isPersistent = false;
//    }
//
//    iss >> sep;

    if (!(iss >> conf.gibbsSteps)) {
        LOG()->error("Could not read number of Gibbs steps for RBM layer, using 1.");
        conf.gibbsSteps = 1;
    }

    iss >> sep;

    if (!(iss >> lr)) {
        LOG()->warn("Could not read learning rate for RBM layer from configuration. Using default of 0.3.");
        lr = .3;
    }

    iss >> sep;

    if (!(iss >> boolalpha >> conf.useBias)) {
        LOG()->warn("Could not read bias for RBM layer from configuration. Not using bias...");
        conf.useBias = false;
    }
}

RbmConfig RbmLayer::getConfig() {
    return conf;
}

bool RbmLayer::isPretrainable() {
    return true;
}

static LayerRegister<RbmLayer> reg("Rbm");
<commit_msg>Do not backpropagate RBM layers after pretraining.<commit_after>/*
 * File:   RbmLayer.cpp
 * Author: janvojt
 *
 * Created on November 11, 2015, 8:43 PM
 */

#include "RbmLayer.h"
#include "../../common.h"
#include "../LayerFactory.h"
#include "../../util/cudaHelpers.h"

#include "../../log/LoggerFactory.h"
#include "log4cpp/Category.hh"

RbmLayer::RbmLayer() {
}

RbmLayer::RbmLayer(const RbmLayer& orig) {
}

RbmLayer::~RbmLayer() {
}

void RbmLayer::setup(string confString) {

    processConfString(confString);

    outputsCount = conf.outputSize;

    inputSize = previousLayer->getOutputsCount();
    genuineWeightsCount = inputSize * outputsCount;

    if (conf.useBias) {
        weightsCount = genuineWeightsCount + inputSize + outputsCount;
    } else {
        weightsCount = genuineWeightsCount;
    }

    // arrays for storing sampled input and output
    checkCudaErrors(cudaMalloc(&sInputs, inputSize * sizeof(data_t)));
    checkCudaErrors(cudaMalloc(&sOutputs, outputsCount * sizeof(data_t)));

    // arrays for storing original potentials
    checkCudaErrors(cudaMalloc(&ovPotentials, inputSize * sizeof(data_t)));
    checkCudaErrors(cudaMalloc(&ohPotentials, outputsCount * sizeof(data_t)));

    // arrays for storing sampled potentials
    checkCudaErrors(cudaMalloc(&svPotentials, inputSize * sizeof(data_t)));
    checkCudaErrors(cudaMalloc(&shPotentials, outputsCount * sizeof(data_t)));

    int memCount = outputsCount > inputSize ? outputsCount : inputSize;
    checkCudaErrors(cudaMalloc(&randomData, memCount * sizeof(data_t)));

    // store for computing parallel array reduction
    checkCudaErrors(cudaMalloc(&tempReduce, outputsCount * sizeof(data_t)));
}

void RbmLayer::forwardCpu() {
    LOG()->error("Forward run on CPU is not yet implemented for RBM layer.");
}

void RbmLayer::forwardGpu() {
    propagateForwardGpu(previousLayer->getOutputs(), ohPotentials, outputs);
}

void RbmLayer::backwardCpu() {
    // DO NOTHING
    // There is no need to backpropagate, because the RBM layers are learning
    // only in the pretraining phase. See #pretrain().
}

void RbmLayer::backwardGpu() {
    // DO NOTHING
    // There is no need to backpropagate, because the RBM layers are learning
    // only in the pretraining phase. See #pretrain().
}

void RbmLayer::propagateForwardCpu(data_t* visibles, data_t* potentials, data_t* hiddens) {
    LOG()->error("RBM layer does not implement CPU support in this version.");
}

void RbmLayer::propagateForwardGpu(data_t* visibles, data_t* potentials, data_t* hiddens) {

    data_t *hbias = weights + inputSize * outputsCount + inputSize;

    //note cuBLAS is column primary!
    //need to transpose the order
    k_gemm(this->cublasHandle,
            CblasTrans, CblasNoTrans,
            /*n*/outputsCount,/*m*/ 1,/*k*/ inputSize,
            (data_t) 1., weights,
            visibles, (data_t) 0., potentials);

    if (conf.useBias) {
        k_sumVectors(potentials, hbias, outputsCount);
    }

    k_computeSigmoid(potentials, hiddens, outputsCount);
}

void RbmLayer::propagateBackwardCpu(data_t* hiddens, data_t* potentials, data_t* visibles) {
    LOG()->error("RBM layer does not implement CPU support in this version.");
}

void RbmLayer::propagateBackwardGpu(data_t* hiddens, data_t* potentials, data_t* visibles) {

    data_t *vbias = weights + inputSize * outputsCount;

    //note cuBLAS is column primary!
    //need to transpose the order
    k_gemm(this->cublasHandle,
            CblasTrans, CblasNoTrans,
            /*n*/inputSize,/*m*/ 1,/*k*/ outputsCount,
            (data_t) 1., weights,
            hiddens, (data_t) 0., potentials);

    if (conf.useBias) {
        k_sumVectors(potentials, vbias, inputSize);
    }

    k_computeSigmoid(potentials, visibles, inputSize);
}

void RbmLayer::pretrainCpu() {
    LOG()->error("Pretraining RBM layer on CPU is not supported in this version. Please pretrain on GPU.");
}

void RbmLayer::pretrainGpu() {

    data_t *inputs =  previousLayer->getOutputs();

    // single forward run will compute original results
    // needed to compute the differentials
    forwardGpu();

    // Reset the parameters sampled from previous training
    if (!conf.isPersistent || !samplesInitialized) {
        int memSize = inputSize * sizeof(data_t);
        checkCudaErrors(cudaMemcpy(sInputs, inputs, memSize, cudaMemcpyDeviceToDevice));
        sample_vh_gpu();
    }

    // perform CD-k
    gibbs_hvh(conf.gibbsSteps);

    // COMPUTE THE DIFFERENTIALS

    // First we will compute the matrix for sampled data,
    // then for real data and subtract the sampled matrix.
    k_gemm(cublasHandle, CblasNoTrans, CblasNoTrans,
            outputsCount, inputSize, 1,
            lr, sOutputs, sInputs, (data_t) 0., weightDiffs);

    k_gemm(cublasHandle, CblasNoTrans, CblasNoTrans,
            outputsCount, inputSize, 1,
            lr, outputs, inputs, (data_t) -1., weightDiffs);

    if (conf.useBias) {

        data_t *vdiffs = weightDiffs + genuineWeightsCount;
        data_t *hdiffs = vdiffs + inputSize;

        // clear the bias diffs just before working with them
        checkCudaErrors(cudaMemset(vdiffs, 0, (inputSize + outputsCount) * sizeof(data_t)));

        // compute bias for visible neurons
        k_axpy(cublasHandle, inputSize, (data_t) lr, inputs, 1, vdiffs, 1);
        k_axpy(cublasHandle, inputSize, (data_t) -lr, sInputs, 1, vdiffs, 1);

        // compute bias for hidden neurons
        k_axpy(cublasHandle, outputsCount, (data_t) lr, outputs, 1, hdiffs, 1);
        k_axpy(cublasHandle, outputsCount, (data_t) -lr, sOutputs, 1, hdiffs, 1);
    }

    // adjust RBM parameters according to computed diffs
    k_sumVectors(weights, weightDiffs, weightsCount);
}

void RbmLayer::sample_vh_gpu() {

    propagateForwardGpu(sInputs, shPotentials, sOutputs);

    k_generateUniform(*curandGen, randomData, outputsCount);
    k_uniformToCoinFlip(sOutputs, randomData, outputsCount);
}

void RbmLayer::sample_hv_gpu() {

    propagateBackwardGpu(sOutputs, svPotentials, sInputs);

    k_generateUniform(*curandGen, randomData, inputSize);
    k_uniformToCoinFlip(sInputs, randomData, inputSize);
}

void RbmLayer::gibbs_hvh(int steps) {

    for (int i = 0; i<steps; i++) {
        sample_hv_gpu();
        sample_vh_gpu();
    }
}

void RbmLayer::gibbs_vhv(int steps) {

    for (int i = 0; i<steps; i++) {
        sample_vh_gpu();
        sample_hv_gpu();
    }
}

data_t RbmLayer::freeEnergy() {

    data_t *vbias = weights + inputSize * outputsCount;

    data_t vbiasTerm = 0;
    k_dotProduct(cublasHandle, inputSize, sInputs, 1, vbias, 1, &vbiasTerm);

    data_t hiddenTerm = k_logPlusExpReduce(1., shPotentials, tempReduce, outputsCount);

    return -hiddenTerm - vbiasTerm;
}

void RbmLayer::costUpdates() {

    data_t *inputs = previousLayer->getOutputs();

    // Reset the parameters sampled from previous training
    if (!conf.isPersistent || !samplesInitialized) {
        int memSize = inputSize * sizeof(data_t);
        checkCudaErrors(cudaMemcpy(sInputs, inputs, memSize, cudaMemcpyDeviceToDevice));
        sample_vh_gpu();
    } else {
        // TODO ???
    }

    data_t oEnergy = freeEnergy();

    gibbs_hvh(conf.gibbsSteps);

    data_t cost = oEnergy - freeEnergy();
    // TODO what to do with cost?
}

void RbmLayer::backwardLastCpu(data_t* expectedOutput) {
    LOG()->error("Backpropagation based on expected output is not implemented in RBM layer. This error happens when RBM layer is the last network layer.");
}

void RbmLayer::backwardLastGpu(data_t* expectedOutput) {
    LOG()->error("Backpropagation based on expected output is not implemented in RBM layer. This error happens when RBM layer is the last network layer.");
}

void RbmLayer::processConfString(string confString) {
    // dummy variable for delimiters
    char sep;
    istringstream iss (confString);

    if (!(iss >> conf.outputSize)) {
        LOG()->error("Could not read output size for RBM layer.");
    }

    iss >> sep;

//    if (!(iss >> boolalpha >> conf.isPersistent)) {
//        LOG()->warn("Could not read whether to use CD or PCD for RBM layer from configuration. Using CD...");
//        conf.isPersistent = false;
//    }
//
//    iss >> sep;

    if (!(iss >> conf.gibbsSteps)) {
        LOG()->error("Could not read number of Gibbs steps for RBM layer, using 1.");
        conf.gibbsSteps = 1;
    }

    iss >> sep;

    if (!(iss >> lr)) {
        LOG()->warn("Could not read learning rate for RBM layer from configuration. Using default of 0.3.");
        lr = .3;
    }

    iss >> sep;

    if (!(iss >> boolalpha >> conf.useBias)) {
        LOG()->warn("Could not read bias for RBM layer from configuration. Not using bias...");
        conf.useBias = false;
    }
}

RbmConfig RbmLayer::getConfig() {
    return conf;
}

bool RbmLayer::isPretrainable() {
    return true;
}

static LayerRegister<RbmLayer> reg("Rbm");
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include <ICUBridge/ICUBridge.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/XalanDecimalFormatSymbols.hpp>

#include <PlatformSupport/DoubleSupport.hpp>

#include <unicode/coll.h>
#include <unicode/dcfmtsym.h>
#include <unicode/decimfmt.h>

#include <Include/XalanAutoPtr.hpp>

#if defined(XALAN_NO_NAMESPACES)
	typedef vector<UChar>					UCharVectorType;
#else
	typedef std::vector<UChar>				UCharVectorType;
#endif

#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)
inline void
doCopyData(
			const XalanDOMChar*		theString,
			unsigned int			theStringLength,
			XalanDOMChar*			theBuffer)
{
	// Copy the data, truncating each character...
	for (unsigned int i = 0; i < theStringLength; ++i)
	{
		// There should be no truncation, since XalanDOMChars
		// hold UTF-16 code points, but assert, just in case...
		assert(theString[i] == UChar(theString[i]));

		theBuffer[i] = theString[i];
	}

}
#endif

// Use a stack-based buffer up to this size.
const unsigned int	theStackBufferSize = 200u;

const UnicodeString
ICUBridge::XalanDOMCharStringToUnicodeString(const XalanDOMChar*	theString)
{
	if (theString == 0)
	{
		return UnicodeString();
	}
	else
	{
#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)

		const unsigned int	theLength = length(theString);

		if (theStackBufferSize > theLength)
		{
			XalanDOMChar	theBuffer[theStackBufferSize];

			doCopyData(theString, theLength, theBuffer);

#if U_SIZEOF_WCHAR_T==2
			return UnicodeString((wchar_t*)&theBuffer[0], theLength);
#else
			return UnicodeString(&theBuffer[0], theLength);
#endif
		}
		else
		{
			// Create a buffer to copy out the UnicodeString data...
			UCharVectorType		theBuffer;

			// Resize the buffer appropriately...
			theBuffer.resize(theLength);

#if U_SIZEOF_WCHAR_T==2
			doCopyData(theString, theLength, (XalanDOMChar*)&theBuffer[0]);
#else
			doCopyData(theString, theLength, &theBuffer[0]);
#endif

			assert(theLength == theBuffer.size());

			return UnicodeString(&theBuffer[0], theLength);
		}
#else
		return UnicodeString(theString, length(theString));
#endif
	}
}

const UnicodeString
ICUBridge::XalanDOMStringToUnicodeString(const XalanDOMString&	theString)
{
	// Just call up to the XalanDOMChar* version...
	return XalanDOMCharStringToUnicodeString(c_wstr(theString));
}

const XalanDOMString
ICUBridge::UnicodeStringToXalanDOMString(const UnicodeString&	theString)
{
	const int32_t	theLength = theString.length();

#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)

	// If XalanDOMChar is larger than the ICU's UChar, we have to more work...
	// Create a buffer...
	XalanDOMCharVectorType	theBuffer;

	// Reserve the appropriate amount of space...
	theBuffer.reserve(theLength);

	// Copy the data...
	for (int32_t i = 0; i < theLength; ++i)
	{
		theBuffer.push_back(theString[i]);
	}

	return XalanDOMString(&theBuffer[0], theBuffer.size());

#else

	if (theStackBufferSize > theLength)
	{
		UChar	theBuffer[theStackBufferSize];

		// Extract the data...
		theString.extract(0, theLength, theBuffer);

		return XalanDOMString(theBuffer, theLength);
	}
	else
	{
		// Create a buffer to copy out the UnicodeString data...
		UCharVectorType		theBuffer;

		// Resize the buffer appropriately...
		theBuffer.resize(theLength);

		// Extract the data...
		theString.extract(0, theLength, &theBuffer[0]);

		assert(theLength == int32_t(theBuffer.size()));

		return XalanDOMString(&theBuffer[0], theLength);
	}
#endif
}

void
ICUBridge::UnicodeStringToXalanDOMString(
			const UnicodeString&	theString,
			XalanDOMString&			theResult)
{
#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)

	// If XalanDOMChar is larger than the ICU's UChar, we have to more work.
	// Don't bother to provide the optimized version, just call to the
	// previous function.

	theResult = UnicodeStringToXalanDOMString(theString);

#else

	const int32_t	theLength = theString.length();

	if (theStackBufferSize > theLength)
	{
		UChar	theBuffer[theStackBufferSize];

		// Extract the data...
		theString.extract(0, theLength, theBuffer);

		theResult = XalanDOMString(theBuffer, theLength);
	}
	else
	{
#if defined(XALAN_NO_NAMESPACES)
		typedef vector<UChar>		UCharVectorType;
#else
		typedef std::vector<UChar>	UCharVectorType;
#endif

		// Create a buffer to copy out the UnicodeString data...
		UCharVectorType		theBuffer;

		// Resize the buffer appropriately...
		theBuffer.resize(theLength);

		// Extract the data...
		theString.extract(0, theLength, &theBuffer[0]);

		theResult = XalanDOMString(&theBuffer[0], theBuffer.size());
	}
#endif
}

static void
doFormatNumber(
			const XalanDOMString&				thePattern,
			double								theNumber,
			const XalanDecimalFormatSymbols&	theXalanDFS,
			UErrorCode&							theStatus,
			XalanDOMString&						theResult)
{
	if (theStatus == U_ZERO_ERROR ||
		theStatus == U_USING_DEFAULT_ERROR)
	{
		// Use a XalanAutoPtr, to keep this safe until we construct the DecimalFormat instance.
		XalanAutoPtr<DecimalFormatSymbols>	theDFS(new DecimalFormatSymbols(theStatus));

		// We got a XalanDecimalFormatSymbols, so set the
		// corresponding data in the ICU DecimalFormatSymbols.
		theDFS->setZeroDigit(theXalanDFS.getZeroDigit());
		theDFS->setGroupingSeparator(theXalanDFS.getGroupingSeparator());
		theDFS->setDecimalSeparator(theXalanDFS.getDecimalSeparator());
		theDFS->setPerMill(theXalanDFS.getPerMill());
		theDFS->setPercent(theXalanDFS.getPercent());
		theDFS->setDigit(theXalanDFS.getDigit());
		theDFS->setPatternSeparator(theXalanDFS.getPatternSeparator());

		theDFS->setInfinity(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getInfinity()));
		theDFS->setNaN(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getNaN()));
	//	theDFS->setPlusSign(theZeroDigitChar);
		theDFS->setMinusSign(theXalanDFS.getMinusSign());
	//	theDFS->setExponentialSymbol(theZeroDigitChar);
		theDFS->setCurrencySymbol(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getCurrencySymbol()));
		theDFS->setInternationalCurrencySymbol(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getInternationalCurrencySymbol()));
		theDFS->setMonetaryDecimalSeparator(theXalanDFS.getMonetaryDecimalSeparator());

		UnicodeString	theUnicodeResult;

		// Construct a DecimalFormat.  Note that we release the XalanAutoPtr, since the
		// DecimalFormat will adopt the DecimalFormatSymbols instance.
		DecimalFormat	theFormatter(ICUBridge::XalanDOMStringToUnicodeString(thePattern), theDFS.release(), theStatus);

		if (theStatus == U_ZERO_ERROR ||
			theStatus == U_USING_DEFAULT_ERROR)
		{
			// Do the format...
			theFormatter.format(theNumber, theUnicodeResult);

			ICUBridge::UnicodeStringToXalanDOMString(theUnicodeResult, theResult);

			theStatus = U_ZERO_ERROR;
		}
	}
}

unsigned long
ICUBridge::FormatNumber(
			const XalanDOMString&				thePattern,
			double								theNumber,
			const XalanDecimalFormatSymbols*	theXalanDFS,
			XalanDOMString&						theResult)
{
	UErrorCode	theStatus = U_ZERO_ERROR;

	if (theXalanDFS == 0)
	{
		XalanDecimalFormatSymbols	theDefaultSymbols;

		doFormatNumber(
				thePattern,
				theNumber,
				theDefaultSymbols,
				theStatus,
				theResult);
	}
	else
	{
		doFormatNumber(
				thePattern,
				theNumber,
				*theXalanDFS,
				theStatus,
				theResult);
	}

	return theStatus;
}

int
ICUBridge::collationCompare(
			const XalanDOMString&	theLHS,
			const XalanDOMString&	theRHS)
{
	// Just call to the XalanDOMChar* version...
	return collationCompare(c_wstr(theLHS), c_wstr(theRHS));
}

int
ICUBridge::collationCompare(
			const XalanDOMChar*		theLHS,
			const XalanDOMChar*		theRHS)
{
	UErrorCode				theStatus = U_ZERO_ERROR;

	// Create a collator, and keep it in an XalanAutoPtr...
	const XalanAutoPtr<Collator>	theCollator(Collator::createInstance(theStatus));

	if (theStatus == U_ZERO_ERROR || theStatus == U_USING_DEFAULT_ERROR)
	{
		// OK, do the compare...
		return theCollator->compare(
#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)
					XalanDOMCharStringToUnicodeString(theLHS),
					XalanDOMCharStringToUnicodeString(theRHS));
#else
					theLHS,
					length(theLHS),
					theRHS,
					length(theRHS));
#endif
	}
	else
	{
		// If creating the ICU Collator failed, fall back to the default...
		return collationCompare(theLHS, theRHS);
	}
}
<commit_msg>Fixed error detection.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include <ICUBridge/ICUBridge.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/XalanDecimalFormatSymbols.hpp>

#include <PlatformSupport/DoubleSupport.hpp>

#include <unicode/coll.h>
#include <unicode/dcfmtsym.h>
#include <unicode/decimfmt.h>

#include <Include/XalanAutoPtr.hpp>

#if defined(XALAN_NO_NAMESPACES)
	typedef vector<UChar>					UCharVectorType;
#else
	typedef std::vector<UChar>				UCharVectorType;
#endif

#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)
inline void
doCopyData(
			const XalanDOMChar*		theString,
			unsigned int			theStringLength,
			XalanDOMChar*			theBuffer)
{
	// Copy the data, truncating each character...
	for (unsigned int i = 0; i < theStringLength; ++i)
	{
		// There should be no truncation, since XalanDOMChars
		// hold UTF-16 code points, but assert, just in case...
		assert(theString[i] == UChar(theString[i]));

		theBuffer[i] = theString[i];
	}

}
#endif

// Use a stack-based buffer up to this size.
const unsigned int	theStackBufferSize = 200u;

const UnicodeString
ICUBridge::XalanDOMCharStringToUnicodeString(const XalanDOMChar*	theString)
{
	if (theString == 0)
	{
		return UnicodeString();
	}
	else
	{
#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)

		const unsigned int	theLength = length(theString);

		if (theStackBufferSize > theLength)
		{
			XalanDOMChar	theBuffer[theStackBufferSize];

			doCopyData(theString, theLength, theBuffer);

#if U_SIZEOF_WCHAR_T==2
			return UnicodeString((wchar_t*)&theBuffer[0], theLength);
#else
			return UnicodeString(&theBuffer[0], theLength);
#endif
		}
		else
		{
			// Create a buffer to copy out the UnicodeString data...
			UCharVectorType		theBuffer;

			// Resize the buffer appropriately...
			theBuffer.resize(theLength);

#if U_SIZEOF_WCHAR_T==2
			doCopyData(theString, theLength, (XalanDOMChar*)&theBuffer[0]);
#else
			doCopyData(theString, theLength, &theBuffer[0]);
#endif

			assert(theLength == theBuffer.size());

			return UnicodeString(&theBuffer[0], theLength);
		}
#else
		return UnicodeString(theString, length(theString));
#endif
	}
}

const UnicodeString
ICUBridge::XalanDOMStringToUnicodeString(const XalanDOMString&	theString)
{
	// Just call up to the XalanDOMChar* version...
	return XalanDOMCharStringToUnicodeString(c_wstr(theString));
}

const XalanDOMString
ICUBridge::UnicodeStringToXalanDOMString(const UnicodeString&	theString)
{
	const int32_t	theLength = theString.length();

#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)

	// If XalanDOMChar is larger than the ICU's UChar, we have to more work...
	// Create a buffer...
	XalanDOMCharVectorType	theBuffer;

	// Reserve the appropriate amount of space...
	theBuffer.reserve(theLength);

	// Copy the data...
	for (int32_t i = 0; i < theLength; ++i)
	{
		theBuffer.push_back(theString[i]);
	}

	return XalanDOMString(&theBuffer[0], theBuffer.size());

#else

	if (theStackBufferSize > theLength)
	{
		UChar	theBuffer[theStackBufferSize];

		// Extract the data...
		theString.extract(0, theLength, theBuffer);

		return XalanDOMString(theBuffer, theLength);
	}
	else
	{
		// Create a buffer to copy out the UnicodeString data...
		UCharVectorType		theBuffer;

		// Resize the buffer appropriately...
		theBuffer.resize(theLength);

		// Extract the data...
		theString.extract(0, theLength, &theBuffer[0]);

		assert(theLength == int32_t(theBuffer.size()));

		return XalanDOMString(&theBuffer[0], theLength);
	}
#endif
}

void
ICUBridge::UnicodeStringToXalanDOMString(
			const UnicodeString&	theString,
			XalanDOMString&			theResult)
{
#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)

	// If XalanDOMChar is larger than the ICU's UChar, we have to more work.
	// Don't bother to provide the optimized version, just call to the
	// previous function.

	theResult = UnicodeStringToXalanDOMString(theString);

#else

	const int32_t	theLength = theString.length();

	if (theStackBufferSize > theLength)
	{
		UChar	theBuffer[theStackBufferSize];

		// Extract the data...
		theString.extract(0, theLength, theBuffer);

		theResult = XalanDOMString(theBuffer, theLength);
	}
	else
	{
#if defined(XALAN_NO_NAMESPACES)
		typedef vector<UChar>		UCharVectorType;
#else
		typedef std::vector<UChar>	UCharVectorType;
#endif

		// Create a buffer to copy out the UnicodeString data...
		UCharVectorType		theBuffer;

		// Resize the buffer appropriately...
		theBuffer.resize(theLength);

		// Extract the data...
		theString.extract(0, theLength, &theBuffer[0]);

		theResult = XalanDOMString(&theBuffer[0], theBuffer.size());
	}
#endif
}

static void
doFormatNumber(
			const XalanDOMString&				thePattern,
			double								theNumber,
			const XalanDecimalFormatSymbols&	theXalanDFS,
			UErrorCode&							theStatus,
			XalanDOMString&						theResult)
{
	if (theStatus == U_ZERO_ERROR ||
		theStatus == U_USING_DEFAULT_ERROR)
	{
		// Use a XalanAutoPtr, to keep this safe until we construct the DecimalFormat instance.
		XalanAutoPtr<DecimalFormatSymbols>	theDFS(new DecimalFormatSymbols(theStatus));

		// We got a XalanDecimalFormatSymbols, so set the
		// corresponding data in the ICU DecimalFormatSymbols.
		theDFS->setZeroDigit(theXalanDFS.getZeroDigit());
		theDFS->setGroupingSeparator(theXalanDFS.getGroupingSeparator());
		theDFS->setDecimalSeparator(theXalanDFS.getDecimalSeparator());
		theDFS->setPerMill(theXalanDFS.getPerMill());
		theDFS->setPercent(theXalanDFS.getPercent());
		theDFS->setDigit(theXalanDFS.getDigit());
		theDFS->setPatternSeparator(theXalanDFS.getPatternSeparator());

		theDFS->setInfinity(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getInfinity()));
		theDFS->setNaN(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getNaN()));
	//	theDFS->setPlusSign(theZeroDigitChar);
		theDFS->setMinusSign(theXalanDFS.getMinusSign());
	//	theDFS->setExponentialSymbol(theZeroDigitChar);
		theDFS->setCurrencySymbol(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getCurrencySymbol()));
		theDFS->setInternationalCurrencySymbol(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getInternationalCurrencySymbol()));
		theDFS->setMonetaryDecimalSeparator(theXalanDFS.getMonetaryDecimalSeparator());

		UnicodeString	theUnicodeResult;

		// Construct a DecimalFormat.  Note that we release the XalanAutoPtr, since the
		// DecimalFormat will adopt the DecimalFormatSymbols instance.
		DecimalFormat	theFormatter(ICUBridge::XalanDOMStringToUnicodeString(thePattern), theDFS.release(), theStatus);

		if (theStatus == U_ZERO_ERROR ||
		    (theStatus >= U_ERROR_INFO_START && theStatus < U_ERROR_INFO_LIMIT))
		{
			// Do the format...
			theFormatter.format(theNumber, theUnicodeResult);

			ICUBridge::UnicodeStringToXalanDOMString(theUnicodeResult, theResult);

			theStatus = U_ZERO_ERROR;
		}
	}
}

unsigned long
ICUBridge::FormatNumber(
			const XalanDOMString&				thePattern,
			double								theNumber,
			const XalanDecimalFormatSymbols*	theXalanDFS,
			XalanDOMString&						theResult)
{
	UErrorCode	theStatus = U_ZERO_ERROR;

	if (theXalanDFS == 0)
	{
		XalanDecimalFormatSymbols	theDefaultSymbols;

		doFormatNumber(
				thePattern,
				theNumber,
				theDefaultSymbols,
				theStatus,
				theResult);
	}
	else
	{
		doFormatNumber(
				thePattern,
				theNumber,
				*theXalanDFS,
				theStatus,
				theResult);
	}

	return theStatus;
}

int
ICUBridge::collationCompare(
			const XalanDOMString&	theLHS,
			const XalanDOMString&	theRHS)
{
	// Just call to the XalanDOMChar* version...
	return collationCompare(c_wstr(theLHS), c_wstr(theRHS));
}

int
ICUBridge::collationCompare(
			const XalanDOMChar*		theLHS,
			const XalanDOMChar*		theRHS)
{
	UErrorCode				theStatus = U_ZERO_ERROR;

	// Create a collator, and keep it in an XalanAutoPtr...
	const XalanAutoPtr<Collator>	theCollator(Collator::createInstance(theStatus));

	if (theStatus == U_ZERO_ERROR || theStatus == U_USING_DEFAULT_ERROR)
	{
		// OK, do the compare...
		return theCollator->compare(
#if defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)
					XalanDOMCharStringToUnicodeString(theLHS),
					XalanDOMCharStringToUnicodeString(theRHS));
#else
					theLHS,
					length(theLHS),
					theRHS,
					length(theRHS));
#endif
	}
	else
	{
		// If creating the ICU Collator failed, fall back to the default...
		return collationCompare(theLHS, theRHS);
	}
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include <dispatch/dispatch.h>
#include <stdio.h>

#define DISPATCH_RUNTIME_STDLIB_INTERFACE __attribute__((__visibility__("default")))

#if USE_OBJC
@protocol OS_dispatch_source;
@protocol OS_dispatch_source_mach_send;
@protocol OS_dispatch_source_mach_recv;
@protocol OS_dispatch_source_memorypressure;
@protocol OS_dispatch_source_proc;
@protocol OS_dispatch_source_read;
@protocol OS_dispatch_source_signal;
@protocol OS_dispatch_source_timer;
@protocol OS_dispatch_source_data_add;
@protocol OS_dispatch_source_data_or;
@protocol OS_dispatch_source_vnode;
@protocol OS_dispatch_source_write;

// #include <dispatch/private.h>
__attribute__((constructor))
static void _dispatch_overlay_constructor() {
  Class source = objc_lookUpClass("OS_dispatch_source");
  if (source) {
    class_addProtocol(source, @protocol(OS_dispatch_source));
    class_addProtocol(source, @protocol(OS_dispatch_source_mach_send));
    class_addProtocol(source, @protocol(OS_dispatch_source_mach_recv));
    class_addProtocol(source, @protocol(OS_dispatch_source_memorypressure));
    class_addProtocol(source, @protocol(OS_dispatch_source_proc));
    class_addProtocol(source, @protocol(OS_dispatch_source_read));
    class_addProtocol(source, @protocol(OS_dispatch_source_signal));
    class_addProtocol(source, @protocol(OS_dispatch_source_timer));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_add));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_or));
    class_addProtocol(source, @protocol(OS_dispatch_source_vnode));
    class_addProtocol(source, @protocol(OS_dispatch_source_write));
  }
}

#endif /* USE_OBJC */

#if 0 /* FIXME -- adding directory to include path may need build-script plumbing to do properly... */
#include "swift/Runtime/Config.h"
#else
#define SWIFT_CC(x) /* FIXME!! */
#endif

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_queue_attr_t
_swift_dispatch_queue_concurrent(void) {
  return DISPATCH_QUEUE_CONCURRENT;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_apply_current(size_t iterations, __attribute__((__noescape__)) void (^block)(size_t)) {
  dispatch_apply(iterations, (dispatch_queue_t _Nonnull)0, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_queue_t
_swift_dispatch_get_main_queue(void) {
  return dispatch_get_main_queue();
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_data_t
_swift_dispatch_data_empty(void) {
  return dispatch_data_empty;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_data_destructor_default(void) {
  return DISPATCH_DATA_DESTRUCTOR_DEFAULT;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_data_destructor_free(void) {
  return _dispatch_data_destructor_free;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_data_destructor_munmap(void) {
  return _dispatch_data_destructor_munmap;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_block_create_with_qos_class(dispatch_block_flags_t flags, dispatch_qos_class_t qos, int relative_priority, dispatch_block_t block) {
  return dispatch_block_create_with_qos_class(flags, qos, relative_priority, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_block_create_noescape(dispatch_block_flags_t flags, dispatch_block_t block) {
  return dispatch_block_create(flags, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_block_cancel(dispatch_block_t block) {
  dispatch_block_cancel(block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" long
_swift_dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout) {
  return dispatch_block_wait(block, timeout);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue, dispatch_block_t notification_block) {
  dispatch_block_notify(block, queue, notification_block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" long
_swift_dispatch_block_testcancel(dispatch_block_t block) {
  return dispatch_block_testcancel(block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" bool
_swift_dispatch_data_apply(dispatch_data_t data, bool (^applier)(dispatch_data_t, size_t, const void *, size_t)) {
  return dispatch_data_apply(data, applier);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_async(dispatch_queue_t queue, dispatch_block_t block) {
  dispatch_async(queue, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block) {
  dispatch_group_async(group, queue, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_sync(dispatch_queue_t queue, dispatch_block_t block) {
  dispatch_sync(queue, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_release(dispatch_object_t obj) {
  dispatch_release(obj);
}

// DISPATCH_RUNTIME_STDLIB_INTERFACE
// extern "C" dispatch_queue_t
// _swift_apply_current_root_queue() {
// 	return DISPATCH_APPLY_CURRENT_ROOT_QUEUE;
// }

#define SOURCE(t)                                                              \
  SWIFT_CC(swift)                                                              \
  DISPATCH_RUNTIME_STDLIB_INTERFACE extern "C" dispatch_source_type_t  \
  _swift_dispatch_source_type_##t(void) {                                      \
    return DISPATCH_SOURCE_TYPE_##t;                                           \
  }

SOURCE(DATA_ADD)
SOURCE(DATA_OR)
#if HAVE_MACH
SOURCE(MACH_SEND)
SOURCE(MACH_RECV)
SOURCE(MEMORYPRESSURE)
#endif
#ifndef __linux__
SOURCE(PROC)
#endif
SOURCE(READ)
SOURCE(SIGNAL)
SOURCE(TIMER)
#ifndef __linux__
SOURCE(VNODE)
#endif
SOURCE(WRITE)

// See comment in CFFuntime.c explaining why objc_retainAutoreleasedReturnValue is needed.
extern "C" void swift_release(void *);
extern "C" void * objc_retainAutoreleasedReturnValue(void *obj) {
    if (obj) {
        swift_release(obj);
        return obj;
    }
    else return NULL;
}
<commit_msg>define SWIFT_CC(swift) macro for DispatchStubs<commit_after>//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include <dispatch/dispatch.h>
#include <stdio.h>

#define DISPATCH_RUNTIME_STDLIB_INTERFACE __attribute__((__visibility__("default")))

#if USE_OBJC
@protocol OS_dispatch_source;
@protocol OS_dispatch_source_mach_send;
@protocol OS_dispatch_source_mach_recv;
@protocol OS_dispatch_source_memorypressure;
@protocol OS_dispatch_source_proc;
@protocol OS_dispatch_source_read;
@protocol OS_dispatch_source_signal;
@protocol OS_dispatch_source_timer;
@protocol OS_dispatch_source_data_add;
@protocol OS_dispatch_source_data_or;
@protocol OS_dispatch_source_vnode;
@protocol OS_dispatch_source_write;

// #include <dispatch/private.h>
__attribute__((constructor))
static void _dispatch_overlay_constructor() {
  Class source = objc_lookUpClass("OS_dispatch_source");
  if (source) {
    class_addProtocol(source, @protocol(OS_dispatch_source));
    class_addProtocol(source, @protocol(OS_dispatch_source_mach_send));
    class_addProtocol(source, @protocol(OS_dispatch_source_mach_recv));
    class_addProtocol(source, @protocol(OS_dispatch_source_memorypressure));
    class_addProtocol(source, @protocol(OS_dispatch_source_proc));
    class_addProtocol(source, @protocol(OS_dispatch_source_read));
    class_addProtocol(source, @protocol(OS_dispatch_source_signal));
    class_addProtocol(source, @protocol(OS_dispatch_source_timer));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_add));
    class_addProtocol(source, @protocol(OS_dispatch_source_data_or));
    class_addProtocol(source, @protocol(OS_dispatch_source_vnode));
    class_addProtocol(source, @protocol(OS_dispatch_source_write));
  }
}

#endif /* USE_OBJC */

// Replicate the SWIFT_CC(swift) calling convention macro from
// swift/include/swift/Runtime/Config.h because it is
// quite awkward to include Config.h and its recursive includes
// in dispatch. This define must be manually kept in synch
#define SWIFT_CC(CC) SWIFT_CC_##CC
#if SWIFT_USE_SWIFTCALL
#define SWIFT_CC_swift __attribute__((swiftcall))
#else
#define SWIFT_CC_swift
#endif

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_queue_attr_t
_swift_dispatch_queue_concurrent(void) {
  return DISPATCH_QUEUE_CONCURRENT;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_apply_current(size_t iterations, __attribute__((__noescape__)) void (^block)(size_t)) {
  dispatch_apply(iterations, (dispatch_queue_t _Nonnull)0, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_queue_t
_swift_dispatch_get_main_queue(void) {
  return dispatch_get_main_queue();
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_data_t
_swift_dispatch_data_empty(void) {
  return dispatch_data_empty;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_data_destructor_default(void) {
  return DISPATCH_DATA_DESTRUCTOR_DEFAULT;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_data_destructor_free(void) {
  return _dispatch_data_destructor_free;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_data_destructor_munmap(void) {
  return _dispatch_data_destructor_munmap;
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_block_create_with_qos_class(dispatch_block_flags_t flags, dispatch_qos_class_t qos, int relative_priority, dispatch_block_t block) {
  return dispatch_block_create_with_qos_class(flags, qos, relative_priority, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" dispatch_block_t
_swift_dispatch_block_create_noescape(dispatch_block_flags_t flags, dispatch_block_t block) {
  return dispatch_block_create(flags, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_block_cancel(dispatch_block_t block) {
  dispatch_block_cancel(block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" long
_swift_dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout) {
  return dispatch_block_wait(block, timeout);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue, dispatch_block_t notification_block) {
  dispatch_block_notify(block, queue, notification_block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" long
_swift_dispatch_block_testcancel(dispatch_block_t block) {
  return dispatch_block_testcancel(block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" bool
_swift_dispatch_data_apply(dispatch_data_t data, bool (^applier)(dispatch_data_t, size_t, const void *, size_t)) {
  return dispatch_data_apply(data, applier);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_async(dispatch_queue_t queue, dispatch_block_t block) {
  dispatch_async(queue, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block) {
  dispatch_group_async(group, queue, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_sync(dispatch_queue_t queue, dispatch_block_t block) {
  dispatch_sync(queue, block);
}

SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE
extern "C" void
_swift_dispatch_release(dispatch_object_t obj) {
  dispatch_release(obj);
}

// DISPATCH_RUNTIME_STDLIB_INTERFACE
// extern "C" dispatch_queue_t
// _swift_apply_current_root_queue() {
// 	return DISPATCH_APPLY_CURRENT_ROOT_QUEUE;
// }

#define SOURCE(t)                                                              \
  SWIFT_CC(swift)                                                              \
  DISPATCH_RUNTIME_STDLIB_INTERFACE extern "C" dispatch_source_type_t  \
  _swift_dispatch_source_type_##t(void) {                                      \
    return DISPATCH_SOURCE_TYPE_##t;                                           \
  }

SOURCE(DATA_ADD)
SOURCE(DATA_OR)
#if HAVE_MACH
SOURCE(MACH_SEND)
SOURCE(MACH_RECV)
SOURCE(MEMORYPRESSURE)
#endif
#ifndef __linux__
SOURCE(PROC)
#endif
SOURCE(READ)
SOURCE(SIGNAL)
SOURCE(TIMER)
#ifndef __linux__
SOURCE(VNODE)
#endif
SOURCE(WRITE)

// See comment in CFFuntime.c explaining why objc_retainAutoreleasedReturnValue is needed.
extern "C" void swift_release(void *);
extern "C" void * objc_retainAutoreleasedReturnValue(void *obj) {
    if (obj) {
        swift_release(obj);
        return obj;
    }
    else return NULL;
}
<|endoftext|>


<commit_before>/*
 * Author: Csaszar, Peter <csjpeter@gmail.com>
 * Copyright (C) 2011-2016 Csaszar, Peter
 */

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "csjp_daemon.h"

//for more tricks: http://www.enderunix.org/docs/eng/daemon.php

namespace csjp {

String defaultDaemonLockFileName()
{
	String lockFileName;
	lockFileName.catf("/var/run/%.pid", getBinaryName());
	return lockFileName;
}

String defaultDaemonLogDirName()
{
	String logDirName;
	logDirName.catf("/var/log/");
	return logDirName;
}

Daemon::Daemon(bool exitParent) :
	lockFile(defaultDaemonLockFileName()),
	logDirName(defaultDaemonLogDirName()),
	pid(0)
{
	daemonize(exitParent);
}

Daemon::Daemon(const String & lockFileName, const String & logDirName, bool exitParent) :
	lockFile(lockFileName),
	logDirName(logDirName),
	pid(0)
{
	daemonize(exitParent);
}

void Daemon::daemonize(bool exitParent)
{
	LOG("Daemonizing: uid: %, euid: %, gid: %, egid: %",
			getuid(), geteuid(), getgid(), getegid());

	pid = fork();
	if(pid < 0)
		throw SystemError("Fork to daemonize failed. Error: %", csjp::ErrNo());
	if(0 < pid){
		if(exitParent)
			exit(EXIT_SUCCESS);
		else
			throw DaemonParent();
	}
	pid = getpid();

	/* Close standard file descriptors, we dont wnat to trash into them */
	// FIXME error handling?
	close(STDIN_FILENO); stdin = NULL;
	close(STDOUT_FILENO); stdout = NULL;
	close(STDERR_FILENO); stderr = NULL;

	// reopen on 0,1,2 file descriptors to avoid third party code caused crash
	int stdIn = open("/dev/null", O_RDWR); (void)stdIn;
	int stdOut = open("/dev/null", O_RDWR); (void)stdOut;
	int stdErr = open("/dev/null", O_RDWR); (void)stdErr;

	umask(S_IRWXO | S_IRWXG); // Only owner shall have acces to daemon created files, etc

	setLogDir(logDirName); // We want to log into the daemon's own log file

	LOG("Daemon process forked"); // First note into own log file to give life sign

	String pidString;
	pidString << pid;
	lockFile.write(pidString);
	lockFile.rewind();
	lockFile.lock();

	LOG("Pid file is ready"); // Administrator can use the pid file from now on

	if((chdir("/")) < 0)
		throw SystemError("Failed to make root the current directory.");

	pid_t sid = setsid();
	if(sid < 0)
		throw SystemError("Failed to make the forked daemon process the group leader.");

	LOG("Daemonization is ready");
}

Daemon::~Daemon()
{
	lockFile.unlock();
	lockFile.unlink();
}

}

<commit_msg>lockf() is not usable for now<commit_after>/*
 * Author: Csaszar, Peter <csjpeter@gmail.com>
 * Copyright (C) 2011-2016 Csaszar, Peter
 */

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "csjp_daemon.h"

//for more tricks: http://www.enderunix.org/docs/eng/daemon.php

namespace csjp {

String defaultDaemonLockFileName()
{
	String lockFileName;
	lockFileName.catf("/var/run/%.pid", getBinaryName());
	return lockFileName;
}

String defaultDaemonLogDirName()
{
	String logDirName;
	logDirName.catf("/var/log/");
	return logDirName;
}

Daemon::Daemon(bool exitParent) :
	lockFile(defaultDaemonLockFileName()),
	logDirName(defaultDaemonLogDirName()),
	pid(0)
{
	daemonize(exitParent);
}

Daemon::Daemon(const String & lockFileName, const String & logDirName, bool exitParent) :
	lockFile(lockFileName),
	logDirName(logDirName),
	pid(0)
{
	daemonize(exitParent);
}

void Daemon::daemonize(bool exitParent)
{
	LOG("Daemonizing: uid: %, euid: %, gid: %, egid: %",
			getuid(), geteuid(), getgid(), getegid());

	pid = fork();
	if(pid < 0)
		throw SystemError("Fork to daemonize failed. Error: %", csjp::ErrNo());
	if(0 < pid){
		if(exitParent)
			exit(EXIT_SUCCESS);
		else
			throw DaemonParent();
	}
	pid = getpid();

	/* Close standard file descriptors, we dont wnat to trash into them */
	// FIXME error handling?
	close(STDIN_FILENO); stdin = NULL;
	close(STDOUT_FILENO); stdout = NULL;
	close(STDERR_FILENO); stderr = NULL;

	// reopen on 0,1,2 file descriptors to avoid third party code caused crash
	int stdIn = open("/dev/null", O_RDWR); (void)stdIn;
	int stdOut = open("/dev/null", O_RDWR); (void)stdOut;
	int stdErr = open("/dev/null", O_RDWR); (void)stdErr;

	umask(S_IRWXO | S_IRWXG); // Only owner shall have acces to daemon created files, etc

	setLogDir(logDirName); // We want to log into the daemon's own log file

	LOG("Daemon process forked"); // First note into own log file to give life sign

	String pidString;
	pidString << pid;
	lockFile.write(pidString);
	lockFile.rewind();
	//lockFile.lock();

	LOG("Pid file is ready"); // Administrator can use the pid file from now on

	if((chdir("/")) < 0)
		throw SystemError("Failed to make root the current directory.");

	pid_t sid = setsid();
	if(sid < 0)
		throw SystemError("Failed to make the forked daemon process the group leader.");

	LOG("Daemonization is ready");
}

Daemon::~Daemon()
{
	//lockFile.unlock();
	lockFile.unlink();
}

}

<|endoftext|>


<commit_before># pragma once
#include <Siv3D.hpp>

namespace asc
{
	using namespace s3d;

	class TCPStringClient : public TCPClient
	{
	private:

		std::string m_buffer;

	public:

		bool readChar(wchar& to)
		{
			String buffer = FromUTF8(m_buffer);

			if (buffer.length > 0)
			{
				to = buffer[0];
				m_buffer = ToUTF8(buffer.substr(1));
				return true;
			}

			char character;

			if(!read(character))
				return false;

			m_buffer.push_back(character);
			buffer = FromUTF8(m_buffer);

			if (buffer.length > 0)
			{
				to = buffer[0];
				m_buffer = ToUTF8(buffer.substr(1));
				return true;
			}

			return false;
		}

		bool readLine(String& to)
		{
			for (;;)
			{
				char character;

				if (!read(character))
					return false;

				if (character == '\n')
					break;

				m_buffer.push_back(character);
			}

			to = FromUTF8(m_buffer);
			return true;
		}
	};
}<commit_msg>Implement readString.<commit_after># pragma once
#include <Siv3D.hpp>

namespace asc
{
	using namespace s3d;

	class TCPStringClient : public TCPClient
	{
	private:

		std::string m_buffer;

	public:

		bool readChar(wchar& to)
		{
			String buffer = FromUTF8(m_buffer);

			if (buffer.length > 0)
			{
				to = buffer[0];
				m_buffer = ToUTF8(buffer.substr(1));
				return true;
			}

			char character;

			if(!read(character))
				return false;

			m_buffer.push_back(character);
			buffer = FromUTF8(m_buffer);

			if (buffer.length > 0)
			{
				to = buffer[0];
				m_buffer = ToUTF8(buffer.substr(1));
				return true;
			}

			return false;
		}

		bool readString(size_t length, String& to)
		{
			String buffer = FromUTF8(m_buffer);

			if (buffer.length >= length)
			{
				to = buffer.substr(0, length);
				m_buffer = ToUTF8(buffer.substr(length));
				return true;
			}

			for(;;)
			{
				char character;

				if (!read(character))
					return false;

				m_buffer.push_back(character);
				buffer = FromUTF8(m_buffer);

				if (buffer.length >= length)
				{
					to = buffer.substr(0, length);
					m_buffer = ToUTF8(buffer.substr(length));
					return true;
				}
			}

			return false;
		}

		bool readLine(String& to)
		{
			for (;;)
			{
				char character;

				if (!read(character))
					return false;

				if (character == '\n')
					break;

				m_buffer.push_back(character);
			}

			to = FromUTF8(m_buffer);
			return true;
		}
	};
}<|endoftext|>