<commit_before>
#include "tcam_c.h"

#include "tcam.h"
#include "Error.h"

using namespace tcam;

/* error / debug */

int tcam_last_errno ()
{
    return getError().getErrno();
}

const char* tcam_last_error_messsage ()
{
    return getError().getString().c_str();
}

/* device discovery / watchdog */

tcam_device_index* tcam_create_device_index ()
{
    return (tcam_device_index*)new DeviceIndex();
}

void tcam_destroy_device_index (tcam_device_index* index)
{
    delete reinterpret_cast<DeviceIndex*>(index);
}

int tcam_device_index_get_device_count (tcam_device_index* index)
{
    return reinterpret_cast<DeviceIndex*>(index)->getDeviceList().size();
}

int tcam_device_index_get_device_infos (tcam_device_index* index,
                                        tcam_device_info* arr,
                                        size_t size)
{
    auto vec = reinterpret_cast<DeviceIndex*>(index)->getDeviceList();

    if (vec.size() < size)
    {
        setError(Error("Array is to small to contain all devices", EFAULT));
        return -1;
    }

    int i = 0;
    for (const auto& v : vec)
    {
        arr[i] = v.getInfo();
        i++;
    }

    return vec.size();
}

/* image source */

tcam_capture_device* tcam_create_new_capture_device (const tcam_device_info* info)
{
    return (tcam_capture_device*) new CaptureDevice(DeviceInfo(*info));
}

void tcam_destroy_capture_device (tcam_capture_device* source)
{
    delete reinterpret_cast<CaptureDevice*>(source);
}

/* device related */

bool tcam_capture_device_is_device_open (tcam_capture_device* source)
{
    return reinterpret_cast<CaptureDevice*>(source)->isDeviceOpen();
}

/* property related*/

int tcam_capture_device_get_property_count (const tcam_capture_device* source)
{
    return reinterpret_cast<const CaptureDevice*>(source)->getAvailableProperties().size();
}

int tcam_capture_device_get_properties (const tcam_capture_device* source,
                                        const tcam_camera_property* properties)
{}

bool tcam_capture_device_set_property (tcam_capture_device* source,
                                       const tcam_camera_property* property)
{
    auto vec = reinterpret_cast<CaptureDevice*>(source)->getAvailableProperties();

    for (auto& v :vec)
    {
        if (v.getID() == property->id)
        {
            //return v.set
        }
    }
    setError(Error("No such property found", ENOENT));
    return false;
}

/* video format related */

int tcam_capture_device_get_image_format_description_count (const tcam_capture_device* source)
{
    if (source == nullptr)
    {
        return -1;
    }

    return reinterpret_cast<const CaptureDevice*>(source)->getAvailableVideoFormats().size();
}

int tcam_capture_device_get_image_format_description (const tcam_capture_device* source,
                                                      tcam_video_format_description* arr,
                                                      const size_t size)
{

    auto vec = reinterpret_cast<const CaptureDevice*>(source)->getAvailableVideoFormats();

    if (vec.size() > size)
    {
        return -1;
    }

    int i = 0;
    for (const auto& v : vec)
    {
        arr[i] = v.getStruct();
        i++;
    }

    return vec.size();
}

bool tcam_capture_device_set_image_format (tcam_capture_device* source,
                                           const tcam_video_format* format)
{
    VideoFormat f (*format);

    return reinterpret_cast<CaptureDevice*>(source)->setVideoFormat(f);
}

bool tcam_capture_device_get_image_format (tcam_capture_device* source,
                                           tcam_video_format* format)
{
    VideoFormat f = reinterpret_cast<CaptureDevice*>(source)->getActiveVideoFormat();

    *format = f.getStruct();

    return true;
}

/* streaming functions */

bool tcam_capture_device_start_stream (tcam_capture_device* source,
                                       tcam_image_callback callback,
                                       void* user_data)
{

}

bool tcam_capture_device_stop_stream (tcam_capture_device* source)
{
    return reinterpret_cast<CaptureDevice*>(source)->stopStream();
}
<commit_msg>Corrected spelling error in function definitions<commit_after>
#include "tcam_c.h"

#include "tcam.h"
#include "Error.h"

using namespace tcam;

/* error / debug */

int tcam_last_errno ()
{
    return getError().getErrno();
}

const char* tcam_last_error_messsage ()
{
    return getError().getString().c_str();
}

/* device discovery / watchdog */

tcam_device_index* tcam_create_device_index ()
{
    return (tcam_device_index*)new DeviceIndex();
}

void tcam_destroy_device_index (tcam_device_index* index)
{
    delete reinterpret_cast<DeviceIndex*>(index);
}

int tcam_device_index_get_device_count (tcam_device_index* index)
{
    return reinterpret_cast<DeviceIndex*>(index)->getDeviceList().size();
}

int tcam_device_index_get_device_infos (tcam_device_index* index,
                                        tcam_device_info* arr,
                                        size_t size)
{
    auto vec = reinterpret_cast<DeviceIndex*>(index)->getDeviceList();

    if (vec.size() < size)
    {
        setError(Error("Array is to small to contain all devices", EFAULT));
        return -1;
    }

    int i = 0;
    for (const auto& v : vec)
    {
        arr[i] = v.getInfo();
        i++;
    }

    return vec.size();
}

/* image source */

tcam_capture_device* tcam_create_new_capture_device (const tcam_device_info* info)
{
    return (tcam_capture_device*) new CaptureDevice(DeviceInfo(*info));
}

void tcam_destroy_capture_device (tcam_capture_device* source)
{
    delete reinterpret_cast<CaptureDevice*>(source);
}

/* device related */

bool tcam_capture_device_is_device_open (tcam_capture_device* source)
{
    return reinterpret_cast<CaptureDevice*>(source)->isDeviceOpen();
}

/* property related*/

int tcam_capture_device_get_property_count (const tcam_capture_device* source)
{
    return reinterpret_cast<const CaptureDevice*>(source)->getAvailableProperties().size();
}

int tcam_capture_device_get_properties (const tcam_capture_device* source,
                                        const tcam_camera_property* properties)
{}

bool tcam_capture_device_set_property (tcam_capture_device* source,
                                       const tcam_camera_property* property)
{
    auto vec = reinterpret_cast<CaptureDevice*>(source)->getAvailableProperties();

    for (auto& v :vec)
    {
        if (v.getID() == property->id)
        {
            //return v.set
        }
    }
    setError(Error("No such property found", ENOENT));
    return false;
}

/* video format related */

int tcam_capture_device_get_image_format_descriptions_count (const tcam_capture_device* source)
{
    if (source == nullptr)
    {
        return -1;
    }

    return reinterpret_cast<const CaptureDevice*>(source)->getAvailableVideoFormats().size();
}

int tcam_capture_device_get_image_format_descriptions (const tcam_capture_device* source,
                                                      tcam_video_format_description* arr,
                                                      const size_t size)
{

    auto vec = reinterpret_cast<const CaptureDevice*>(source)->getAvailableVideoFormats();

    if (vec.size() > size)
    {
        return -1;
    }

    int i = 0;
    for (const auto& v : vec)
    {
        arr[i] = v.getStruct();
        i++;
    }

    return vec.size();
}

bool tcam_capture_device_set_image_format (tcam_capture_device* source,
                                           const tcam_video_format* format)
{
    VideoFormat f (*format);

    return reinterpret_cast<CaptureDevice*>(source)->setVideoFormat(f);
}

bool tcam_capture_device_get_image_format (tcam_capture_device* source,
                                           tcam_video_format* format)
{
    VideoFormat f = reinterpret_cast<CaptureDevice*>(source)->getActiveVideoFormat();

    *format = f.getStruct();

    return true;
}

/* streaming functions */

bool tcam_capture_device_start_stream (tcam_capture_device* source,
                                       tcam_image_callback callback,
                                       void* user_data)
{

}

bool tcam_capture_device_stop_stream (tcam_capture_device* source)
{
    return reinterpret_cast<CaptureDevice*>(source)->stopStream();
}
<|endoftext|>


<commit_before>#include "Buffer.h"
#include "Debug.h"
#include "Error.h"
#include "JITModule.h"
#include "runtime/HalideRuntime.h"
#include "Target.h"
#include "Var.h"
#include "IREquality.h"
#include "IROperator.h"

namespace Halide {
namespace Internal {

struct BufferContents {
    Image<> image;
    std::string name;
    mutable RefCount ref_count;
};

template<>
EXPORT RefCount &ref_count<BufferContents>(const BufferContents *p) {
    return p->ref_count;
}

template<>
EXPORT void destroy<BufferContents>(const BufferContents *p) {
    delete p;
}

namespace {
std::string make_buffer_name(const std::string &n, BufferPtr *b) {
    if (n.empty()) {
        return Internal::make_entity_name(b, "Halide::Internal::BufferPtr", 'b');
    } else {
        return n;
    }
}
}

BufferPtr::BufferPtr(const Image<> &buf, std::string name) :
    contents(new Internal::BufferContents {Image<>(buf), make_buffer_name(name, this)}) {}

BufferPtr::BufferPtr(Type t, const buffer_t &buf, std::string name) :
    contents(new Internal::BufferContents {Image<>(t, buf), make_buffer_name(name, this)}) {}

BufferPtr::BufferPtr(Type t, const std::vector<int> &size, std::string name) :
    contents(new Internal::BufferContents {Image<>(t, size), make_buffer_name(name, this)}) {}

bool BufferPtr::same_as(const BufferPtr &other) const {
    return contents.same_as(other.contents);
}

Image<> &BufferPtr::get() {
    return contents->image;
}

const Image<> &BufferPtr::get() const {
    return contents->image;
}

bool BufferPtr::defined() const {
    return contents->image;
}

const std::string &BufferPtr::name() const {
    return contents->name;
}

BufferPtr::operator Argument() const {
    return Argument(name(), Argument::InputBuffer, type(), dimensions());
}

Type BufferPtr::type() const {
    return contents->image.type();
}

int BufferPtr::dimensions() const {
    return contents->image.dimensions();
}

Image<>::Dimension BufferPtr::dim(int i) const {
    return contents->image.dim(i);
}

int BufferPtr::min(int i) const {
    return dim(i).min();
}

int BufferPtr::extent(int i) const {
    return dim(i).extent();
}

int BufferPtr::stride(int i) const {
    return dim(i).stride();
}

buffer_t *BufferPtr::raw_buffer() const {
    return contents->image.raw_buffer();
}

size_t BufferPtr::size_in_bytes() const {
    return contents->image.size_in_bytes();
}

uint8_t *BufferPtr::host_ptr() const {
    return raw_buffer()->host;
}

Expr BufferPtr::operator()(const std::vector<Expr> &args) const {
    // Cast the inputs to int32
    std::vector<Expr> int_args;
    for (Expr e : args) {
        user_assert(Int(32).can_represent(e.type()))
            << "Args to a call to an Image must be representable as 32-bit integers.\n";
        if (equal(e, _)) {
            // Expand the _ into the appropriate number of implicit vars.
            int missing_dimensions = dimensions() - (int)args.size() + 1;
            for (int i = 0; i < missing_dimensions; i++) {
                int_args.push_back(Var::implicit(i));
            }
        } else if (e.type() == Int(32)) {
            int_args.push_back(e);
        } else {
            int_args.push_back(cast<int>(e));
        }
    }
    return Internal::Call::make(*this, int_args);
}

}
}
<commit_msg>More windows fixes<commit_after>#include "Buffer.h"
#include "Debug.h"
#include "Error.h"
#include "JITModule.h"
#include "runtime/HalideRuntime.h"
#include "Target.h"
#include "Var.h"
#include "IREquality.h"
#include "IROperator.h"

namespace Halide {
namespace Internal {

struct BufferContents {
    Image<> image;
    std::string name;
    mutable RefCount ref_count;
};

template<>
EXPORT RefCount &ref_count<BufferContents>(const BufferContents *p) {
    return p->ref_count;
}

template<>
EXPORT void destroy<BufferContents>(const BufferContents *p) {
    delete p;
}

namespace {
std::string make_buffer_name(const std::string &n, BufferPtr *b) {
    if (n.empty()) {
        return Internal::make_entity_name(b, "Halide::Internal::BufferPtr", 'b');
    } else {
        return n;
    }
}
}

BufferPtr::BufferPtr(const Image<> &buf, std::string name) :
    contents(new Internal::BufferContents) {
    contents->image = Image<>(buf);
    contents->name = make_buffer_name(name, this);
}

BufferPtr::BufferPtr(Type t, const buffer_t &buf, std::string name) :
    contents(new Internal::BufferContents) {
    contents->image = Image<>(t, buf);
    contents->name = make_buffer_name(name, this);
}

BufferPtr::BufferPtr(Type t, const std::vector<int> &size, std::string name) :
    contents(new Internal::BufferContents) {
    contents->image = Image<>(t, size);
    contents->name = make_buffer_name(name, this);
}

bool BufferPtr::same_as(const BufferPtr &other) const {
    return contents.same_as(other.contents);
}

Image<> &BufferPtr::get() {
    return contents->image;
}

const Image<> &BufferPtr::get() const {
    return contents->image;
}

bool BufferPtr::defined() const {
    return contents->image;
}

const std::string &BufferPtr::name() const {
    return contents->name;
}

BufferPtr::operator Argument() const {
    return Argument(name(), Argument::InputBuffer, type(), dimensions());
}

Type BufferPtr::type() const {
    return contents->image.type();
}

int BufferPtr::dimensions() const {
    return contents->image.dimensions();
}

Image<>::Dimension BufferPtr::dim(int i) const {
    return contents->image.dim(i);
}

int BufferPtr::min(int i) const {
    return dim(i).min();
}

int BufferPtr::extent(int i) const {
    return dim(i).extent();
}

int BufferPtr::stride(int i) const {
    return dim(i).stride();
}

buffer_t *BufferPtr::raw_buffer() const {
    return contents->image.raw_buffer();
}

size_t BufferPtr::size_in_bytes() const {
    return contents->image.size_in_bytes();
}

uint8_t *BufferPtr::host_ptr() const {
    return raw_buffer()->host;
}

Expr BufferPtr::operator()(const std::vector<Expr> &args) const {
    // Cast the inputs to int32
    std::vector<Expr> int_args;
    for (Expr e : args) {
        user_assert(Int(32).can_represent(e.type()))
            << "Args to a call to an Image must be representable as 32-bit integers.\n";
        if (equal(e, _)) {
            // Expand the _ into the appropriate number of implicit vars.
            int missing_dimensions = dimensions() - (int)args.size() + 1;
            for (int i = 0; i < missing_dimensions; i++) {
                int_args.push_back(Var::implicit(i));
            }
        } else if (e.type() == Int(32)) {
            int_args.push_back(e);
        } else {
            int_args.push_back(cast<int>(e));
        }
    }
    return Internal::Call::make(*this, int_args);
}

}
}
<|endoftext|>


<commit_before>#include "Buffer.h"
#include "Debug.h"
#include "Error.h"
#include "JITCompiledModule.h"

namespace Halide {
namespace Internal {

namespace {
void check_buffer_size(uint64_t bytes, const std::string &name) {
    user_assert(bytes < (1UL << 31)) << "Total size of buffer " << name << " exceeds 2^31 - 1\n";
}
}

struct BufferContents {
    /** The buffer_t object we're wrapping. */
    buffer_t buf;

    /** The type of the allocation. buffer_t's don't currently track this so we do it here. */
    Type type;

    /** If we made the allocation ourselves via a Buffer constructor,
     * and hence should delete it when this buffer dies, then this
     * pointer is set to the memory we need to free. Otherwise it's
     * NULL. */
    uint8_t *allocation;

    /** How many Buffer objects point to this BufferContents */
    mutable RefCount ref_count;

    /** What is the name of the buffer? Useful for debugging symbols. */
    std::string name;

    /** If this buffer was generated by a jit-compiled module, we need
     * to hang onto the module, as it may contain internal state that
     * tells us how to use this buffer. In particular, if the buffer
     * was generated on the gpu and hasn't been copied back yet, only
     * the module knows how to do that, so we'd better keep the module
     * alive. */
    JITCompiledModule source_module;

    BufferContents(Type t, int x_size, int y_size, int z_size, int w_size,
                   uint8_t* data, const std::string &n) :
        type(t), allocation(NULL), name(n.empty() ? unique_name('b') : n) {
        user_assert(t.width == 1) << "Can't create of a buffer of a vector type";
        buf.elem_size = t.bytes();
        uint64_t size = 1;
        if (x_size) {
            size *= x_size;
            check_buffer_size(size, name);
        }
        if (y_size) {
            size *= y_size;
            check_buffer_size(size, name);
        }
        if (z_size) {
            size *= z_size;
            check_buffer_size(size, name);
        }
        if (w_size) {
            size *= w_size;
            check_buffer_size(size, name);
        }
        size *= buf.elem_size;
        check_buffer_size(size, name);

        if (!data) {
            size = size + 32;
            check_buffer_size(size, name);
            allocation = (uint8_t *)calloc(1, (size_t)size);
            user_assert(allocation) << "Out of memory allocating buffer " << name << " of size " << size << "\n";
            buf.host = allocation;
            while ((size_t)(buf.host) & 0x1f) buf.host++;
        } else {
            buf.host = data;
        }
        buf.dev = 0;
        buf.host_dirty = false;
        buf.dev_dirty = false;
        buf.extent[0] = x_size;
        buf.extent[1] = y_size;
        buf.extent[2] = z_size;
        buf.extent[3] = w_size;
        buf.stride[0] = 1;
        buf.stride[1] = x_size;
        buf.stride[2] = x_size*y_size;
        buf.stride[3] = x_size*y_size*z_size;
        buf.min[0] = 0;
        buf.min[1] = 0;
        buf.min[2] = 0;
        buf.min[3] = 0;
    }

    BufferContents(Type t, const buffer_t *b, const std::string &n) :
        type(t), allocation(NULL), name(n.empty() ? unique_name('b') : n) {
        buf = *b;
        user_assert(t.width == 1) << "Can't create of a buffer of a vector type";
    }
};

template<>
EXPORT RefCount &ref_count<BufferContents>(const BufferContents *p) {
    return p->ref_count;
}

template<>
EXPORT void destroy<BufferContents>(const BufferContents *p) {
    // Free any device-side allocation
    if (p->source_module.free_dev_buffer) {
        int error = p->source_module.free_dev_buffer(NULL, const_cast<buffer_t *>(&p->buf));
        user_assert(!error) << "Failed to free device buffer\n";
    }
    free(p->allocation);

    delete p;
}

}

namespace {
int32_t size_or_zero(const std::vector<int32_t> &sizes, size_t index) {
    return (index < sizes.size()) ? sizes[index] : 0;
}

std::string make_buffer_name(const std::string &n, Buffer *b) {
    if (n.empty()) {
        return Internal::make_entity_name(b, "Halide::Buffer", 'b');
    } else {
        return n;
    }
}
}

Buffer::Buffer(Type t, int x_size, int y_size, int z_size, int w_size,
               uint8_t* data, const std::string &name) :
    contents(new Internal::BufferContents(t, x_size, y_size, z_size, w_size, data,
                                          make_buffer_name(name, this))) {
}

Buffer::Buffer(Type t, const std::vector<int32_t> &sizes,
               uint8_t* data, const std::string &name) :
    contents(new Internal::BufferContents(t,
                                          size_or_zero(sizes, 0),
                                          size_or_zero(sizes, 1),
                                          size_or_zero(sizes, 2),
                                          size_or_zero(sizes, 3),
                                          data,
                                          make_buffer_name(name, this))) {
    user_assert(sizes.size() <= 4) << "Buffer dimensions greater than 4 are not supported.";
}

Buffer::Buffer(Type t, const buffer_t *buf, const std::string &name) :
    contents(new Internal::BufferContents(t, buf,
                                          make_buffer_name(name, this))) {
}

void *Buffer::host_ptr() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return (void *)contents.ptr->buf.host;
}

buffer_t *Buffer::raw_buffer() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return &(contents.ptr->buf);
}

uint64_t Buffer::device_handle() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->buf.dev;
}

bool Buffer::host_dirty() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->buf.host_dirty;
}

void Buffer::set_host_dirty(bool dirty) {
    user_assert(defined()) << "Buffer is undefined\n";
    contents.ptr->buf.host_dirty = dirty;
}

bool Buffer::device_dirty() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->buf.dev_dirty;
}

void Buffer::set_device_dirty(bool dirty) {
    user_assert(defined()) << "Buffer is undefined\n";
    contents.ptr->buf.host_dirty = dirty;
}

int Buffer::dimensions() const {
    for (int i = 0; i < 4; i++) {
        if (extent(i) == 0) return i;
    }
    return 4;
}

int Buffer::extent(int dim) const {
    user_assert(defined()) << "Buffer is undefined\n";
    user_assert(dim >= 0 && dim < 4) << "We only support 4-dimensional buffers for now";
    return contents.ptr->buf.extent[dim];
}

int Buffer::stride(int dim) const {
    user_assert(defined());
    user_assert(dim >= 0 && dim < 4) << "We only support 4-dimensional buffers for now";
    return contents.ptr->buf.stride[dim];
}

int Buffer::min(int dim) const {
    user_assert(defined()) << "Buffer is undefined\n";
    user_assert(dim >= 0 && dim < 4) << "We only support 4-dimensional buffers for now";
    return contents.ptr->buf.min[dim];
}

void Buffer::set_min(int m0, int m1, int m2, int m3) {
    user_assert(defined()) << "Buffer is undefined\n";
    contents.ptr->buf.min[0] = m0;
    contents.ptr->buf.min[1] = m1;
    contents.ptr->buf.min[2] = m2;
    contents.ptr->buf.min[3] = m3;
}

Type Buffer::type() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->type;
}

bool Buffer::same_as(const Buffer &other) const {
    return contents.same_as(other.contents);
}

bool Buffer::defined() const {
    return contents.defined();
}

const std::string &Buffer::name() const {
    return contents.ptr->name;
}

Buffer::operator Argument() const {
    return Argument(name(), true, type());
}

void Buffer::set_source_module(const Internal::JITCompiledModule &module) {
    user_assert(defined()) << "Buffer is undefined\n";
    contents.ptr->source_module = module;
}

const Internal::JITCompiledModule &Buffer::source_module() {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->source_module;
}

int Buffer::copy_to_host() {
    int (*copy_to_host)(void *, buffer_t *) =
        contents.ptr->source_module.copy_to_host;
    if (copy_to_host) {
        /* The user context is always NULL when jitting, so it's safe to
         * pass NULL here. */
        return copy_to_host(NULL, raw_buffer());
    }
    return 0;
}

int Buffer::copy_to_dev() {
    int (*copy_to_dev)(void *, buffer_t *) =
        contents.ptr->source_module.copy_to_dev;
    if (copy_to_dev) {
        return copy_to_dev(NULL, raw_buffer());
    }
    return 0;
}

int Buffer::free_dev_buffer() {
    int (*free_dev_buffer)(void *, buffer_t *) =
        contents.ptr->source_module.free_dev_buffer;
    if (free_dev_buffer) {
        return free_dev_buffer(NULL, raw_buffer());
    }
    return 0;
}

}
<commit_msg>Fix Buffer::set_device_dirty()<commit_after>#include "Buffer.h"
#include "Debug.h"
#include "Error.h"
#include "JITCompiledModule.h"

namespace Halide {
namespace Internal {

namespace {
void check_buffer_size(uint64_t bytes, const std::string &name) {
    user_assert(bytes < (1UL << 31)) << "Total size of buffer " << name << " exceeds 2^31 - 1\n";
}
}

struct BufferContents {
    /** The buffer_t object we're wrapping. */
    buffer_t buf;

    /** The type of the allocation. buffer_t's don't currently track this so we do it here. */
    Type type;

    /** If we made the allocation ourselves via a Buffer constructor,
     * and hence should delete it when this buffer dies, then this
     * pointer is set to the memory we need to free. Otherwise it's
     * NULL. */
    uint8_t *allocation;

    /** How many Buffer objects point to this BufferContents */
    mutable RefCount ref_count;

    /** What is the name of the buffer? Useful for debugging symbols. */
    std::string name;

    /** If this buffer was generated by a jit-compiled module, we need
     * to hang onto the module, as it may contain internal state that
     * tells us how to use this buffer. In particular, if the buffer
     * was generated on the gpu and hasn't been copied back yet, only
     * the module knows how to do that, so we'd better keep the module
     * alive. */
    JITCompiledModule source_module;

    BufferContents(Type t, int x_size, int y_size, int z_size, int w_size,
                   uint8_t* data, const std::string &n) :
        type(t), allocation(NULL), name(n.empty() ? unique_name('b') : n) {
        user_assert(t.width == 1) << "Can't create of a buffer of a vector type";
        buf.elem_size = t.bytes();
        uint64_t size = 1;
        if (x_size) {
            size *= x_size;
            check_buffer_size(size, name);
        }
        if (y_size) {
            size *= y_size;
            check_buffer_size(size, name);
        }
        if (z_size) {
            size *= z_size;
            check_buffer_size(size, name);
        }
        if (w_size) {
            size *= w_size;
            check_buffer_size(size, name);
        }
        size *= buf.elem_size;
        check_buffer_size(size, name);

        if (!data) {
            size = size + 32;
            check_buffer_size(size, name);
            allocation = (uint8_t *)calloc(1, (size_t)size);
            user_assert(allocation) << "Out of memory allocating buffer " << name << " of size " << size << "\n";
            buf.host = allocation;
            while ((size_t)(buf.host) & 0x1f) buf.host++;
        } else {
            buf.host = data;
        }
        buf.dev = 0;
        buf.host_dirty = false;
        buf.dev_dirty = false;
        buf.extent[0] = x_size;
        buf.extent[1] = y_size;
        buf.extent[2] = z_size;
        buf.extent[3] = w_size;
        buf.stride[0] = 1;
        buf.stride[1] = x_size;
        buf.stride[2] = x_size*y_size;
        buf.stride[3] = x_size*y_size*z_size;
        buf.min[0] = 0;
        buf.min[1] = 0;
        buf.min[2] = 0;
        buf.min[3] = 0;
    }

    BufferContents(Type t, const buffer_t *b, const std::string &n) :
        type(t), allocation(NULL), name(n.empty() ? unique_name('b') : n) {
        buf = *b;
        user_assert(t.width == 1) << "Can't create of a buffer of a vector type";
    }
};

template<>
EXPORT RefCount &ref_count<BufferContents>(const BufferContents *p) {
    return p->ref_count;
}

template<>
EXPORT void destroy<BufferContents>(const BufferContents *p) {
    // Free any device-side allocation
    if (p->source_module.free_dev_buffer) {
        int error = p->source_module.free_dev_buffer(NULL, const_cast<buffer_t *>(&p->buf));
        user_assert(!error) << "Failed to free device buffer\n";
    }
    free(p->allocation);

    delete p;
}

}

namespace {
int32_t size_or_zero(const std::vector<int32_t> &sizes, size_t index) {
    return (index < sizes.size()) ? sizes[index] : 0;
}

std::string make_buffer_name(const std::string &n, Buffer *b) {
    if (n.empty()) {
        return Internal::make_entity_name(b, "Halide::Buffer", 'b');
    } else {
        return n;
    }
}
}

Buffer::Buffer(Type t, int x_size, int y_size, int z_size, int w_size,
               uint8_t* data, const std::string &name) :
    contents(new Internal::BufferContents(t, x_size, y_size, z_size, w_size, data,
                                          make_buffer_name(name, this))) {
}

Buffer::Buffer(Type t, const std::vector<int32_t> &sizes,
               uint8_t* data, const std::string &name) :
    contents(new Internal::BufferContents(t,
                                          size_or_zero(sizes, 0),
                                          size_or_zero(sizes, 1),
                                          size_or_zero(sizes, 2),
                                          size_or_zero(sizes, 3),
                                          data,
                                          make_buffer_name(name, this))) {
    user_assert(sizes.size() <= 4) << "Buffer dimensions greater than 4 are not supported.";
}

Buffer::Buffer(Type t, const buffer_t *buf, const std::string &name) :
    contents(new Internal::BufferContents(t, buf,
                                          make_buffer_name(name, this))) {
}

void *Buffer::host_ptr() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return (void *)contents.ptr->buf.host;
}

buffer_t *Buffer::raw_buffer() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return &(contents.ptr->buf);
}

uint64_t Buffer::device_handle() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->buf.dev;
}

bool Buffer::host_dirty() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->buf.host_dirty;
}

void Buffer::set_host_dirty(bool dirty) {
    user_assert(defined()) << "Buffer is undefined\n";
    contents.ptr->buf.host_dirty = dirty;
}

bool Buffer::device_dirty() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->buf.dev_dirty;
}

void Buffer::set_device_dirty(bool dirty) {
    user_assert(defined()) << "Buffer is undefined\n";
    contents.ptr->buf.dev_dirty = dirty;
}

int Buffer::dimensions() const {
    for (int i = 0; i < 4; i++) {
        if (extent(i) == 0) return i;
    }
    return 4;
}

int Buffer::extent(int dim) const {
    user_assert(defined()) << "Buffer is undefined\n";
    user_assert(dim >= 0 && dim < 4) << "We only support 4-dimensional buffers for now";
    return contents.ptr->buf.extent[dim];
}

int Buffer::stride(int dim) const {
    user_assert(defined());
    user_assert(dim >= 0 && dim < 4) << "We only support 4-dimensional buffers for now";
    return contents.ptr->buf.stride[dim];
}

int Buffer::min(int dim) const {
    user_assert(defined()) << "Buffer is undefined\n";
    user_assert(dim >= 0 && dim < 4) << "We only support 4-dimensional buffers for now";
    return contents.ptr->buf.min[dim];
}

void Buffer::set_min(int m0, int m1, int m2, int m3) {
    user_assert(defined()) << "Buffer is undefined\n";
    contents.ptr->buf.min[0] = m0;
    contents.ptr->buf.min[1] = m1;
    contents.ptr->buf.min[2] = m2;
    contents.ptr->buf.min[3] = m3;
}

Type Buffer::type() const {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->type;
}

bool Buffer::same_as(const Buffer &other) const {
    return contents.same_as(other.contents);
}

bool Buffer::defined() const {
    return contents.defined();
}

const std::string &Buffer::name() const {
    return contents.ptr->name;
}

Buffer::operator Argument() const {
    return Argument(name(), true, type());
}

void Buffer::set_source_module(const Internal::JITCompiledModule &module) {
    user_assert(defined()) << "Buffer is undefined\n";
    contents.ptr->source_module = module;
}

const Internal::JITCompiledModule &Buffer::source_module() {
    user_assert(defined()) << "Buffer is undefined\n";
    return contents.ptr->source_module;
}

int Buffer::copy_to_host() {
    int (*copy_to_host)(void *, buffer_t *) =
        contents.ptr->source_module.copy_to_host;
    if (copy_to_host) {
        /* The user context is always NULL when jitting, so it's safe to
         * pass NULL here. */
        return copy_to_host(NULL, raw_buffer());
    }
    return 0;
}

int Buffer::copy_to_dev() {
    int (*copy_to_dev)(void *, buffer_t *) =
        contents.ptr->source_module.copy_to_dev;
    if (copy_to_dev) {
        return copy_to_dev(NULL, raw_buffer());
    }
    return 0;
}

int Buffer::free_dev_buffer() {
    int (*free_dev_buffer)(void *, buffer_t *) =
        contents.ptr->source_module.free_dev_buffer;
    if (free_dev_buffer) {
        return free_dev_buffer(NULL, raw_buffer());
    }
    return 0;
}

}
<|endoftext|>


<commit_before>/*
 * Part of HTTPP.
 *
 * Distributed under the 3-clause BSD licence (See LICENCE.TXT file at the
 * project root).
 *
 * Copyright (c) 2013 Thomas Sanchez.  All rights reserved.
 *
 */

#include "httpp/HttpServer.hpp"

#include <boost/log/trivial.hpp>

#include "httpp/utils/Exception.hpp"
#include "httpp/http/Utils.hpp"

namespace HTTPP
{
struct HttpServer::Acceptor : boost::asio::ip::tcp::acceptor
{
    Acceptor(boost::asio::io_service& service)
    : boost::asio::ip::tcp::acceptor(service)
    {
    }

    void setSSLContext(SSLContext ctx)
    {
        ssl_ctx.reset(
            new boost::asio::ssl::context(boost::asio::ssl::context::sslv23));
        if (!((ctx.cert_file.empty() ^ ctx.cert_buffer.empty()) &&
              (ctx.key_file.empty() ^ ctx.key_buffer.empty())))
        {
            throw std::invalid_argument(
                "Cert and Key file/buffer are required");
        }

        auto flags = boost::asio::ssl::context::default_workarounds |
                     boost::asio::ssl::context::no_sslv2 |
                     boost::asio::ssl::context::single_dh_use;

        ssl_ctx->set_options(flags);

        if (!ctx.cert_file.empty())
        {
            ssl_ctx->use_certificate_file(ctx.cert_file,
                                          boost::asio::ssl::context::pem);
        }
        else
        {
            ssl_ctx->use_certificate(boost::asio::buffer(ctx.cert_buffer),
                                     boost::asio::ssl::context::pem);
        }

        if (!ctx.key_file.empty())
        {
            ssl_ctx->use_private_key_file(ctx.key_file,
                                          boost::asio::ssl::context::pem);
        }
        else
        {
            ssl_ctx->use_private_key(boost::asio::buffer(ctx.key_buffer),
                                     boost::asio::ssl::context::pem);
        }

        if (!ctx.dh_file.empty())
        {
            ssl_ctx->use_tmp_dh_file(ctx.dh_file);
        }
        else if (!ctx.dh_buffer.empty())
        {
            ssl_ctx->use_tmp_dh(boost::asio::buffer(ctx.dh_buffer));
        }
    }

    std::unique_ptr<boost::asio::ssl::context> ssl_ctx;
};

HttpServer::HttpServer(size_t threads)
: service_(threads)
, pool_(threads, service_)
{
}

HttpServer::~HttpServer()
{
    if (running_)
    {
        stop();
    }
}

void HttpServer::start(ThreadInit fct)
{
    if (running_)
    {
        return;
    }
    running_ = true;
    pool_.start(fct);
}

void HttpServer::stopListeners()
{
    for (auto acc : acceptors_)
    {
        boost::system::error_code ec;
        acc->cancel(ec);
        acc->close(ec);
    }

    acceptors_.clear();

    while (running_acceptors_)
    {
        std::this_thread::yield();
    }

}

void HttpServer::stop()
{
    if (!running_)
    {
        return;
    }

    running_ = false;

    stopListeners();

    {
        std::lock_guard<std::mutex> lock(connections_mutex_);
        for (auto connection : connections_)
        {
            connection->markToBeDeleted();
        }
    }

    while (connection_count_)
    {
        std::this_thread::yield();
    }

    pool_.stop();
}

void HttpServer::bind(const std::string& address, const std::string& port)
{
    auto acc = HttpServer::bind(service_, address, port);
    BOOST_LOG_TRIVIAL(debug) << "Bind address: " << address
                             << " on port: " << port;
    acceptors_.push_back(acc);
    ++running_acceptors_;
    start_accept(acc);
}

void HttpServer::bind(const std::string& address,
                      SSLContext ctx,
                      const std::string& port)
{

    auto acc = HttpServer::bind(service_, address, port);
    acc->setSSLContext(std::move(ctx));
    BOOST_LOG_TRIVIAL(debug) << "SSL bind address: " << address
                             << " on port: " << port;
    acceptors_.push_back(acc);
    ++running_acceptors_;
    start_accept(acc);
}

void HttpServer::mark(ConnectionPtr connection)
{
    ++connection_count_;
    std::lock_guard<std::mutex> lock(connections_mutex_);
    connections_.emplace_back(connection);
}

void HttpServer::destroy(ConnectionPtr connection, bool release)
{
    connection->markToBeDeleted();

    {
        std::lock_guard<std::mutex> lock(connections_mutex_);
        auto it = std::find_if(std::begin(connections_),
                               std::end(connections_),
                               [&](ConnectionPtr conn)
                               { return connection == conn; });
        if (it == std::end(connections_))
        {
            return;
        }
        else
        {
            --connection_count_;
            connections_.erase(it);
        }
    }

    if (release)
    {
        connection->disown();
        HTTP::Connection::release(connection);
    }
}

void HttpServer::start_accept(AcceptorPtr acceptor)
{
    if (running_)
    {

        auto connection =
            new HTTP::Connection(*this, service_, pool_, acceptor->ssl_ctx.get());
        mark(connection);

        acceptor->async_accept(connection->socket_,
                               std::bind(&HttpServer::accept_callback,
                                         this,
                                         std::placeholders::_1,
                                         acceptor,
                                         connection));
    }
}

void HttpServer::accept_callback(const boost::system::error_code& error,
                                 AcceptorPtr acceptor,
                                 ConnectionPtr connection)
{

    if (error)
    {
        destroy(connection);

        if (error == boost::asio::error::operation_aborted)
        {
            BOOST_LOG_TRIVIAL(info) << "Cancel listener";
        }
        else
        {
            BOOST_LOG_TRIVIAL(error)
                << "Error during accept: " << error.message();
        }

        --running_acceptors_;
        return;
    }
    else
    {
        if (running_)
        {
            BOOST_LOG_TRIVIAL(debug)
                << "New connection accepted from: " << connection->source();
            connection->start();
        }
        else
        {
            destroy(connection);
        }
    }

    start_accept(acceptor);
}

HttpServer::AcceptorPtr HttpServer::bind(boost::asio::io_service& service,
                                         const std::string& host,
                                         const std::string& port)
{
    auto acceptor = AcceptorPtr(new Acceptor(service));
    boost::system::error_code error;
    auto addr = boost::asio::ip::address::from_string(host, error);
    boost::asio::ip::tcp::endpoint endpoint;
    if (error)
    {
        boost::asio::ip::tcp::resolver resolver(service);
        boost::asio::ip::tcp::resolver::query query(host, port);
        boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(query),
                                                 end;

        if (it == end)
        {
            BOOST_LOG_TRIVIAL(error)
                << "Error bad address (ip address in dotted format or ipv6 hex format: "
                << host << ", error msg: " << error.message();
            throw UTILS::convert_boost_ec_to_std_ec(error);
        }
        else
        {
            endpoint = *it;
        }
    }
    else
    {
        endpoint = boost::asio::ip::tcp::endpoint(addr, std::stoi(port));
    }

    acceptor->open(endpoint.protocol());
    acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), error);
    if (error)
    {

        BOOST_LOG_TRIVIAL(warning) << "Cannot set REUSEADDR on " << host
                                   << " on " << port
                                   << ", error msg: " << error.message();
    }

    acceptor->bind(endpoint, error);
    if (error)
    {

        BOOST_LOG_TRIVIAL(error) << "Cannot bind " << host << " on " << port
                                 << " error msg: " << error.message();
        throw UTILS::convert_boost_ec_to_std_ec(error);
    }

    acceptor->listen(boost::asio::socket_base::max_connections, error);
    if (error)
    {
        BOOST_LOG_TRIVIAL(error) << "Cannot listen " << host << " on " << port
                                 << ", error msg: " << error.message();
        throw UTILS::convert_boost_ec_to_std_ec(error);
    }
    return acceptor;
}

void HttpServer::connection_error(ConnectionPtr connection,
                                  const boost::system::error_code& ec)
{
    if (ec != boost::asio::error::eof &&
        ec != boost::asio::error::connection_reset &&
        ec != boost::asio::error::operation_aborted)
    {
        BOOST_LOG_TRIVIAL(warning)
            << "Got an error from a Connection: " << ec.message();
    }

    destroy(connection);
}

void HttpServer::connection_recycle(ConnectionPtr connection)
{
    connection->start();
}

void HttpServer::connection_notify_request(ConnectionPtr connection,
                                           HTTP::Request&& request)
{
    if (sink_)
    {
        connection->disown();
        sink_(connection, std::forward<HTTP::Request>(request));
    }
    else
    {
        connection->response().setCode(HTTP::HttpCode::NoContent).setBody("");
        HTTP::setShouldConnectionBeClosed(request, connection->response());
        connection->sendResponse();
    }
}

}
<commit_msg>Disable sslv3 and tlsv1 in HTTPP's https code<commit_after>/*
 * Part of HTTPP.
 *
 * Distributed under the 3-clause BSD licence (See LICENCE.TXT file at the
 * project root).
 *
 * Copyright (c) 2013 Thomas Sanchez.  All rights reserved.
 *
 */

#include "httpp/HttpServer.hpp"

#include <boost/log/trivial.hpp>

#include "httpp/utils/Exception.hpp"
#include "httpp/http/Utils.hpp"

namespace HTTPP
{
struct HttpServer::Acceptor : boost::asio::ip::tcp::acceptor
{
    Acceptor(boost::asio::io_service& service)
    : boost::asio::ip::tcp::acceptor(service)
    {
    }

    void setSSLContext(SSLContext ctx)
    {
        ssl_ctx.reset(
            new boost::asio::ssl::context(boost::asio::ssl::context::sslv23));
        if (!((ctx.cert_file.empty() ^ ctx.cert_buffer.empty()) &&
              (ctx.key_file.empty() ^ ctx.key_buffer.empty())))
        {
            throw std::invalid_argument(
                "Cert and Key file/buffer are required");
        }

        auto flags = boost::asio::ssl::context::default_workarounds |
                     boost::asio::ssl::context::no_sslv2 |
                     boost::asio::ssl::context::no_sslv3 |
                     boost::asio::ssl::context::no_tlsv1 |
                     boost::asio::ssl::context::single_dh_use;

        ssl_ctx->set_options(flags);

        if (!ctx.cert_file.empty())
        {
            ssl_ctx->use_certificate_file(ctx.cert_file,
                                          boost::asio::ssl::context::pem);
        }
        else
        {
            ssl_ctx->use_certificate(boost::asio::buffer(ctx.cert_buffer),
                                     boost::asio::ssl::context::pem);
        }

        if (!ctx.key_file.empty())
        {
            ssl_ctx->use_private_key_file(ctx.key_file,
                                          boost::asio::ssl::context::pem);
        }
        else
        {
            ssl_ctx->use_private_key(boost::asio::buffer(ctx.key_buffer),
                                     boost::asio::ssl::context::pem);
        }

        if (!ctx.dh_file.empty())
        {
            ssl_ctx->use_tmp_dh_file(ctx.dh_file);
        }
        else if (!ctx.dh_buffer.empty())
        {
            ssl_ctx->use_tmp_dh(boost::asio::buffer(ctx.dh_buffer));
        }
    }

    std::unique_ptr<boost::asio::ssl::context> ssl_ctx;
};

HttpServer::HttpServer(size_t threads)
: service_(threads)
, pool_(threads, service_)
{
}

HttpServer::~HttpServer()
{
    if (running_)
    {
        stop();
    }
}

void HttpServer::start(ThreadInit fct)
{
    if (running_)
    {
        return;
    }
    running_ = true;
    pool_.start(fct);
}

void HttpServer::stopListeners()
{
    for (auto acc : acceptors_)
    {
        boost::system::error_code ec;
        acc->cancel(ec);
        acc->close(ec);
    }

    acceptors_.clear();

    while (running_acceptors_)
    {
        std::this_thread::yield();
    }

}

void HttpServer::stop()
{
    if (!running_)
    {
        return;
    }

    running_ = false;

    stopListeners();

    {
        std::lock_guard<std::mutex> lock(connections_mutex_);
        for (auto connection : connections_)
        {
            connection->markToBeDeleted();
        }
    }

    while (connection_count_)
    {
        std::this_thread::yield();
    }

    pool_.stop();
}

void HttpServer::bind(const std::string& address, const std::string& port)
{
    auto acc = HttpServer::bind(service_, address, port);
    BOOST_LOG_TRIVIAL(debug) << "Bind address: " << address
                             << " on port: " << port;
    acceptors_.push_back(acc);
    ++running_acceptors_;
    start_accept(acc);
}

void HttpServer::bind(const std::string& address,
                      SSLContext ctx,
                      const std::string& port)
{

    auto acc = HttpServer::bind(service_, address, port);
    acc->setSSLContext(std::move(ctx));
    BOOST_LOG_TRIVIAL(debug) << "SSL bind address: " << address
                             << " on port: " << port;
    acceptors_.push_back(acc);
    ++running_acceptors_;
    start_accept(acc);
}

void HttpServer::mark(ConnectionPtr connection)
{
    ++connection_count_;
    std::lock_guard<std::mutex> lock(connections_mutex_);
    connections_.emplace_back(connection);
}

void HttpServer::destroy(ConnectionPtr connection, bool release)
{
    connection->markToBeDeleted();

    {
        std::lock_guard<std::mutex> lock(connections_mutex_);
        auto it = std::find_if(std::begin(connections_),
                               std::end(connections_),
                               [&](ConnectionPtr conn)
                               { return connection == conn; });
        if (it == std::end(connections_))
        {
            return;
        }
        else
        {
            --connection_count_;
            connections_.erase(it);
        }
    }

    if (release)
    {
        connection->disown();
        HTTP::Connection::release(connection);
    }
}

void HttpServer::start_accept(AcceptorPtr acceptor)
{
    if (running_)
    {

        auto connection =
            new HTTP::Connection(*this, service_, pool_, acceptor->ssl_ctx.get());
        mark(connection);

        acceptor->async_accept(connection->socket_,
                               std::bind(&HttpServer::accept_callback,
                                         this,
                                         std::placeholders::_1,
                                         acceptor,
                                         connection));
    }
}

void HttpServer::accept_callback(const boost::system::error_code& error,
                                 AcceptorPtr acceptor,
                                 ConnectionPtr connection)
{

    if (error)
    {
        destroy(connection);

        if (error == boost::asio::error::operation_aborted)
        {
            BOOST_LOG_TRIVIAL(info) << "Cancel listener";
        }
        else
        {
            BOOST_LOG_TRIVIAL(error)
                << "Error during accept: " << error.message();
        }

        --running_acceptors_;
        return;
    }
    else
    {
        if (running_)
        {
            BOOST_LOG_TRIVIAL(debug)
                << "New connection accepted from: " << connection->source();
            connection->start();
        }
        else
        {
            destroy(connection);
        }
    }

    start_accept(acceptor);
}

HttpServer::AcceptorPtr HttpServer::bind(boost::asio::io_service& service,
                                         const std::string& host,
                                         const std::string& port)
{
    auto acceptor = AcceptorPtr(new Acceptor(service));
    boost::system::error_code error;
    auto addr = boost::asio::ip::address::from_string(host, error);
    boost::asio::ip::tcp::endpoint endpoint;
    if (error)
    {
        boost::asio::ip::tcp::resolver resolver(service);
        boost::asio::ip::tcp::resolver::query query(host, port);
        boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(query),
                                                 end;

        if (it == end)
        {
            BOOST_LOG_TRIVIAL(error)
                << "Error bad address (ip address in dotted format or ipv6 hex format: "
                << host << ", error msg: " << error.message();
            throw UTILS::convert_boost_ec_to_std_ec(error);
        }
        else
        {
            endpoint = *it;
        }
    }
    else
    {
        endpoint = boost::asio::ip::tcp::endpoint(addr, std::stoi(port));
    }

    acceptor->open(endpoint.protocol());
    acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), error);
    if (error)
    {

        BOOST_LOG_TRIVIAL(warning) << "Cannot set REUSEADDR on " << host
                                   << " on " << port
                                   << ", error msg: " << error.message();
    }

    acceptor->bind(endpoint, error);
    if (error)
    {

        BOOST_LOG_TRIVIAL(error) << "Cannot bind " << host << " on " << port
                                 << " error msg: " << error.message();
        throw UTILS::convert_boost_ec_to_std_ec(error);
    }

    acceptor->listen(boost::asio::socket_base::max_connections, error);
    if (error)
    {
        BOOST_LOG_TRIVIAL(error) << "Cannot listen " << host << " on " << port
                                 << ", error msg: " << error.message();
        throw UTILS::convert_boost_ec_to_std_ec(error);
    }
    return acceptor;
}

void HttpServer::connection_error(ConnectionPtr connection,
                                  const boost::system::error_code& ec)
{
    if (ec != boost::asio::error::eof &&
        ec != boost::asio::error::connection_reset &&
        ec != boost::asio::error::operation_aborted)
    {
        BOOST_LOG_TRIVIAL(warning)
            << "Got an error from a Connection: " << ec.message();
    }

    destroy(connection);
}

void HttpServer::connection_recycle(ConnectionPtr connection)
{
    connection->start();
}

void HttpServer::connection_notify_request(ConnectionPtr connection,
                                           HTTP::Request&& request)
{
    if (sink_)
    {
        connection->disown();
        sink_(connection, std::forward<HTTP::Request>(request));
    }
    else
    {
        connection->response().setCode(HTTP::HttpCode::NoContent).setBody("");
        HTTP::setShouldConnectionBeClosed(request, connection->response());
        connection->sendResponse();
    }
}

}
<|endoftext|>


<commit_before>#include "PlayGameState.hpp"

#include "Render.hpp"
#include "InputService.hpp"
#include "TimeService.hpp"
#include "Application.hpp"
#include "TextureMappedFont.hpp"
#include "Global.hpp"
#include "Particles.hpp"
#include "Camera2D.hpp"

namespace Game
{
	PlayGame::PlayGame()
	{
		m_requestExit = false;

		Global::pContext->pInputService->Link_KEYBACK(Param1PtrCallbackStruct(onBackKey,this));

		m_particleTex = new Texture2D;
		m_particleTex->Load("@GUI_Button.tga");

		m_pEmitter = new ParticleEmitterCircle;

		m_pEmitter->SetAngularVelocity(15.0f,17.0f);
		m_pEmitter->SetParticleLife(8.0f,10.0f);
		m_pEmitter->SetVelocity(10.0f,15.0f);
		m_pEmitter->SetTexture(m_particleTex);
		m_pEmitter->SetPosition(Vector2f(200.0f,200.0f));
		m_pEmitter->SetSpawnDelay(1.0f/10.0f);
		m_pEmitter->m_modifiers.push_back(new ParticleEffectorGravity());
		m_pEmitter->m_modifiers.push_back(new ParticleEffectorColor(Vector4f(1.0f,1.0f,0.0f,1.0f),Vector4f(0.0f,0.0f,1.0f,0.0f)));

		//Texture loading
		m_playerTexture=new Texture2D;
		m_joystickInnerTex=new Texture2D;
		m_joystickOuterTex=new Texture2D;

		m_playerTexture->Load("@Player.png");
		m_joystickInnerTex->Load("@joystick_inner.png");
		m_joystickOuterTex->Load("@joystick_outer.png");

		//Sprite setup
		m_playerSprite=new Sprite;
		m_playerSprite->m_position=Vector2f(Render::GetScreenWidth()*0.5,Render::GetScreenHeight()*0.5);
		m_playerSprite->SetTexture(m_playerTexture);
		m_playerSprite->SetSize(50.0f,50.0f);
		m_playerSprite->m_spriteShadingType=SpriteVertex::ALPHA_BLEND;

		//Player setup
		m_playerObject=new Player;
		m_playerObject->m_sprite=m_playerSprite;

		//Joystick setup
		m_joystick=new Joystick;
		m_joystick->SetTextures(m_joystickInnerTex,m_joystickOuterTex);
		m_joystick->SetMaxDistance(100.0f);

		//Camera setup
		Global::pActiveCamera=new Camera2D();
		Global::pActiveCamera->Link(m_playerObject);

		//Setup input surface
		m_fingers[0]=m_fingers[1]=NULL;
		Global::pContext->pInputService->Link_FDOWN(Param2PtrCallbackStruct(DOWN_callback,this));
		Global::pContext->pInputService->Link_FUP(Param2PtrCallbackStruct(UP_callback,this));

		//should be deleted in final version
		m_testTexture=new Texture2D();
		m_testTexture->Load("@explosion.png");

		m_testSprite=new AnimatedSprite();
		m_testSprite->m_position=Vector2f(Render::GetScreenWidth()*0.5,Render::GetScreenHeight()*0.5);
		m_testSprite->SetTexture(m_testTexture);
		m_testSprite->SetSize(200.0f,200.0f);
		m_testSprite->m_spriteShadingType=SpriteVertex::ALPHA_BLEND;
		m_testSprite->m_layer=1.0f;

		m_testSprite->BuildFrameGrid(5,4);
		m_testSprite->SetAnimation(Animation(0,20,10.0f));
	}

	int PlayGame::Update()
	{
		float lTimeStep = Global::pContext->pTimeService->Elapsed();

		m_testSprite->Update(lTimeStep);

		m_joystick->Update();

		if(m_requestExit)
		{
			return EVENT_PLAYGAME_EXIT;
		}

		if(m_fingers[1]!=NULL)
		{
			GLfloat firstDistance=m_firstPosition[0].Distance(m_firstPosition[1]);
			GLfloat currentDistance=m_fingers[0]->m_pos.Distance(m_fingers[1]->m_pos);
			GLfloat ratio=currentDistance/firstDistance;
			Global::pActiveCamera->SetScale(m_firstScale*ratio);
		}

		//NOT FINAL HERE!!!
		m_playerObject->m_acceleration=m_joystick->m_dir*5.0f;
		m_playerObject->m_direction=m_playerObject->m_velocity.Normalized();
		//NOT FINAL HERE!!!

		return EVENT_NOTHING;
	}

	void PlayGame::Render()
	{
		//Global::pFont->SendString("NEW GAME!",Render::GetScreenWidth()*0.5,Render::GetScreenHeight()*0.5,ALIGN_CENTER);
		//m_testSprite->Render();

		m_joystick->Render();
	}

	PlayGame::~PlayGame()
	{
		delete m_particleTex;
		delete m_pEmitter;

		delete m_playerTexture;
		delete m_joystickInnerTex;
		delete m_joystickOuterTex;

		delete m_playerObject;

		delete m_joystick;

		delete Global::pActiveCamera;
		Global::pActiveCamera=NULL;

		//should be deleted in final version
		delete m_testSprite;
		delete m_testTexture;
	}

	void PlayGame::onBackKey(void *pointer)
	{
		PlayGame *pPlayGame=(PlayGame*)(pointer);
		pPlayGame->m_requestExit=true;
	}

	void PlayGame::DOWN_callback(void *param1, void *param2)
	{
		PlayGame *pPlayGame=(PlayGame*)(param1);
		Finger *pFinger=(Finger*)(param2);
		if(pFinger->m_flag==FF_LOCKED)
		{
			return;
		}
		if(pPlayGame->m_fingers[0]==NULL)
		{
			pFinger->m_flag=FF_LOCKED;
			pPlayGame->m_firstPosition[0]=pFinger->m_pos;
			pPlayGame->m_fingers[0]=pFinger;
			return;
		}
		if(pPlayGame->m_fingers[1]==NULL)
		{
			pFinger->m_flag==FF_LOCKED;
			pPlayGame->m_firstPosition[1]=pFinger->m_pos;
			pPlayGame->m_fingers[1]=pFinger;
			pPlayGame->m_firstScale=Global::pActiveCamera->GetScale();
		}
	}

	void PlayGame::UP_callback(void *param1, void *param2)
	{
		PlayGame *pPlayGame=(PlayGame*)(param1);
		Finger *pFinger=(Finger*)(param2);
		if(pPlayGame->m_fingers[1]==pFinger)
		{
			pFinger->m_flag=FF_FREE;
			pPlayGame->m_fingers[1]=NULL;
		}
		if(pPlayGame->m_fingers[0]==pFinger)
		{
			pFinger->m_flag==FF_FREE;
			if(pPlayGame->m_fingers[1]!=NULL)
			{
				pPlayGame->m_fingers[0]=pPlayGame->m_fingers[1];
				pPlayGame->m_fingers[1]=NULL;
			}
			else
			{
				pPlayGame->m_fingers[0]=NULL;
			}
		}
	}
}
<commit_msg>Fixed pinch bug<commit_after>#include "PlayGameState.hpp"

#include "Render.hpp"
#include "InputService.hpp"
#include "TimeService.hpp"
#include "Application.hpp"
#include "TextureMappedFont.hpp"
#include "Global.hpp"
#include "Particles.hpp"
#include "Camera2D.hpp"

namespace Game
{
	PlayGame::PlayGame()
	{
		m_requestExit = false;

		Global::pContext->pInputService->Link_KEYBACK(Param1PtrCallbackStruct(onBackKey,this));

		m_particleTex = new Texture2D;
		m_particleTex->Load("@GUI_Button.tga");

		m_pEmitter = new ParticleEmitterCircle;

		m_pEmitter->SetAngularVelocity(15.0f,17.0f);
		m_pEmitter->SetParticleLife(8.0f,10.0f);
		m_pEmitter->SetVelocity(10.0f,15.0f);
		m_pEmitter->SetTexture(m_particleTex);
		m_pEmitter->SetPosition(Vector2f(200.0f,200.0f));
		m_pEmitter->SetSpawnDelay(1.0f/10.0f);
		m_pEmitter->m_modifiers.push_back(new ParticleEffectorGravity());
		m_pEmitter->m_modifiers.push_back(new ParticleEffectorColor(Vector4f(1.0f,1.0f,0.0f,1.0f),Vector4f(0.0f,0.0f,1.0f,0.0f)));

		//Texture loading
		m_playerTexture=new Texture2D;
		m_joystickInnerTex=new Texture2D;
		m_joystickOuterTex=new Texture2D;

		m_playerTexture->Load("@Player.png");
		m_joystickInnerTex->Load("@joystick_inner.png");
		m_joystickOuterTex->Load("@joystick_outer.png");

		//Sprite setup
		m_playerSprite=new Sprite;
		m_playerSprite->m_position=Vector2f(Render::GetScreenWidth()*0.5,Render::GetScreenHeight()*0.5);
		m_playerSprite->SetTexture(m_playerTexture);
		m_playerSprite->SetSize(50.0f,50.0f);
		m_playerSprite->m_spriteShadingType=SpriteVertex::ALPHA_BLEND;

		//Player setup
		m_playerObject=new Player;
		m_playerObject->m_sprite=m_playerSprite;

		//Joystick setup
		m_joystick=new Joystick;
		m_joystick->SetTextures(m_joystickInnerTex,m_joystickOuterTex);
		m_joystick->SetMaxDistance(100.0f);

		//Camera setup
		Global::pActiveCamera=new Camera2D();
		Global::pActiveCamera->Link(m_playerObject);

		//Setup input surface
		m_fingers[0]=m_fingers[1]=NULL;
		Global::pContext->pInputService->Link_FDOWN(Param2PtrCallbackStruct(DOWN_callback,this));
		Global::pContext->pInputService->Link_FUP(Param2PtrCallbackStruct(UP_callback,this));

		//should be deleted in final version
		m_testTexture=new Texture2D();
		m_testTexture->Load("@explosion.png");

		m_testSprite=new AnimatedSprite();
		m_testSprite->m_position=Vector2f(Render::GetScreenWidth()*0.5,Render::GetScreenHeight()*0.5);
		m_testSprite->SetTexture(m_testTexture);
		m_testSprite->SetSize(200.0f,200.0f);
		m_testSprite->m_spriteShadingType=SpriteVertex::ALPHA_BLEND;
		m_testSprite->m_layer=1.0f;

		m_testSprite->BuildFrameGrid(5,4);
		m_testSprite->SetAnimation(Animation(0,20,10.0f));
	}

	int PlayGame::Update()
	{
		float lTimeStep = Global::pContext->pTimeService->Elapsed();

		m_testSprite->Update(lTimeStep);

		m_joystick->Update();

		if(m_requestExit)
		{
			return EVENT_PLAYGAME_EXIT;
		}

		if(m_fingers[1]!=NULL)
		{
			GLfloat firstDistance=m_firstPosition[0].Distance(m_firstPosition[1]);
			GLfloat currentDistance=m_fingers[0]->m_pos.Distance(m_fingers[1]->m_pos);
			GLfloat ratio=currentDistance/firstDistance;
			Global::pActiveCamera->SetScale(m_firstScale*ratio);
		}

		//NOT FINAL HERE!!!
		m_playerObject->m_acceleration=m_joystick->m_dir*5.0f;
		m_playerObject->m_direction=m_playerObject->m_velocity.Normalized();
		//NOT FINAL HERE!!!

		return EVENT_NOTHING;
	}

	void PlayGame::Render()
	{
		//Global::pFont->SendString("NEW GAME!",Render::GetScreenWidth()*0.5,Render::GetScreenHeight()*0.5,ALIGN_CENTER);
		//m_testSprite->Render();

		m_joystick->Render();
	}

	PlayGame::~PlayGame()
	{
		delete m_particleTex;
		delete m_pEmitter;

		delete m_playerTexture;
		delete m_joystickInnerTex;
		delete m_joystickOuterTex;

		delete m_playerObject;

		delete m_joystick;

		delete Global::pActiveCamera;
		Global::pActiveCamera=NULL;

		//should be deleted in final version
		delete m_testSprite;
		delete m_testTexture;
	}

	void PlayGame::onBackKey(void *pointer)
	{
		PlayGame *pPlayGame=(PlayGame*)(pointer);
		pPlayGame->m_requestExit=true;
	}

	void PlayGame::DOWN_callback(void *param1, void *param2)
	{
		PlayGame *pPlayGame=(PlayGame*)(param1);
		Finger *pFinger=(Finger*)(param2);
		if(pFinger->m_flag==FF_LOCKED)
		{
			return;
		}
		if(pPlayGame->m_fingers[0]==NULL)
		{
			pFinger->m_flag=FF_LOCKED;
			pPlayGame->m_firstPosition[0]=pFinger->m_pos;
			pPlayGame->m_fingers[0]=pFinger;
			return;
		}
		if(pPlayGame->m_fingers[1]==NULL)
		{
			pFinger->m_flag==FF_LOCKED;
			pPlayGame->m_firstPosition[1]=pFinger->m_pos;
			pPlayGame->m_fingers[1]=pFinger;
			pPlayGame->m_firstScale=Global::pActiveCamera->GetScale();
		}
	}

	void PlayGame::UP_callback(void *param1, void *param2)
	{
		PlayGame *pPlayGame=(PlayGame*)(param1);
		Finger *pFinger=(Finger*)(param2);
		if(pPlayGame->m_fingers[1]==pFinger)
		{
			pFinger->m_flag=FF_FREE;
			pPlayGame->m_fingers[1]=NULL;
		}
		if(pPlayGame->m_fingers[0]==pFinger)
		{
			pFinger->m_flag==FF_FREE;
			if(pPlayGame->m_fingers[1]!=NULL)
			{
				pPlayGame->m_fingers[0]=pPlayGame->m_fingers[1];
				pPlayGame->m_firstPosition[0]=pPlayGame->m_firstPosition[1];
				pPlayGame->m_fingers[1]=NULL;
			}
			else
			{
				pPlayGame->m_fingers[0]=NULL;
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2015, Nagoya University
 *  All rights reserved.
 *
 *  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 Autoware nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "state_machine.h"

namespace state_machine
{

void StateTrafficLightStop::update(StateContext *context)
{
  if(context->getLightColor() == TrafficLight::GREEN)
  context->setState(StateMoveForward::create());
}

void StateMoveForward::update(StateContext *context)
{
  if (context->getLightColor() == TrafficLight::RED)
    context->setState(StateTrafficLightStop::create());
}

}  // state_machine<commit_msg>Add comments<commit_after>/*
 *  Copyright (c) 2015, Nagoya University
 *  All rights reserved.
 *
 *  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 Autoware nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "state_machine.h"

namespace state_machine
{

void StateTrafficLightStop::update(StateContext *context)
{
  //if light is GREEN, Go to MOVE_FORWARD
  if(context->getLightColor() == TrafficLight::GREEN)
  context->setState(StateMoveForward::create());
}

void StateMoveForward::update(StateContext *context)
{
  //if light is RED, Go to TRAFFIC_LIGHT_STOP
  if (context->getLightColor() == TrafficLight::RED)
    context->setState(StateTrafficLightStop::create());
}

}  // state_machine<|endoftext|>


<commit_before>/*
 * Copyright (c) 2005-2015 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form 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,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

# include  "compile.h"
# include  "schedule.h"
# include  "dff.h"
# include  <climits>
# include  <cstdio>
# include  <cassert>
# include  <cstdlib>
# include  <iostream>

/* We need to ensure an initial output value is propagated. This is
   achieved by setting asc_ to BIT4_Z to flag that we haven't yet
   propagated an output value. This will also disable clocked output.
   For flip-flops without an asynchronous set/clear, we schedule an
   initial value of BIT4_0 to be sent to port 3. For flip-flops with
   an asynchronous set/clear, we rely on the network propagating an
   initial value to port 3. The first value received on port 3 will
   either propagate the set/clear value (if the received value is
   BIT4_1) or will propagate an initial value of 'bx. From then on
   the flip-flop operates normally. */

vvp_dff::vvp_dff(unsigned width, bool negedge)
: clk_(BIT4_X), ena_(BIT4_X), asc_(BIT4_Z), d_(width, BIT4_X)
{
      clk_active_ = negedge ? BIT4_0 : BIT4_1;
}

vvp_dff::~vvp_dff()
{
}

vvp_dff_aclr::vvp_dff_aclr(unsigned width, bool negedge)
: vvp_dff(width, negedge)
{
}

vvp_dff_aset::vvp_dff_aset(unsigned width, bool negedge)
: vvp_dff(width, negedge)
{
}

vvp_dff_asc::vvp_dff_asc(unsigned width, bool negedge, char*asc_value)
: vvp_dff(width, negedge)
{
      asc_value_ = c4string_to_vector4(asc_value);
}

void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
                        vvp_context_t)
{
      vvp_bit4_t tmp;

      switch (port.port()) {

	  case 0: // D
	    d_ = bit;
	    break;

	  case 1: // CLK
	    assert(bit.size() == 1);
	    if (asc_ != BIT4_0)
		  break;
	    if (ena_ != BIT4_1)
		  break;
	    tmp = clk_;
	    clk_ = bit.value(0);
	    if (clk_ == clk_active_ && tmp != clk_active_)
		  port.ptr()->send_vec4(d_, 0);
	    break;

	  case 2: // CE
	    assert(bit.size() == 1);
	    ena_ = bit.value(0);
	    break;

	  case 3: // asynch SET/CLR
	    assert(bit.size() == 1);
	    tmp = asc_;
	    asc_ = bit.value(0);
	    if (asc_ == BIT4_1 && tmp != BIT4_1)
		  recv_async(port);
	    else if (tmp == BIT4_Z)
		  port.ptr()->send_vec4(vvp_vector4_t(d_.size(), BIT4_X), 0);
	    break;
      }
}

/*
 * The recv_async functions respond to the asynchronous
 * set/clear input by propagating the desired output.
 *
 * NOTE: Don't touch the d_ value, because that tracks the D input,
 * which may be needed when the device is clocked afterwards.
 */
void vvp_dff::recv_async(vvp_net_ptr_t)
{
	// The base dff does not have an asynchronous set/clr input.
      assert(0);
}

void vvp_dff_aclr::recv_async(vvp_net_ptr_t port)
{
      port.ptr()->send_vec4(vvp_vector4_t(d_.size(), BIT4_0), 0);
}

void vvp_dff_aset::recv_async(vvp_net_ptr_t port)
{
      port.ptr()->send_vec4(vvp_vector4_t(d_.size(), BIT4_1), 0);
}

void vvp_dff_asc::recv_async(vvp_net_ptr_t port)
{
      port.ptr()->send_vec4(asc_value_, 0);
}

void compile_dff(char*label, unsigned width, bool negedge,
		 struct symb_s arg_d,
		 struct symb_s arg_c,
		 struct symb_s arg_e)
{
      vvp_net_t*ptr = new vvp_net_t;
      vvp_dff*fun = new vvp_dff(width, negedge);

      ptr->fun = fun;
      define_functor_symbol(label, ptr);
      free(label);
      input_connect(ptr, 0, arg_d.text);
      input_connect(ptr, 1, arg_c.text);
      input_connect(ptr, 2, arg_e.text);

      vvp_vector4_t init_val = vvp_vector4_t(1, BIT4_0);
      schedule_init_vector(vvp_net_ptr_t(ptr,3), init_val);
}

void compile_dff_aclr(char*label, unsigned width, bool negedge,
		      struct symb_s arg_d,
		      struct symb_s arg_c,
		      struct symb_s arg_e,
		      struct symb_s arg_a)
{
      vvp_net_t*ptr = new vvp_net_t;
      vvp_dff*fun = new vvp_dff_aclr(width, negedge);

      ptr->fun = fun;
      define_functor_symbol(label, ptr);
      free(label);
      input_connect(ptr, 0, arg_d.text);
      input_connect(ptr, 1, arg_c.text);
      input_connect(ptr, 2, arg_e.text);
      input_connect(ptr, 3, arg_a.text);
}

void compile_dff_aset(char*label, unsigned width, bool negedge,
		      struct symb_s arg_d,
		      struct symb_s arg_c,
		      struct symb_s arg_e,
		      struct symb_s arg_a,
		      char*asc_value)
{
      vvp_net_t*ptr = new vvp_net_t;
      vvp_dff*fun;
      if (asc_value) {
	    assert(c4string_test(asc_value));
	    fun = new vvp_dff_asc(width, negedge, asc_value);
	    free(asc_value);
      } else {
	    fun = new vvp_dff_aset(width, negedge);
      }

      ptr->fun = fun;
      define_functor_symbol(label, ptr);
      free(label);
      input_connect(ptr, 0, arg_d.text);
      input_connect(ptr, 1, arg_c.text);
      input_connect(ptr, 2, arg_e.text);
      input_connect(ptr, 3, arg_a.text);
}
<commit_msg>Delayed output of vvp dff to end of current time slot.<commit_after>/*
 * Copyright (c) 2005-2015 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form 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,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

# include  "compile.h"
# include  "schedule.h"
# include  "dff.h"
# include  <climits>
# include  <cstdio>
# include  <cassert>
# include  <cstdlib>
# include  <iostream>

/* We need to ensure an initial output value is propagated. This is
   achieved by setting asc_ to BIT4_Z to flag that we haven't yet
   propagated an output value. This will also disable clocked output.
   For flip-flops without an asynchronous set/clear, we schedule an
   initial value of BIT4_0 to be sent to port 3. For flip-flops with
   an asynchronous set/clear, we rely on the network propagating an
   initial value to port 3. The first value received on port 3 will
   either propagate the set/clear value (if the received value is
   BIT4_1) or will propagate an initial value of 'bx. From then on
   the flip-flop operates normally. */

vvp_dff::vvp_dff(unsigned width, bool negedge)
: clk_(BIT4_X), ena_(BIT4_X), asc_(BIT4_Z), d_(width, BIT4_X)
{
      clk_active_ = negedge ? BIT4_0 : BIT4_1;
}

vvp_dff::~vvp_dff()
{
}

vvp_dff_aclr::vvp_dff_aclr(unsigned width, bool negedge)
: vvp_dff(width, negedge)
{
}

vvp_dff_aset::vvp_dff_aset(unsigned width, bool negedge)
: vvp_dff(width, negedge)
{
}

vvp_dff_asc::vvp_dff_asc(unsigned width, bool negedge, char*asc_value)
: vvp_dff(width, negedge)
{
      asc_value_ = c4string_to_vector4(asc_value);
}

void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
                        vvp_context_t)
{
      vvp_bit4_t tmp;

      switch (port.port()) {

	  case 0: // D
	    d_ = bit;
	    break;

	  case 1: // CLK
	    assert(bit.size() == 1);
	    if (asc_ != BIT4_0)
		  break;
	    if (ena_ != BIT4_1)
		  break;
	    tmp = clk_;
	    clk_ = bit.value(0);
	    if (clk_ == clk_active_ && tmp != clk_active_)
		  schedule_propagate_vector(port.ptr(), 0, d_);
	    break;

	  case 2: // CE
	    assert(bit.size() == 1);
	    ena_ = bit.value(0);
	    break;

	  case 3: // asynch SET/CLR
	    assert(bit.size() == 1);
	    tmp = asc_;
	    asc_ = bit.value(0);
	    if (asc_ == BIT4_1 && tmp != BIT4_1)
		  recv_async(port);
	    else if (tmp == BIT4_Z)
		  port.ptr()->send_vec4(vvp_vector4_t(d_.size(), BIT4_X), 0);
	    break;
      }
}

/*
 * The recv_async functions respond to the asynchronous
 * set/clear input by propagating the desired output.
 *
 * NOTE: Don't touch the d_ value, because that tracks the D input,
 * which may be needed when the device is clocked afterwards.
 */
void vvp_dff::recv_async(vvp_net_ptr_t)
{
	// The base dff does not have an asynchronous set/clr input.
      assert(0);
}

void vvp_dff_aclr::recv_async(vvp_net_ptr_t port)
{
      schedule_propagate_vector(port.ptr(), 0, vvp_vector4_t(d_.size(), BIT4_0));
}

void vvp_dff_aset::recv_async(vvp_net_ptr_t port)
{
      schedule_propagate_vector(port.ptr(), 0, vvp_vector4_t(d_.size(), BIT4_1));
}

void vvp_dff_asc::recv_async(vvp_net_ptr_t port)
{
      schedule_propagate_vector(port.ptr(), 0, asc_value_);
}

void compile_dff(char*label, unsigned width, bool negedge,
		 struct symb_s arg_d,
		 struct symb_s arg_c,
		 struct symb_s arg_e)
{
      vvp_net_t*ptr = new vvp_net_t;
      vvp_dff*fun = new vvp_dff(width, negedge);

      ptr->fun = fun;
      define_functor_symbol(label, ptr);
      free(label);
      input_connect(ptr, 0, arg_d.text);
      input_connect(ptr, 1, arg_c.text);
      input_connect(ptr, 2, arg_e.text);

      vvp_vector4_t init_val = vvp_vector4_t(1, BIT4_0);
      schedule_init_vector(vvp_net_ptr_t(ptr,3), init_val);
}

void compile_dff_aclr(char*label, unsigned width, bool negedge,
		      struct symb_s arg_d,
		      struct symb_s arg_c,
		      struct symb_s arg_e,
		      struct symb_s arg_a)
{
      vvp_net_t*ptr = new vvp_net_t;
      vvp_dff*fun = new vvp_dff_aclr(width, negedge);

      ptr->fun = fun;
      define_functor_symbol(label, ptr);
      free(label);
      input_connect(ptr, 0, arg_d.text);
      input_connect(ptr, 1, arg_c.text);
      input_connect(ptr, 2, arg_e.text);
      input_connect(ptr, 3, arg_a.text);
}

void compile_dff_aset(char*label, unsigned width, bool negedge,
		      struct symb_s arg_d,
		      struct symb_s arg_c,
		      struct symb_s arg_e,
		      struct symb_s arg_a,
		      char*asc_value)
{
      vvp_net_t*ptr = new vvp_net_t;
      vvp_dff*fun;
      if (asc_value) {
	    assert(c4string_test(asc_value));
	    fun = new vvp_dff_asc(width, negedge, asc_value);
	    free(asc_value);
      } else {
	    fun = new vvp_dff_aset(width, negedge);
      }

      ptr->fun = fun;
      define_functor_symbol(label, ptr);
      free(label);
      input_connect(ptr, 0, arg_d.text);
      input_connect(ptr, 1, arg_c.text);
      input_connect(ptr, 2, arg_e.text);
      input_connect(ptr, 3, arg_a.text);
}
<|endoftext|>


<commit_before>#include "dialog.h"
#include "resources.h"
#include "settings.h"
#include "reposition.h"
#include <shellapi.h>

HWND create_dialog (HINSTANCE hInstance, dialog_struct_t * ds)
{
  INITCOMMONCONTROLSEX icc = { sizeof (INITCOMMONCONTROLSEX), ICC_BAR_CLASSES | ICC_LINK_CLASS | ICC_STANDARD_CLASSES };
  ::InitCommonControlsEx (& icc);

  return ::CreateDialogParam (hInstance, MAKEINTRESOURCE (IDD_CONFIGURE), ds->hwnd, DialogProc, (LPARAM) ds);
}

INT_PTR CALLBACK DialogProc (HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
{
  dialog_struct_t * ds = reinterpret_cast <dialog_struct_t *> (::GetWindowLongPtr (hdlg, DWLP_USER));

  switch (message)
  {
  case WM_INITDIALOG: {
    ds = (dialog_struct_t *) lParam;
    ::SetWindowLongPtr (hdlg, DWLP_USER, (LONG_PTR) ds);
    HWND hwnd_message = ::GetDlgItem (hdlg, IDC_MESSAGE);
    HFONT font = ::CreateFont (16, 0, 0, 0, FW_DONTCARE, TRUE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS,
                               CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_ROMAN, TEXT ("Segoe UI"));
    ::SendMessage (hwnd_message, WM_SETFONT, (WPARAM) font, 0);
    // The id of trackbar n is IDC_TRACKBARS_START + 4 * n, and its buddies have the two succeeding ids.
    for (unsigned i = 0; i != trackbar_count; ++ i) {
      HWND hwnd_trackbar = ::GetDlgItem (hdlg, IDC_TRACKBARS_START + 4 * i);
      ::SendMessage (hwnd_trackbar, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) ds->settings.trackbar_pos [i]);
      for (unsigned j = 0; j != 2; ++ j) {
        HWND hwnd_buddy = ::GetDlgItem (hdlg, IDC_TRACKBARS_START + 4 * i + 1 + j);
        ::SendMessage (hwnd_trackbar, TBM_SETBUDDY, (WPARAM) j, (LPARAM) hwnd_buddy);
      }
    }
    reposition_window (hdlg);
    // Override the Z order specified by the ownership relationship.
    ::SetWindowPos (hdlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
    return TRUE;
  }

  case WM_COMMAND: {
    const UINT id = LOWORD (wParam);
    for (unsigned i = 0; i != trackbar_count; ++ i) {
      HWND hwnd_trackbar = ::GetDlgItem (hdlg, IDC_TRACKBARS_START + 4 * i);
      ds->settings.trackbar_pos [i] = (DWORD) ::SendMessage (hwnd_trackbar, TBM_GETPOS, 0, 0);
    }
    if (id == IDOK) save_settings (ds->settings);
    if (id != IDC_PREVIEW_BUTTON) ::DestroyWindow (ds->hwnd);
    if (id == IDC_PREVIEW_BUTTON) ::ShowWindow (ds->hwnd, SW_SHOW);
    return TRUE;
  }

  case WM_NOTIFY: {
    LPNMHDR notify = (LPNMHDR) lParam;
    if (notify->idFrom == IDC_SYSLINK && (notify->code == NM_CLICK || notify->code == NM_RETURN)) {
      PNMLINK link_notify = (PNMLINK) lParam;
      ::ShellExecute (NULL, TEXT ("open"), link_notify->item.szUrl, NULL, NULL, SW_SHOW);
    }
    return FALSE;
  }

  case WM_DRAWITEM: {
    // Draw trackbar buddy labels with baseline aligned to the bottom of the channel.
    DRAWITEMSTRUCT * drawitem = (DRAWITEMSTRUCT *) lParam;
    const UINT buddy_id = drawitem->CtlID;
    const UINT trackbar_id = buddy_id & ~3;
    HWND hwnd_buddy = drawitem->hwndItem;
    HWND hwnd_trackbar = ::GetDlgItem (hdlg, trackbar_id);
    BOOL buddy_side = (buddy_id & 3) - 1;
    // Compute the reference point in the buddy's client coordinates.
    RECT buddy_rect, trackbar_rect, channel_rect;
    ::GetWindowRect (hwnd_trackbar, & trackbar_rect);
    ::GetWindowRect (hwnd_buddy, & buddy_rect);
    ::SendMessage (hwnd_trackbar, TBM_GETCHANNELRECT, 0, (LPARAM) & channel_rect);
    int x = (buddy_side ? buddy_rect.right : buddy_rect.left) - buddy_rect.left;
    int y = trackbar_rect.top + channel_rect.bottom - buddy_rect.top;
    // Retrieve the buddy's text.
    const WPARAM buffer_size = 64;
    TCHAR buffer [buffer_size];
    UINT length = (UINT) ::SendMessage (hwnd_buddy, WM_GETTEXT, buffer_size, (LPARAM) buffer);
    // Render the text.
    ::SetTextAlign (drawitem->hDC, (buddy_side ? TA_RIGHT : TA_LEFT) | TA_BASELINE | TA_NOUPDATECP);
    ::ExtTextOut (drawitem->hDC, x, y, 0, NULL, buffer, length, NULL);
    return TRUE;
  }

  case WM_CTLCOLORSTATIC: case WM_CTLCOLORDLG: {
    COLORREF color = (HWND) lParam == ::GetDlgItem (hdlg, IDC_BUTTONS_STATIC) ? COLOR_BTNFACE : COLOR_WINDOW;
    return (INT_PTR) ::GetSysColorBrush (color);
  }

  default:
    return FALSE;
  }
}
<commit_msg>dialog.cpp: since szUrl is an array of WCHAR we must use the Unicode version of ShellExecute.<commit_after>#include "dialog.h"
#include "resources.h"
#include "settings.h"
#include "reposition.h"
#include <shellapi.h>

HWND create_dialog (HINSTANCE hInstance, dialog_struct_t * ds)
{
  INITCOMMONCONTROLSEX icc = { sizeof (INITCOMMONCONTROLSEX), ICC_BAR_CLASSES | ICC_LINK_CLASS | ICC_STANDARD_CLASSES };
  ::InitCommonControlsEx (& icc);

  return ::CreateDialogParam (hInstance, MAKEINTRESOURCE (IDD_CONFIGURE), ds->hwnd, DialogProc, (LPARAM) ds);
}

INT_PTR CALLBACK DialogProc (HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
{
  dialog_struct_t * ds = reinterpret_cast <dialog_struct_t *> (::GetWindowLongPtr (hdlg, DWLP_USER));

  switch (message)
  {
  case WM_INITDIALOG: {
    ds = (dialog_struct_t *) lParam;
    ::SetWindowLongPtr (hdlg, DWLP_USER, (LONG_PTR) ds);
    HWND hwnd_message = ::GetDlgItem (hdlg, IDC_MESSAGE);
    HFONT font = ::CreateFont (16, 0, 0, 0, FW_DONTCARE, TRUE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS,
                               CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_ROMAN, TEXT ("Segoe UI"));
    ::SendMessage (hwnd_message, WM_SETFONT, (WPARAM) font, 0);
    // The id of trackbar n is IDC_TRACKBARS_START + 4 * n, and its buddies have the two succeeding ids.
    for (unsigned i = 0; i != trackbar_count; ++ i) {
      HWND hwnd_trackbar = ::GetDlgItem (hdlg, IDC_TRACKBARS_START + 4 * i);
      ::SendMessage (hwnd_trackbar, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) ds->settings.trackbar_pos [i]);
      for (unsigned j = 0; j != 2; ++ j) {
        HWND hwnd_buddy = ::GetDlgItem (hdlg, IDC_TRACKBARS_START + 4 * i + 1 + j);
        ::SendMessage (hwnd_trackbar, TBM_SETBUDDY, (WPARAM) j, (LPARAM) hwnd_buddy);
      }
    }
    reposition_window (hdlg);
    // Override the Z order specified by the ownership relationship.
    ::SetWindowPos (hdlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
    return TRUE;
  }

  case WM_COMMAND: {
    const UINT id = LOWORD (wParam);
    for (unsigned i = 0; i != trackbar_count; ++ i) {
      HWND hwnd_trackbar = ::GetDlgItem (hdlg, IDC_TRACKBARS_START + 4 * i);
      ds->settings.trackbar_pos [i] = (DWORD) ::SendMessage (hwnd_trackbar, TBM_GETPOS, 0, 0);
    }
    if (id == IDOK) save_settings (ds->settings);
    if (id != IDC_PREVIEW_BUTTON) ::DestroyWindow (ds->hwnd);
    if (id == IDC_PREVIEW_BUTTON) ::ShowWindow (ds->hwnd, SW_SHOW);
    return TRUE;
  }

  case WM_NOTIFY: {
    LPNMHDR notify = (LPNMHDR) lParam;
    if (notify->idFrom == IDC_SYSLINK && (notify->code == NM_CLICK || notify->code == NM_RETURN)) {
      PNMLINK link_notify = (PNMLINK) lParam;
      ::ShellExecuteW (NULL, L"open", link_notify->item.szUrl, NULL, NULL, SW_SHOW);
    }
    return FALSE;
  }

  case WM_DRAWITEM: {
    // Draw trackbar buddy labels with baseline aligned to the bottom of the channel.
    DRAWITEMSTRUCT * drawitem = (DRAWITEMSTRUCT *) lParam;
    const UINT buddy_id = drawitem->CtlID;
    const UINT trackbar_id = buddy_id & ~3;
    HWND hwnd_buddy = drawitem->hwndItem;
    HWND hwnd_trackbar = ::GetDlgItem (hdlg, trackbar_id);
    BOOL buddy_side = (buddy_id & 3) - 1;
    // Compute the reference point in the buddy's client coordinates.
    RECT buddy_rect, trackbar_rect, channel_rect;
    ::GetWindowRect (hwnd_trackbar, & trackbar_rect);
    ::GetWindowRect (hwnd_buddy, & buddy_rect);
    ::SendMessage (hwnd_trackbar, TBM_GETCHANNELRECT, 0, (LPARAM) & channel_rect);
    int x = (buddy_side ? buddy_rect.right : buddy_rect.left) - buddy_rect.left;
    int y = trackbar_rect.top + channel_rect.bottom - buddy_rect.top;
    // Retrieve the buddy's text.
    const WPARAM buffer_size = 64;
    TCHAR buffer [buffer_size];
    UINT length = (UINT) ::SendMessage (hwnd_buddy, WM_GETTEXT, buffer_size, (LPARAM) buffer);
    // Render the text.
    ::SetTextAlign (drawitem->hDC, (buddy_side ? TA_RIGHT : TA_LEFT) | TA_BASELINE | TA_NOUPDATECP);
    ::ExtTextOut (drawitem->hDC, x, y, 0, NULL, buffer, length, NULL);
    return TRUE;
  }

  case WM_CTLCOLORSTATIC: case WM_CTLCOLORDLG: {
    COLORREF color = (HWND) lParam == ::GetDlgItem (hdlg, IDC_BUTTONS_STATIC) ? COLOR_BTNFACE : COLOR_WINDOW;
    return (INT_PTR) ::GetSysColorBrush (color);
  }

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