<commit_before>#include "../ref/main_types.h"
#include "../src/glresource_types.hpp"
#include "../src/gltexturing.hpp"
#include "../src/gldebug.hpp"
#include "../src/glshaders.hpp"

#include <micros/api.h>

#include "stb_perlin.h"
#include "stb_image_write.h"

#include <GL/glew.h>

#include <vector>
#include <future>

static std::string dirname(std::string path)
{
        return path.substr(0, path.find_last_of("/\\"));
}

extern void render_next_2chn_48khz_audio(uint64_t time_micros,
                int const sample_count, double left[/*sample_count*/],
                double right[/*sample_count*/])
{
        // silence is soothing
}

struct SimpleShaderProgram : public ShaderProgramResource {
        VertexShaderResource vertexShader;
        FragmentShaderResource fragmentShader;
};

static void defineProgram(SimpleShaderProgram& program,
                          std::string const& vertexShaderSource,
                          std::string const& fragmentShaderSource)
{
        compile(program.vertexShader, vertexShaderSource);
        compile(program.fragmentShader, fragmentShaderSource);

        glAttachShader(program.id, program.vertexShader.id);
        glAttachShader(program.id, program.fragmentShader.id);
        glLinkProgram(program.id);
}

struct MainShaderVariables {
        GLint textureUniforms[2];
        GLint positionAttrib;
        GLint texcoordAttrib;
};

static MainShaderVariables getMainShaderVariables(ShaderProgramResource const&
                program)
{
        auto const id = program.id;
        MainShaderVariables variables = {
                {
                        glGetUniformLocation(id, "tex0"),
                        glGetUniformLocation(id, "tex1")
                },
                glGetAttribLocation(program.id, "position"),
                glGetAttribLocation(program.id, "texcoord")
        };

        return variables;
}

static size_t define2dQuadIndices(BufferResource const& buffer)
{
        size_t count = 0;
        withElementBuffer(buffer,
        [&count]() {
                GLuint data[] = {
                        0, 1, 2, 2, 3, 0,
                };
                count = sizeof data / sizeof data[0];

                glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof data, data,
                             GL_STREAM_DRAW);
        });

        return count;
}

static GLvoid* define2dQuadBuffer(BufferResource const& buffer, float xmin,
                                  float ymin, float width, float height)
{
        withArrayBuffer(buffer,
        [=]() {
                float data[] = {
                        xmin, ymin,
                        xmin, ymin + height,
                        xmin + width, ymin + height,
                        xmin + width, ymin,
                };

                glBufferData(GL_ARRAY_BUFFER, sizeof data, data, GL_STREAM_DRAW);
        });

        return 0;
}

extern void render_next_gl3(uint64_t time_micros)
{
        static class Tasks : public DisplayThreadTasks
        {
        public:
                void add_task(std::function<bool()>&& task)
                {
                        std::lock_guard<std::mutex> lock(tasks_mtx);
                        tasks.emplace_back(task);
                }

                void run()
                {
                        std::lock_guard<std::mutex> lock(tasks_mtx);
                        for (auto& task : tasks) {
                                std::future<bool> future = task.get_future();
                                task();
                                future.get();
                        }
                        tasks.clear();
                }

                std::mutex tasks_mtx;
                std::vector<std::packaged_task<bool()>> tasks;
        } tasks;

        static class SrcFileSystem : public FileSystem
        {
        public:
                SrcFileSystem() : base_path(dirname(__FILE__)) {}

                std::ifstream open_file(std::string relpath) const
                {
                        auto stream = std::ifstream(base_path + "/" + relpath);

                        if (stream.fail()) {
                                throw std::runtime_error("could not load file at " + relpath);
                        }

                        return stream;
                }

                std::string base_path;
        } srcFileSystem;

        static struct Resources {
                Resources() :
                        fileLoader(makeFileLoader(srcFileSystem, tasks))
                {
                        {
                                indicesCount = define2dQuadIndices(indices);
                                quadPositionOffset = define2dQuadBuffer(vertices, -1.0, -1.0, 2.0, 2.0);
                                quadTexcoordsOffset = define2dQuadBuffer(texcoords, 0.0, 0.0, 1.0, 1.0);
                        }

                        loadFilePair(*fileLoader.get(), "main.vs",
                        "main.fs", [=](std::string const& contentVS, std::string const& contentFS) {
                                defineProgram(mainShader, contentVS, contentFS);
                                mainShaderVars = getMainShaderVariables(mainShader);

                                withShaderProgram(mainShader, [=]() {
                                        // bind to texture units 0 and 1
                                        glUniform1i(mainShaderVars.textureUniforms[0], 0);
                                        glUniform1i(mainShaderVars.textureUniforms[1], 1);
                                });

                                withVertexArray(vertexArray, [=]() {
                                        glBindBuffer(GL_ARRAY_BUFFER, texcoords.id);
                                        glVertexAttribPointer(mainShaderVars.texcoordAttrib, 2, GL_FLOAT, GL_FALSE, 0,
                                                              quadTexcoordsOffset);
                                        glBindBuffer(GL_ARRAY_BUFFER, vertices.id);
                                        glVertexAttribPointer(mainShaderVars.positionAttrib, 2, GL_FLOAT, GL_FALSE, 0,
                                                              quadPositionOffset);

                                        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices.id);
                                        glEnableVertexAttribArray(mainShaderVars.texcoordAttrib);
                                        glEnableVertexAttribArray(mainShaderVars.positionAttrib);
                                        validate(mainShader);
                                });
                        });

                        {
                                int const width = 64;
                                int const height = 64;
                                OGL_TRACE;

                                withTexture(quadTexture,
                                []() {
                                        defineNonMipmappedARGB32Texture(width, height, [](uint32_t* data,
                                        int const width, int const height) {
                                                for (int y = 0; y < height; y++) {
                                                        for (int x = 0; x < width; x++) {
                                                                uint8_t values[4];
                                                                for (size_t i = 0; i < sizeof values / sizeof values[0]; i++) {
                                                                        float val = 0.5 + stb_perlin_noise3(13.0 * x / width, 17.0 * y / height, 0.0);
                                                                        if (val > 1.0) {
                                                                                val = 1.0;
                                                                        } else if (val < 0.0) {
                                                                                val = 0.0;
                                                                        }

                                                                        values[i] = (int) (255 * val) & 0xff;
                                                                }

                                                                data[x + y*width] = (values[0] << 24)
                                                                                | (values[1] << 16)
                                                                                | (values[2] << 8)
                                                                                | values[3];
                                                        }
                                                }

                                        });
                                });
                        }
                }

                SimpleShaderProgram mainShader;
                MainShaderVariables mainShaderVars;
                FileLoaderResource fileLoader;

                TextureResource quadTexture;
                size_t indicesCount;
                VertexArrayResource vertexArray;
                BufferResource indices;
                BufferResource vertices;
                BufferResource texcoords;

                GLvoid* quadPositionOffset;
                GLvoid* quadTexcoordsOffset;
        } resources;

        tasks.run();

        auto const& program = resources.mainShader;
        if (program.id > 0) {
                withShaderProgram(program, []() {
                        withTexture(resources.quadTexture, []() {
                                withVertexArray(resources.vertexArray, []() {
                                        glDrawElements(GL_TRIANGLES, resources.indicesCount, GL_UNSIGNED_INT, 0);
                                });
                        });
                });
        }
}

int main()
{
        runtime_init();

        return 0;
}
<commit_msg>factorize some more<commit_after>#include "../ref/main_types.h"
#include "../src/glresource_types.hpp"
#include "../src/gltexturing.hpp"
#include "../src/gldebug.hpp"
#include "../src/glshaders.hpp"

#include <micros/api.h>

#include "stb_perlin.h"
#include "stb_image_write.h"

#include <GL/glew.h>

#include <vector>
#include <future>

static std::string dirname(std::string path)
{
        return path.substr(0, path.find_last_of("/\\"));
}

extern void render_next_2chn_48khz_audio(uint64_t time_micros,
                int const sample_count, double left[/*sample_count*/],
                double right[/*sample_count*/])
{
        // silence is soothing
}

struct SimpleShaderProgram : public ShaderProgramResource {
        VertexShaderResource vertexShader;
        FragmentShaderResource fragmentShader;
};

static void defineProgram(SimpleShaderProgram& program,
                          std::string const& vertexShaderSource,
                          std::string const& fragmentShaderSource)
{
        compile(program.vertexShader, vertexShaderSource);
        compile(program.fragmentShader, fragmentShaderSource);

        glAttachShader(program.id, program.vertexShader.id);
        glAttachShader(program.id, program.fragmentShader.id);
        glLinkProgram(program.id);
}

struct MainShaderVariables {
        GLint textureUniforms[2];
        GLint positionAttrib;
        GLint texcoordAttrib;
};

static MainShaderVariables getMainShaderVariables(ShaderProgramResource const&
                program)
{
        auto const id = program.id;
        MainShaderVariables variables = {
                {
                        glGetUniformLocation(id, "tex0"),
                        glGetUniformLocation(id, "tex1")
                },
                glGetAttribLocation(program.id, "position"),
                glGetAttribLocation(program.id, "texcoord")
        };

        return variables;
}

static size_t define2dQuadIndices(BufferResource const& buffer)
{
        size_t count = 0;
        withElementBuffer(buffer,
        [&count]() {
                GLuint data[] = {
                        0, 1, 2, 2, 3, 0,
                };
                count = sizeof data / sizeof data[0];

                glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof data, data,
                             GL_STREAM_DRAW);
        });

        return count;
}

static GLvoid* define2dQuadBuffer(BufferResource const& buffer, float xmin,
                                  float ymin, float width, float height)
{
        withArrayBuffer(buffer,
        [=]() {
                float data[] = {
                        xmin, ymin,
                        xmin, ymin + height,
                        xmin + width, ymin + height,
                        xmin + width, ymin,
                };

                glBufferData(GL_ARRAY_BUFFER, sizeof data, data, GL_STREAM_DRAW);
        });

        return 0;
}

static void define2dTrianglesVertexArray(BufferResource const& indices,
                GLint positionAttrib, BufferResource const& positions,
                GLvoid* positionsOffset,
                GLint texcoordAttrib, BufferResource const& texcoords,
                GLvoid* texcoordsOffset)
{
        glBindBuffer(GL_ARRAY_BUFFER, texcoords.id);
        glVertexAttribPointer(texcoordAttrib, 2, GL_FLOAT, GL_FALSE, 0,
                              texcoordsOffset);

        glBindBuffer(GL_ARRAY_BUFFER, positions.id);
        glVertexAttribPointer(positionAttrib, 2, GL_FLOAT, GL_FALSE, 0,
                              positionsOffset);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices.id);
        glEnableVertexAttribArray(texcoordAttrib);
        glEnableVertexAttribArray(positionAttrib);
}

extern void render_next_gl3(uint64_t time_micros)
{
        static class Tasks : public DisplayThreadTasks
        {
        public:
                void add_task(std::function<bool()>&& task)
                {
                        std::lock_guard<std::mutex> lock(tasks_mtx);
                        tasks.emplace_back(task);
                }

                void run()
                {
                        std::lock_guard<std::mutex> lock(tasks_mtx);
                        for (auto& task : tasks) {
                                std::future<bool> future = task.get_future();
                                task();
                                future.get();
                        }
                        tasks.clear();
                }

                std::mutex tasks_mtx;
                std::vector<std::packaged_task<bool()>> tasks;
        } tasks;

        static class SrcFileSystem : public FileSystem
        {
        public:
                SrcFileSystem() : base_path(dirname(__FILE__)) {}

                std::ifstream open_file(std::string relpath) const
                {
                        auto stream = std::ifstream(base_path + "/" + relpath);

                        if (stream.fail()) {
                                throw std::runtime_error("could not load file at " + relpath);
                        }

                        return stream;
                }

                std::string base_path;
        } srcFileSystem;

        static struct Resources {
                Resources() :
                        fileLoader(makeFileLoader(srcFileSystem, tasks))
                {
                        {
                                indicesCount = define2dQuadIndices(indices);
                                quadPositionOffset = define2dQuadBuffer(vertices, -1.0, -1.0, 2.0, 2.0);
                                quadTexcoordsOffset = define2dQuadBuffer(texcoords, 0.0, 0.0, 1.0, 1.0);
                        }

                        loadFilePair(*fileLoader.get(), "main.vs",
                        "main.fs", [=](std::string const& contentVS, std::string const& contentFS) {
                                defineProgram(mainShader, contentVS, contentFS);
                                mainShaderVars = getMainShaderVariables(mainShader);

                                withShaderProgram(mainShader, [=]() {
                                        // bind to texture units 0 and 1
                                        glUniform1i(mainShaderVars.textureUniforms[0], 0);
                                        glUniform1i(mainShaderVars.textureUniforms[1], 1);
                                });

                                withVertexArray(vertexArray, [=]() {
                                        define2dTrianglesVertexArray
                                        (indices,
                                         mainShaderVars.positionAttrib, vertices, quadPositionOffset,
                                         mainShaderVars.texcoordAttrib, texcoords, quadTexcoordsOffset);
                                        validate(mainShader);
                                });
                        });

                        {
                                int const width = 64;
                                int const height = 64;
                                OGL_TRACE;

                                withTexture(quadTexture,
                                []() {
                                        defineNonMipmappedARGB32Texture(width, height, [](uint32_t* data,
                                        int const width, int const height) {
                                                for (int y = 0; y < height; y++) {
                                                        for (int x = 0; x < width; x++) {
                                                                uint8_t values[4];
                                                                for (size_t i = 0; i < sizeof values / sizeof values[0]; i++) {
                                                                        float val = 0.5 + stb_perlin_noise3(13.0 * x / width, 17.0 * y / height, 0.0);
                                                                        if (val > 1.0) {
                                                                                val = 1.0;
                                                                        } else if (val < 0.0) {
                                                                                val = 0.0;
                                                                        }

                                                                        values[i] = (int) (255 * val) & 0xff;
                                                                }

                                                                data[x + y*width] = (values[0] << 24)
                                                                                | (values[1] << 16)
                                                                                | (values[2] << 8)
                                                                                | values[3];
                                                        }
                                                }

                                        });
                                });
                        }
                }

                SimpleShaderProgram mainShader;
                MainShaderVariables mainShaderVars;
                FileLoaderResource fileLoader;

                TextureResource quadTexture;
                size_t indicesCount;
                VertexArrayResource vertexArray;
                BufferResource indices;
                BufferResource vertices;
                BufferResource texcoords;

                GLvoid* quadPositionOffset;
                GLvoid* quadTexcoordsOffset;
        } resources;

        tasks.run();

        auto const& program = resources.mainShader;
        if (program.id > 0) {
                withShaderProgram(program, []() {
                        withTexture(resources.quadTexture, []() {
                                withVertexArray(resources.vertexArray, []() {
                                        glDrawElements(GL_TRIANGLES, resources.indicesCount, GL_UNSIGNED_INT, 0);
                                });
                        });
                });
        }
}

int main()
{
        runtime_init();

        return 0;
}
<|endoftext|>


<commit_before>#include "primitiv_c/internal.h"
#include "primitiv_c/naive_device.h"

#include <primitiv/naive_device.h>

using primitiv::devices::Naive;

extern "C" {

primitiv_Device *primitiv_Naive_new() {
  return reinterpret_cast<primitiv_Device*>(new Naive());
}

primitiv_Device *primitiv_Naive_new_with_seed(uint32_t seed) {
  return reinterpret_cast<primitiv_Device*>(new Naive(seed));
}

void primitiv_Naive_delete(primitiv_Device *device) {
  delete reinterpret_cast<Naive*>(device);
}

}  // end extern "C"
<commit_msg>Refactor device cast.<commit_after>#include "primitiv_c/internal.h"
#include "primitiv_c/naive_device.h"

#include <primitiv/naive_device.h>

using primitiv::devices::Naive;

#define CAST_TO_CC_NAIVE(x) reinterpret_cast<Naive*>(x)
#define CAST_TO_CONST_CC_NAIVE(x) reinterpret_cast<const Naive*>(x)

extern "C" {

primitiv_Device *primitiv_Naive_new() {
  return to_c(new Naive());
}

primitiv_Device *primitiv_Naive_new_with_seed(uint32_t seed) {
  return to_c(new Naive(seed));
}

void primitiv_Naive_delete(primitiv_Device *device) {
  delete CAST_TO_CC_NAIVE(device);
}

}  // end extern "C"
<|endoftext|>


<commit_before>/*
 * This file is part of the Camera Streaming Daemon
 *
 * Copyright (C) 2017  Intel Corporation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <assert.h>
#include <avahi-common/error.h>
#include <sstream>
#include <stdexcept>

#include "avahi_publisher.h"
#include "log.h"
#include "mainloop.h"

AvahiPublisher::AvahiPublisher(std::vector<std::unique_ptr<Stream>> &_streams, int _port,
                               const char *_type)
    : is_running(false)
    , avahi_poll(nullptr)
    , streams(_streams)
    , client(nullptr)
    , group(nullptr)
    , port(_port)
    , type(_type)
{
}

AvahiPublisher::~AvahiPublisher()
{
    stop();
}

void AvahiPublisher::avahi_client_cb(AvahiClient *c, AvahiClientState state, void *userdata)
{
    assert(c);
    AvahiPublisher *publisher = (AvahiPublisher *)userdata;

    switch (state) {
    case AVAHI_CLIENT_S_RUNNING:
        publisher->publish_services(c);
        break;

    case AVAHI_CLIENT_FAILURE:
        log_error("Failed to create avahi client: %s", avahi_strerror(avahi_client_errno(c)));
        // TODO: Restart avahi publisher
        break;

    case AVAHI_CLIENT_S_COLLISION:
    case AVAHI_CLIENT_S_REGISTERING:
        publisher->reset_services();
        break;

    case AVAHI_CLIENT_CONNECTING:;
    }
}

void AvahiPublisher::entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state,
                                          void *userdata)
{
    assert(g);

    /* Called whenever the entry group state changes */

    switch (state) {
    case AVAHI_ENTRY_GROUP_COLLISION:
        log_debug("Service name collision. Ignoring service");
        // TODO: Handle error
        break;

    case AVAHI_ENTRY_GROUP_FAILURE:
        log_error("Failed to create avahi group");
        // TODO: Restart avahi publisher
        break;

    default:;
    }
}

void AvahiPublisher::reset_services()
{
    if (group)
        avahi_entry_group_reset(group);
}

AvahiStringList *AvahiPublisher::txt_record_from_stream(const std::unique_ptr<Stream> &s)
{
    AvahiStringList *lst = NULL;
    const std::vector<Stream::PixelFormat> &formats = s->get_formats();
    for (int i = formats.size() - 1; i >= 0; i--) {
        std::stringstream ss;
        ss << "frame_size[" << i << "]=";
        ss << formats[i];
        lst = avahi_string_list_add(lst, ss.str().c_str());
    }

    std::string name = "name=";
    name.append(s->get_name());
    lst = avahi_string_list_add(lst, name.c_str());

    return lst;
}

void AvahiPublisher::publish_services(AvahiClient *c)
{
    int ret;

    if (!group) {
        group = avahi_entry_group_new(c, entry_group_callback, NULL);
        if (!group) {
            log_error("Failed to create avahi group: %s", avahi_strerror(avahi_client_errno(c)));
            // TODO: Restart avahi publisher
        }
    }

    if (avahi_entry_group_is_empty(group)) {
        for (auto const &s : streams) {
            AvahiStringList *strlist = txt_record_from_stream(s);
            ret = avahi_entry_group_add_service_strlst(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                                                       (AvahiPublishFlags)0, s->get_path().c_str(),
                                                       type, NULL, NULL, port, strlist);
            avahi_string_list_free(strlist);
            if (ret != 0) {
                // TODO: handle error
                log_error("Failed to add service %s", s->get_path().c_str());
            }
        }

        ret = avahi_entry_group_commit(group);
        if (ret < 0) {
            // TODO: handle error
            log_error("Failed to add services to avahi group.");
        }
    }
}

void AvahiPublisher::start()
{
    if (is_running)
        return;
    is_running = true;

    int error;

    client = avahi_client_new(Mainloop::get_mainloop()->get_avahi_poll_api(), (AvahiClientFlags)0,
                              avahi_client_cb, this, &error);
    if (!client) {
        log_error("Unalbe to create avahi client. Video streams won't be published as avahi services.");
    }
}

void AvahiPublisher::stop()
{
    if (!is_running)
        return;
    is_running = false;

    avahi_client_free(client);
    client = nullptr;
    group = nullptr;
}
<commit_msg>Don't try to add avahi services if no video streams are present<commit_after>/*
 * This file is part of the Camera Streaming Daemon
 *
 * Copyright (C) 2017  Intel Corporation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <assert.h>
#include <avahi-common/error.h>
#include <sstream>
#include <stdexcept>

#include "avahi_publisher.h"
#include "log.h"
#include "mainloop.h"

AvahiPublisher::AvahiPublisher(std::vector<std::unique_ptr<Stream>> &_streams, int _port,
                               const char *_type)
    : is_running(false)
    , avahi_poll(nullptr)
    , streams(_streams)
    , client(nullptr)
    , group(nullptr)
    , port(_port)
    , type(_type)
{
}

AvahiPublisher::~AvahiPublisher()
{
    stop();
}

void AvahiPublisher::avahi_client_cb(AvahiClient *c, AvahiClientState state, void *userdata)
{
    assert(c);
    AvahiPublisher *publisher = (AvahiPublisher *)userdata;

    switch (state) {
    case AVAHI_CLIENT_S_RUNNING:
        publisher->publish_services(c);
        break;

    case AVAHI_CLIENT_FAILURE:
        log_error("Failed to create avahi client: %s", avahi_strerror(avahi_client_errno(c)));
        // TODO: Restart avahi publisher
        break;

    case AVAHI_CLIENT_S_COLLISION:
    case AVAHI_CLIENT_S_REGISTERING:
        publisher->reset_services();
        break;

    case AVAHI_CLIENT_CONNECTING:;
    }
}

void AvahiPublisher::entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state,
                                          void *userdata)
{
    assert(g);

    /* Called whenever the entry group state changes */

    switch (state) {
    case AVAHI_ENTRY_GROUP_COLLISION:
        log_debug("Service name collision. Ignoring service");
        // TODO: Handle error
        break;

    case AVAHI_ENTRY_GROUP_FAILURE:
        log_error("Failed to create avahi group");
        // TODO: Restart avahi publisher
        break;

    default:;
    }
}

void AvahiPublisher::reset_services()
{
    if (group)
        avahi_entry_group_reset(group);
}

AvahiStringList *AvahiPublisher::txt_record_from_stream(const std::unique_ptr<Stream> &s)
{
    AvahiStringList *lst = NULL;
    const std::vector<Stream::PixelFormat> &formats = s->get_formats();
    for (int i = formats.size() - 1; i >= 0; i--) {
        std::stringstream ss;
        ss << "frame_size[" << i << "]=";
        ss << formats[i];
        lst = avahi_string_list_add(lst, ss.str().c_str());
    }

    std::string name = "name=";
    name.append(s->get_name());
    lst = avahi_string_list_add(lst, name.c_str());

    return lst;
}

void AvahiPublisher::publish_services(AvahiClient *c)
{
    int ret;

    if (!group) {
        group = avahi_entry_group_new(c, entry_group_callback, NULL);
        if (!group) {
            log_error("Failed to create avahi group: %s", avahi_strerror(avahi_client_errno(c)));
            // TODO: Restart avahi publisher
        }
    }

    if (avahi_entry_group_is_empty(group)) {
        for (auto const &s : streams) {
            AvahiStringList *strlist = txt_record_from_stream(s);
            ret = avahi_entry_group_add_service_strlst(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                                                       (AvahiPublishFlags)0, s->get_path().c_str(),
                                                       type, NULL, NULL, port, strlist);
            avahi_string_list_free(strlist);
            if (ret != 0) {
                // TODO: handle error
                log_error("Failed to add service %s", s->get_path().c_str());
            }
        }

        ret = avahi_entry_group_commit(group);
        if (ret < 0) {
            // TODO: handle error
            log_error("Failed to add services to avahi group.");
        }
    }
}

void AvahiPublisher::start()
{
    if (is_running)
        return;

    if (streams.size() == 0) {
        log_debug("No streams found. Not publishing avahi services");
        return;
    }

    is_running = true;
    int error;

    client = avahi_client_new(Mainloop::get_mainloop()->get_avahi_poll_api(), (AvahiClientFlags)0,
                              avahi_client_cb, this, &error);
    if (!client) {
        log_error("Unalbe to create avahi client. Video streams won't be published as avahi services.");
    }
}

void AvahiPublisher::stop()
{
    if (!is_running)
        return;
    is_running = false;

    avahi_client_free(client);
    client = nullptr;
    group = nullptr;
}
<|endoftext|>


<commit_before><commit_msg>Fix a minor bug that allowed users to remove English from the language config.<commit_after><|endoftext|>


<commit_before><commit_msg>Temporary disabled for landing DevTools protocol patch upstream. https://bugs.webkit.org/show_bug.cgi?id=57957 We are migrating the protocol to JSON-RPC-2.0 spec.<commit_after><|endoftext|>


<commit_before><commit_msg>Another flaky crashy test: ExtensionUpdaterTest.TestBlacklistUpdateCheckRequests<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.  Use of this
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.

#include "chrome/browser/in_process_webkit/dom_storage_context.h"

#include "base/file_path.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/in_process_webkit/storage_area.h"
#include "chrome/browser/in_process_webkit/storage_namespace.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"

DOMStorageContext::DOMStorageContext(WebKitContext* webkit_context)
    : last_storage_area_id_(kFirstStorageAreaId),
      last_storage_namespace_id_(kFirstStorageNamespaceId),
      webkit_context_(webkit_context) {
}

DOMStorageContext::~DOMStorageContext() {
  // This should not go away until all DOM Storage Dispatcher hosts have gone
  // away.  And they remove themselves from this list.
  DCHECK(dispatcher_host_set_.empty());

  // If we don't have any work to do on the WebKit thread, bail.
  if (storage_namespace_map_.empty())
    return;
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));

  // The storage namespace destructor unregisters the storage namespace, so
  // our iterator becomes invalid.  Thus we just keep deleting the first item
  // until there are none left.
  while (!storage_namespace_map_.empty())
    delete storage_namespace_map_.begin()->second;
}

StorageNamespace* DOMStorageContext::LocalStorage() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  StorageNamespace* storage_namespace = GetStorageNamespace(
      kLocalStorageNamespaceId);
  if (storage_namespace)
    return storage_namespace;

  FilePath data_path = webkit_context_->data_path();
  FilePath dir_path;
  if (!data_path.empty())
    dir_path = data_path.AppendASCII("localStorage");
  return StorageNamespace::CreateLocalStorageNamespace(this, dir_path);
}

StorageNamespace* DOMStorageContext::NewSessionStorage() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  return StorageNamespace::CreateSessionStorageNamespace(this);
}

void DOMStorageContext::RegisterStorageArea(StorageArea* storage_area) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  int64 id = storage_area->id();
  DCHECK(!GetStorageArea(id));
  storage_area_map_[id] = storage_area;
}

void DOMStorageContext::UnregisterStorageArea(StorageArea* storage_area) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  int64 id = storage_area->id();
  DCHECK(GetStorageArea(id));
  storage_area_map_.erase(id);
}

StorageArea* DOMStorageContext::GetStorageArea(int64 id) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  StorageAreaMap::iterator iter = storage_area_map_.find(id);
  if (iter == storage_area_map_.end())
    return NULL;
  return iter->second;
}

void DOMStorageContext::RegisterStorageNamespace(
    StorageNamespace* storage_namespace) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  int64 id = storage_namespace->id();
  DCHECK(!GetStorageNamespace(id));
  storage_namespace_map_[id] = storage_namespace;
}

void DOMStorageContext::UnregisterStorageNamespace(
    StorageNamespace* storage_namespace) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  int64 id = storage_namespace->id();
  DCHECK(GetStorageNamespace(id));
  storage_namespace_map_.erase(id);
}

StorageNamespace* DOMStorageContext::GetStorageNamespace(int64 id) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id);
  if (iter == storage_namespace_map_.end())
    return NULL;
  return iter->second;
}

void DOMStorageContext::RegisterDispatcherHost(
    DOMStorageDispatcherHost* dispatcher_host) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  DCHECK(dispatcher_host_set_.find(dispatcher_host) ==
         dispatcher_host_set_.end());
  dispatcher_host_set_.insert(dispatcher_host);
}

void DOMStorageContext::UnregisterDispatcherHost(
    DOMStorageDispatcherHost* dispatcher_host) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  DCHECK(dispatcher_host_set_.find(dispatcher_host) !=
         dispatcher_host_set_.end());
  dispatcher_host_set_.erase(dispatcher_host);
}

const DOMStorageContext::DispatcherHostSet*
DOMStorageContext::GetDispatcherHostSet() const {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  return &dispatcher_host_set_;
}

void DOMStorageContext::PurgeMemory() {
  // It is only safe to purge the memory from the LocalStorage namespace,
  // because it is backed by disk and can be reloaded later.  If we purge a
  // SessionStorage namespace, its data will be gone forever, because it isn't
  // currently backed by disk.
  StorageNamespace* local_storage =
      GetStorageNamespace(kLocalStorageNamespaceId);
  if (local_storage)
    local_storage->PurgeMemory();
}
<commit_msg>Put local storage files in "Local Storage" instead of "localStorage" directory to match existing convention.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.  Use of this
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.

#include "chrome/browser/in_process_webkit/dom_storage_context.h"

#include "base/file_path.h"
#include "base/file_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/in_process_webkit/storage_area.h"
#include "chrome/browser/in_process_webkit/storage_namespace.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"

static const char* kLocalStorageDirectory = "Local Storage";

// TODO(jorlow): Remove after Chrome 4 ships.
static void MigrateLocalStorageDirectory(const FilePath& data_path) {
  FilePath new_path = data_path.AppendASCII(kLocalStorageDirectory);
  FilePath old_path = data_path.AppendASCII("localStorage");
  if (!file_util::DirectoryExists(new_path) &&
      file_util::DirectoryExists(old_path)) {
    file_util::Move(old_path, new_path);
  }
}

DOMStorageContext::DOMStorageContext(WebKitContext* webkit_context)
    : last_storage_area_id_(kFirstStorageAreaId),
      last_storage_namespace_id_(kFirstStorageNamespaceId),
      webkit_context_(webkit_context) {
}

DOMStorageContext::~DOMStorageContext() {
  // This should not go away until all DOM Storage Dispatcher hosts have gone
  // away.  And they remove themselves from this list.
  DCHECK(dispatcher_host_set_.empty());

  // If we don't have any work to do on the WebKit thread, bail.
  if (storage_namespace_map_.empty())
    return;
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));

  // The storage namespace destructor unregisters the storage namespace, so
  // our iterator becomes invalid.  Thus we just keep deleting the first item
  // until there are none left.
  while (!storage_namespace_map_.empty())
    delete storage_namespace_map_.begin()->second;
}

StorageNamespace* DOMStorageContext::LocalStorage() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  StorageNamespace* storage_namespace = GetStorageNamespace(
      kLocalStorageNamespaceId);
  if (storage_namespace)
    return storage_namespace;

  FilePath data_path = webkit_context_->data_path();
  FilePath dir_path;
  if (!data_path.empty()) {
    MigrateLocalStorageDirectory(data_path);
    dir_path = data_path.AppendASCII(kLocalStorageDirectory);
  }
  return StorageNamespace::CreateLocalStorageNamespace(this, dir_path);
}

StorageNamespace* DOMStorageContext::NewSessionStorage() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  return StorageNamespace::CreateSessionStorageNamespace(this);
}

void DOMStorageContext::RegisterStorageArea(StorageArea* storage_area) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  int64 id = storage_area->id();
  DCHECK(!GetStorageArea(id));
  storage_area_map_[id] = storage_area;
}

void DOMStorageContext::UnregisterStorageArea(StorageArea* storage_area) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  int64 id = storage_area->id();
  DCHECK(GetStorageArea(id));
  storage_area_map_.erase(id);
}

StorageArea* DOMStorageContext::GetStorageArea(int64 id) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  StorageAreaMap::iterator iter = storage_area_map_.find(id);
  if (iter == storage_area_map_.end())
    return NULL;
  return iter->second;
}

void DOMStorageContext::RegisterStorageNamespace(
    StorageNamespace* storage_namespace) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  int64 id = storage_namespace->id();
  DCHECK(!GetStorageNamespace(id));
  storage_namespace_map_[id] = storage_namespace;
}

void DOMStorageContext::UnregisterStorageNamespace(
    StorageNamespace* storage_namespace) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  int64 id = storage_namespace->id();
  DCHECK(GetStorageNamespace(id));
  storage_namespace_map_.erase(id);
}

StorageNamespace* DOMStorageContext::GetStorageNamespace(int64 id) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
  StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id);
  if (iter == storage_namespace_map_.end())
    return NULL;
  return iter->second;
}

void DOMStorageContext::RegisterDispatcherHost(
    DOMStorageDispatcherHost* dispatcher_host) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  DCHECK(dispatcher_host_set_.find(dispatcher_host) ==
         dispatcher_host_set_.end());
  dispatcher_host_set_.insert(dispatcher_host);
}

void DOMStorageContext::UnregisterDispatcherHost(
    DOMStorageDispatcherHost* dispatcher_host) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  DCHECK(dispatcher_host_set_.find(dispatcher_host) !=
         dispatcher_host_set_.end());
  dispatcher_host_set_.erase(dispatcher_host);
}

const DOMStorageContext::DispatcherHostSet*
DOMStorageContext::GetDispatcherHostSet() const {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  return &dispatcher_host_set_;
}

void DOMStorageContext::PurgeMemory() {
  // It is only safe to purge the memory from the LocalStorage namespace,
  // because it is backed by disk and can be reloaded later.  If we purge a
  // SessionStorage namespace, its data will be gone forever, because it isn't
  // currently backed by disk.
  StorageNamespace* local_storage =
      GetStorageNamespace(kLocalStorageNamespaceId);
  if (local_storage)
    local_storage->PurgeMemory();
}
<|endoftext|>


<commit_before>#include "NodeShape.hpp"
#include <lib/core/convops.hpp>
#include <lib/core/log.hpp>
#include <lib/core/window.hpp>

#include <SFML/Graphics/Texture.hpp>

#define _USE_MATH_DEFINES
#include <math.h>

namespace lib
{
	namespace draw
	{
		NodeShape::NodeShape(const std::string &name, const vector2df& size, const u32 pointCount, const NodeMode mode)
			: Renderizable{ name }, _mode{ mode }, m_texture{ nullptr },m_textureRect(),m_fillColor(255, 255, 255),
			m_vertices(sf::TrianglesFan), m_bounds(), _size{ size }, m_pointCount{ pointCount }
		{
			update();
		}

		NodeShape::~NodeShape()
		{

		}

		void NodeShape::setSize(const lib::vector2df & size)
		{
			_size = size;
			update();
		}

		void NodeShape::setSize(const float size)
		{
			setSize(lib::vector2df(size,size));
		}

		const lib::vector2df & NodeShape::getSize() const
		{
			return _size;
		}

		u32 NodeShape::getPointCount() const
		{
			return m_pointCount;
		}

		void NodeShape::setPointCount(lib::u32 numPoints)
		{
			m_pointCount = numPoints;
			update();
		}

		vector2df NodeShape::getPoint(unsigned int index) const
		{
			// TO DO:
			// Optimize and cache it
			switch (_mode)
			{
			default:
			case lib::draw::NodeShape::NodeMode::Shape:
			{
				lib::vector2df m_radius{ _size / 2.0f };
				double angle = ((index * 2 * M_PI) / getPointCount()) - (M_PI_2);
				double x = std::cos(angle) * m_radius.x;
				double y = std::sin(angle) * m_radius.y;

				return vector2df(static_cast<float>(m_radius.x + x), static_cast<float>(m_radius.y + y));

			}
			break;
			case lib::draw::NodeShape::NodeMode::Sprite:
			{
				__ASSERT(m_pointCount == 4, "Invalid sprite state");

				switch (index)
				{
				default:
				case 0: return vector2df(0, 0);
				case 1: return vector2df(_size.x, 0);
				case 2: return vector2df(_size.x, _size.y);
				case 3: return vector2df(0, _size.y);
				}
			}
			break;
			}
		}

		void NodeShape::setTexture(const sf::Texture *texture, bool resetSize/*=true*/, bool resetRect /*= false*/)
		{
			setTexture_(texture, resetRect);
			if (resetSize)
			{
				setSize(static_cast<lib::vector2df>(texture->getSize()));
			}
		}

		// Compute the normal of a segment
		vector2df computeNormal(const ::lib::vector2df& p1, const lib::vector2df& p2)
		{
			::lib::vector2df normal(p1.y - p2.y, p2.x - p1.x);
			float length = std::sqrt(normal.x * normal.x + normal.y * normal.y);
			if (length != 0.f)
				normal /= length;
			return normal;
		}

		// Compute the dot product of two vectors
		float dotProduct(const vector2df& p1, const vector2df& p2)
		{
			return p1.x * p2.x + p1.y * p2.y;
		}

		void NodeShape::setTexture_(const sf::Texture* texture, bool resetRect)
		{
			if (texture)
			{
				// Recompute the texture area if requested, or if there was no texture & rect before
				if (resetRect || (!m_texture && (m_textureRect == Rects32())))
					setTextureRect(Rects32(0, 0, texture->getSize().x, texture->getSize().y));
			}

			// Assign the new texture
			m_texture = texture;
		}

		const sf::Texture* NodeShape::getTexture() const
		{
			return m_texture;
		}

		void NodeShape::setTextureRect(const Rects32& rect)
		{
			m_textureRect = rect;
			updateTexCoords();
		}

		const Rects32& NodeShape::getTextureRect() const
		{
			return m_textureRect;
		}

		void NodeShape::setColor(const Color& color)
		{
			m_fillColor = color;
			updateFillColors();
		}

		const Color& NodeShape::getFillColor() const
		{
			return m_fillColor;
		}

		Rectf32 NodeShape::getLocalBounds() const
		{
			return m_bounds;
		}

		Rectf32 NodeShape::getGlobalBounds() const
		{
			return getTransform().transformRect(getLocalBounds());
		}

		void NodeShape::update()
		{
			// Get the total number of points of the shape
			std::size_t count = getPointCount();
			if (count < 3)
			{
				m_vertices.resize(0);
				return;
			}

			m_vertices.resize(count + 2); // + 2 for center and repeated first point

			// Position
			for (std::size_t i = 0; i < count; ++i)
				m_vertices[i + 1].position = getPoint(i);
			m_vertices[count + 1].position = m_vertices[1].position;

			// Update the bounding rectangle
			m_vertices[0] = m_vertices[1]; // so that the result of getBounds() is correct
			m_bounds = convert(m_vertices.getBounds());
			// Compute the center and make it the first vertex
			m_vertices[0].position.x = m_bounds.width / 2;
			m_vertices[0].position.y = m_bounds.height / 2;

			// Color
			updateFillColors();

			// Texture coordinates
			updateTexCoords();
		}

		u32 NodeShape::draw(lib::core::Window *window, lib::draw::RenderStates &states)
		{
			auto oldTransformation= states.transform;
			states.transform *= getTransform();

			// Render the inside
			states.texture = m_texture;
			window->draw(m_vertices, convert(states));

			states.transform = oldTransformation;
			return 1;
		}

		void NodeShape::updateFillColors()
		{
			for (std::size_t i = 0; i < m_vertices.getVertexCount(); ++i)
				m_vertices[i].color = m_fillColor;
		}

		void NodeShape::updateTexCoords()
		{
			for (std::size_t i = 0; i < m_vertices.getVertexCount(); ++i)
			{
				float xratio = m_bounds.width > 0 ? (m_vertices[i].position.x - m_bounds.left) / m_bounds.width : 0;
				float yratio = m_bounds.height > 0 ? (m_vertices[i].position.y - m_bounds.top) / m_bounds.height : 0;
				m_vertices[i].texCoords.x = m_textureRect.left + m_textureRect.width * xratio;
				m_vertices[i].texCoords.y = m_textureRect.top + m_textureRect.height * yratio;
			}
		}
	}
}
<commit_msg>Clean signature.<commit_after>#include "NodeShape.hpp"
#include <lib/core/convops.hpp>
#include <lib/core/log.hpp>
#include <lib/core/window.hpp>

#include <SFML/Graphics/Texture.hpp>

#define _USE_MATH_DEFINES
#include <math.h>

namespace lib
{
	namespace draw
	{
		NodeShape::NodeShape(const std::string &name, const vector2df& size, const u32 pointCount, const NodeMode mode)
			: Renderizable{ name }, _mode{ mode }, m_texture{ nullptr },m_textureRect(),m_fillColor(255, 255, 255),
			m_vertices(sf::TrianglesFan), m_bounds(), _size{ size }, m_pointCount{ pointCount }
		{
			update();
		}

		NodeShape::~NodeShape()
		{

		}

		void NodeShape::setSize(const lib::vector2df & size)
		{
			_size = size;
			update();
		}

		void NodeShape::setSize(const float size)
		{
			setSize(lib::vector2df(size,size));
		}

		const lib::vector2df & NodeShape::getSize() const
		{
			return _size;
		}

		u32 NodeShape::getPointCount() const
		{
			return m_pointCount;
		}

		void NodeShape::setPointCount(lib::u32 numPoints)
		{
			m_pointCount = numPoints;
			update();
		}

		vector2df NodeShape::getPoint(unsigned int index) const
		{
			// TO DO:
			// Optimize and cache it
			switch (_mode)
			{
			default:
			case lib::draw::NodeShape::NodeMode::Shape:
			{
				lib::vector2df m_radius{ _size / 2.0f };
				double angle = ((index * 2 * M_PI) / getPointCount()) - (M_PI_2);
				double x = std::cos(angle) * m_radius.x;
				double y = std::sin(angle) * m_radius.y;

				return vector2df(static_cast<float>(m_radius.x + x), static_cast<float>(m_radius.y + y));

			}
			break;
			case lib::draw::NodeShape::NodeMode::Sprite:
			{
				__ASSERT(m_pointCount == 4, "Invalid sprite state");

				switch (index)
				{
				default:
				case 0: return vector2df(0, 0);
				case 1: return vector2df(_size.x, 0);
				case 2: return vector2df(_size.x, _size.y);
				case 3: return vector2df(0, _size.y);
				}
			}
			break;
			}
		}

		void NodeShape::setTexture(const sf::Texture *texture, bool resetSize/*=true*/, bool resetRect /*= false*/)
		{
			setTexture_(texture, resetRect);
			if (resetSize)
			{
				setSize(static_cast<lib::vector2df>(texture->getSize()));
			}
		}

		// Compute the normal of a segment
		vector2df computeNormal(const ::lib::vector2df& p1, const lib::vector2df& p2)
		{
			::lib::vector2df normal(p1.y - p2.y, p2.x - p1.x);
			float length = std::sqrt(normal.x * normal.x + normal.y * normal.y);
			if (length != 0.f)
				normal /= length;
			return normal;
		}

		// Compute the dot product of two vectors
		float dotProduct(const vector2df& p1, const vector2df& p2)
		{
			return p1.x * p2.x + p1.y * p2.y;
		}

		void NodeShape::setTexture_(const sf::Texture* texture, bool resetRect)
		{
			if (texture)
			{
				// Recompute the texture area if requested, or if there was no texture & rect before
				if (resetRect || (!m_texture && (m_textureRect == Rects32())))
					setTextureRect(Rects32(0, 0, texture->getSize().x, texture->getSize().y));
			}

			// Assign the new texture
			m_texture = texture;
		}

		const sf::Texture* NodeShape::getTexture() const
		{
			return m_texture;
		}

		void NodeShape::setTextureRect(const Rects32& rect)
		{
			m_textureRect = rect;
			updateTexCoords();
		}

		const Rects32& NodeShape::getTextureRect() const
		{
			return m_textureRect;
		}

		void NodeShape::setColor(const Color& color)
		{
			m_fillColor = color;
			updateFillColors();
		}

		const Color& NodeShape::getFillColor() const
		{
			return m_fillColor;
		}

		Rectf32 NodeShape::getLocalBounds() const
		{
			return m_bounds;
		}

		Rectf32 NodeShape::getGlobalBounds() const
		{
			return getTransform().transformRect(getLocalBounds());
		}

		void NodeShape::update()
		{
			// Get the total number of points of the shape
			std::size_t count = getPointCount();
			if (count < 3)
			{
				m_vertices.resize(0);
				return;
			}

			m_vertices.resize(count + 2); // + 2 for center and repeated first point

			// Position
			for (std::size_t i = 0; i < count; ++i)
				m_vertices[i + 1].position = getPoint(i);
			m_vertices[count + 1].position = m_vertices[1].position;

			// Update the bounding rectangle
			m_vertices[0] = m_vertices[1]; // so that the result of getBounds() is correct
			m_bounds = convert(m_vertices.getBounds());
			// Compute the center and make it the first vertex
			m_vertices[0].position.x = m_bounds.width / 2;
			m_vertices[0].position.y = m_bounds.height / 2;

			// Color
			updateFillColors();

			// Texture coordinates
			updateTexCoords();
		}

		u32 NodeShape::draw(lib::core::Window *window, RenderStates &states)
		{
			auto oldTransformation= states.transform;
			states.transform *= getTransform();

			// Render the inside
			states.texture = m_texture;
			window->draw(m_vertices, convert(states));

			states.transform = oldTransformation;
			return 1;
		}

		void NodeShape::updateFillColors()
		{
			for (std::size_t i = 0; i < m_vertices.getVertexCount(); ++i)
				m_vertices[i].color = m_fillColor;
		}

		void NodeShape::updateTexCoords()
		{
			for (std::size_t i = 0; i < m_vertices.getVertexCount(); ++i)
			{
				float xratio = m_bounds.width > 0 ? (m_vertices[i].position.x - m_bounds.left) / m_bounds.width : 0;
				float yratio = m_bounds.height > 0 ? (m_vertices[i].position.y - m_bounds.top) / m_bounds.height : 0;
				m_vertices[i].texCoords.x = m_textureRect.left + m_textureRect.width * xratio;
				m_vertices[i].texCoords.y = m_textureRect.top + m_textureRect.height * yratio;
			}
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>Build fix for Linux.<commit_after><|endoftext|>


<commit_before>/*
    Copyright (c) 2017-2019 Xavier Leclercq and the wxCharts contributors.

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
*/

#include "WxMath2DFrame.h"
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/charts/wxcharts.h>
#include <cmath>

const int ID_LineChart = 1;
const int ID_StemChart = 2;
const int ID_StepChart = 3;
const int ID_CustomXAxis = 4;
const int ID_CustomYAxis = 5;
const int ID_Grid = 6;

WxMath2DFrame::WxMath2DFrame(const wxString& title)
    : wxFrame(NULL, wxID_ANY, title)
{
    m_menubar = new wxMenuBar( 0 );
    m_typeMenu = new wxMenu();
    wxMenuItem* m_line = new wxMenuItem( m_typeMenu, ID_LineChart, wxString( wxT("Line") ), wxEmptyString, wxITEM_RADIO );
    m_typeMenu->Append( m_line );

    wxMenuItem* m_stem = new wxMenuItem( m_typeMenu, ID_StemChart, wxString( wxT("Stem") ), wxEmptyString, wxITEM_RADIO );
    m_typeMenu->Append( m_stem );

    wxMenuItem* m_step = new wxMenuItem( m_typeMenu, ID_StepChart, wxString( wxT("Step") ), wxEmptyString, wxITEM_RADIO );
    m_typeMenu->Append( m_step );

    m_menubar->Append( m_typeMenu, wxT("ChartType") );

    m_axisMenu = new wxMenu();

    wxMenuItem* m_customX = new wxMenuItem( m_axisMenu, ID_CustomXAxis, wxString( wxT("CustomX(exp)") ), wxEmptyString, wxITEM_CHECK );
    m_axisMenu->Append( m_customX );

    wxMenuItem* m_customY = new wxMenuItem( m_axisMenu, ID_CustomYAxis, wxString( wxT("CustomY(exp)") ), wxEmptyString, wxITEM_CHECK );
    m_axisMenu->Append( m_customY );

    m_menubar->Append( m_axisMenu, wxT("AxisType") );

    m_gridMenu = new wxMenu();
    wxMenuItem* m_grid = new wxMenuItem( m_gridMenu, ID_Grid, wxString( wxT("Grid") ), wxEmptyString, wxITEM_CHECK );
    m_grid->Check( true );
    m_gridMenu->Append( m_grid );

    m_menubar->Append( m_gridMenu, wxT("Grid") );
    this->SetMenuBar( m_menubar );

    wxPanel* panel = new wxPanel(this, wxID_ANY);

    wxMath2DPlotData chartData;
    wxMath2DPlotOptions options;
    options.GetCommonOptions().SetShowTooltips(false);

    wxVector<wxPoint2DDouble> points;
    auto pi = 3.1415926535897;
    auto tstart = -2*pi;
    for(auto i = 0u; i<100; i++)
    {
        auto x = tstart+0.1*i;
        points.push_back(wxPoint2DDouble(x,cos(x)*sin(x)));
    }

    wxMath2DPlotDataset::ptr dataset(
        new wxMath2DPlotDataset(
            wxColor(255, 255, 255, 0),
            wxColor(250, 20, 20, 0x78),
            wxColor(0, 0, 0, 0xB8),
            points)
    );
    chartData.AddDataset(dataset);

    math2dPlotCtrl = new wxMath2DPlotCtrl(panel, wxID_ANY, chartData, options);
    wxChartGridOptions opt = math2dPlotCtrl->GetGridOptions();
    opt.GetHorizontalGridLineOptions().SetMajorGridLineColor(wxColour("Grey"));
    opt.GetVerticalGridLineOptions().SetMajorGridLineColor(wxColour("Grey"));
    math2dPlotCtrl->SetGridOptions(opt);

    wxBoxSizer* panelSizer = new wxBoxSizer(wxHORIZONTAL);
    panelSizer->Add(math2dPlotCtrl, 1, wxEXPAND);
    panel->SetSizer(panelSizer);

    wxBoxSizer* topSizer = new wxBoxSizer(wxHORIZONTAL);
    topSizer->Add(panel, 1, wxEXPAND);
    SetSizerAndFit(topSizer);

    Binds();
}

void WxMath2DFrame::Binds()
{
    m_gridMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        auto opt = math2dPlotCtrl->GetGridOptions();
        opt.SetShowGridLines(m_gridMenu->IsChecked(ID_Grid));
        math2dPlotCtrl->SetGridOptions(opt);
    }, ID_Grid);

    m_axisMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        auto opt = math2dPlotCtrl->GetChartOptions();
        if (m_axisMenu->IsChecked(ID_CustomXAxis))
            opt.SetAxisFuncX([](wxDouble x){return std::exp(x);});
        else
            opt.SetAxisFuncX([](wxDouble x){return x;});
        math2dPlotCtrl->SetChartOptions(opt);
    }, ID_CustomXAxis);
    m_axisMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        auto opt = math2dPlotCtrl->GetChartOptions();
        if (m_axisMenu->IsChecked(ID_CustomYAxis))
            opt.SetAxisFuncY([](wxDouble x){return std::exp(x);});
        else
            opt.SetAxisFuncY([](wxDouble x){return x;});
        math2dPlotCtrl->SetChartOptions(opt);
    }, ID_CustomYAxis);
    m_typeMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        math2dPlotCtrl->SetChartType(0,wxCHARTTYPE_LINE);
    }, ID_LineChart);
    m_typeMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        math2dPlotCtrl->SetChartType(0,wxCHARTTYPE_STEPPED);
    }, ID_StepChart);
    m_typeMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        math2dPlotCtrl->SetChartType(0,wxCHARTTYPE_STEM);
    }, ID_StemChart);
}
<commit_msg>Fix test compilation<commit_after>/*
    Copyright (c) 2017-2019 Xavier Leclercq and the wxCharts contributors.

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
*/

#include "WxMath2DFrame.h"
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/charts/wxcharts.h>
#include <cmath>

const int ID_LineChart = 1;
const int ID_StemChart = 2;
const int ID_StepChart = 3;
const int ID_CustomXAxis = 4;
const int ID_CustomYAxis = 5;
const int ID_Grid = 6;

WxMath2DFrame::WxMath2DFrame(const wxString& title)
    : wxFrame(NULL, wxID_ANY, title)
{
    m_menubar = new wxMenuBar( 0 );
    m_typeMenu = new wxMenu();
    wxMenuItem* m_line = new wxMenuItem( m_typeMenu, ID_LineChart, wxString( wxT("Line") ), wxEmptyString, wxITEM_RADIO );
    m_typeMenu->Append( m_line );

    wxMenuItem* m_stem = new wxMenuItem( m_typeMenu, ID_StemChart, wxString( wxT("Stem") ), wxEmptyString, wxITEM_RADIO );
    m_typeMenu->Append( m_stem );

    wxMenuItem* m_step = new wxMenuItem( m_typeMenu, ID_StepChart, wxString( wxT("Step") ), wxEmptyString, wxITEM_RADIO );
    m_typeMenu->Append( m_step );

    m_menubar->Append( m_typeMenu, wxT("ChartType") );

    m_axisMenu = new wxMenu();

    wxMenuItem* m_customX = new wxMenuItem( m_axisMenu, ID_CustomXAxis, wxString( wxT("CustomX(exp)") ), wxEmptyString, wxITEM_CHECK );
    m_axisMenu->Append( m_customX );

    wxMenuItem* m_customY = new wxMenuItem( m_axisMenu, ID_CustomYAxis, wxString( wxT("CustomY(exp)") ), wxEmptyString, wxITEM_CHECK );
    m_axisMenu->Append( m_customY );

    m_menubar->Append( m_axisMenu, wxT("AxisType") );

    m_gridMenu = new wxMenu();
    wxMenuItem* m_grid = new wxMenuItem( m_gridMenu, ID_Grid, wxString( wxT("Grid") ), wxEmptyString, wxITEM_CHECK );
    m_grid->Check( true );
    m_gridMenu->Append( m_grid );

    m_menubar->Append( m_gridMenu, wxT("Grid") );
    this->SetMenuBar( m_menubar );

    wxPanel* panel = new wxPanel(this, wxID_ANY);

    wxMath2DPlotData chartData;
    wxSharedPtr<wxMath2DPlotOptions> options(new wxMath2DPlotOptions());
    options->GetCommonOptions().SetShowTooltips(false);

    wxVector<wxPoint2DDouble> points;
    auto pi = 3.1415926535897;
    auto tstart = -2*pi;
    for(auto i = 0u; i<100; i++)
    {
        auto x = tstart+0.1*i;
        points.push_back(wxPoint2DDouble(x,cos(x)*sin(x)));
    }

    wxMath2DPlotDataset::ptr dataset(
        new wxMath2DPlotDataset(
            wxColor(255, 255, 255, 0),
            wxColor(250, 20, 20, 0x78),
            wxColor(0, 0, 0, 0xB8),
            points)
    );
    chartData.AddDataset(dataset);

    math2dPlotCtrl = new wxMath2DPlotCtrl(panel, wxID_ANY, chartData, options);
    wxChartGridOptions opt = math2dPlotCtrl->GetGridOptions();
    opt.GetHorizontalGridLineOptions().SetMajorGridLineColor(wxColour("Grey"));
    opt.GetVerticalGridLineOptions().SetMajorGridLineColor(wxColour("Grey"));
    math2dPlotCtrl->SetGridOptions(opt);

    wxBoxSizer* panelSizer = new wxBoxSizer(wxHORIZONTAL);
    panelSizer->Add(math2dPlotCtrl, 1, wxEXPAND);
    panel->SetSizer(panelSizer);

    wxBoxSizer* topSizer = new wxBoxSizer(wxHORIZONTAL);
    topSizer->Add(panel, 1, wxEXPAND);
    SetSizerAndFit(topSizer);

    Binds();
}

void WxMath2DFrame::Binds()
{
    m_gridMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        auto opt = math2dPlotCtrl->GetGridOptions();
        opt.SetShowGridLines(m_gridMenu->IsChecked(ID_Grid));
        math2dPlotCtrl->SetGridOptions(opt);
    }, ID_Grid);

    m_axisMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        auto opt = math2dPlotCtrl->GetChartOptions();
        if (m_axisMenu->IsChecked(ID_CustomXAxis))
            opt.SetAxisFuncX([](wxDouble x){return std::exp(x);});
        else
            opt.SetAxisFuncX([](wxDouble x){return x;});
        math2dPlotCtrl->SetChartOptions(opt);
    }, ID_CustomXAxis);
    m_axisMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        auto opt = math2dPlotCtrl->GetChartOptions();
        if (m_axisMenu->IsChecked(ID_CustomYAxis))
            opt.SetAxisFuncY([](wxDouble x){return std::exp(x);});
        else
            opt.SetAxisFuncY([](wxDouble x){return x;});
        math2dPlotCtrl->SetChartOptions(opt);
    }, ID_CustomYAxis);
    m_typeMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        math2dPlotCtrl->SetChartType(0,wxCHARTTYPE_LINE);
    }, ID_LineChart);
    m_typeMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        math2dPlotCtrl->SetChartType(0,wxCHARTTYPE_STEPPED);
    }, ID_StepChart);
    m_typeMenu->Bind(wxEVT_COMMAND_MENU_SELECTED,[&](wxCommandEvent &)
    {
        math2dPlotCtrl->SetChartType(0,wxCHARTTYPE_STEM);
    }, ID_StemChart);
}
<|endoftext|>


<commit_before>#pragma once

#include "terminalpp/detail/export.hpp"
#include <boost/cstdint.hpp>

namespace terminalpp {

typedef boost::int8_t  s8;
typedef boost::int16_t s16;
typedef boost::int32_t s32;
typedef boost::int64_t s64;

typedef boost::uint8_t  u8;
typedef boost::uint16_t u16;
typedef boost::uint32_t u32;
typedef boost::uint64_t u64;

}
<commit_msg>Included cstddef in core.hpp (#146)<commit_after>#pragma once

#include "terminalpp/detail/export.hpp"
#include <cstddef>
#include <boost/cstdint.hpp>

namespace terminalpp {

typedef boost::int8_t  s8;
typedef boost::int16_t s16;
typedef boost::int32_t s32;
typedef boost::int64_t s64;

typedef boost::uint8_t  u8;
typedef boost::uint16_t u16;
typedef boost::uint32_t u32;
typedef boost::uint64_t u64;

}
<|endoftext|>


<commit_before>#include "libcpu.h"
#include "frontend.h"
#include "arm_internal.h"
#include "tag.h"

using namespace llvm;

#define ptr_N			((ccarm_t*)cpu->feptr)->ptr_N
#define ptr_Z			((ccarm_t*)cpu->feptr)->ptr_Z
#define ptr_C			((ccarm_t*)cpu->feptr)->ptr_C
#define ptr_V			((ccarm_t*)cpu->feptr)->ptr_V
#define ptr_I			((ccarm_t*)cpu->feptr)->ptr_I
#define ptr_CPSR	cpu->ptr_xr[0]

#define BAD do { printf("%s:%d\n", __func__, __LINE__); exit(1); } while(0)
#define LOG do { log("%s:%d\n", __func__, __LINE__); } while(0)

#define ARM_BRANCH_TARGET ((((int)BITS(0,23) << 8) >> 6) + pc + 8)

#define RD ((instr >> 12) & 0xF)
#define RN ((instr >> 16) & 0xF)
#define RM (instr & 0xF)
#define I ((instr >> 25) & 1)
#define BIT(n) ((instr >> (n)) & 1)
#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1))
#define S BIT(20)

#define GETADDR(r) ((r==15)?(armregs[15]&r15mask):armregs[r])

//////////////////////////////////////////////////////////////////////
// tagging
//////////////////////////////////////////////////////////////////////

int arch_arm_tag_instr(cpu_t *cpu, addr_t pc, tag_t *tag, addr_t *new_pc, addr_t *next_pc) {
	uint32_t instr = *(uint32_t*)&cpu->RAM[pc];

	if (instr == 0xE1A0F00E) /* MOV r15, r0, r14 */
		*tag = TAG_RET;
	else if (BITS(24,27) == 10) { /* branch */
		*new_pc = ARM_BRANCH_TARGET;
		*tag = TAG_BRANCH;
	} else if (BITS(24,27) == 11) { /* branch and link */
		*new_pc = ARM_BRANCH_TARGET;
		*tag = TAG_CALL;
	} else
		*tag = TAG_CONTINUE;

	if (instr >> 28 != 0xE)
		*tag |= TAG_CONDITIONAL;

	*next_pc = pc + 4;
	return 4;
}

static inline unsigned shift4(unsigned opcode)
{
	BAD;
#if 0
        unsigned shiftmode=opcode&0x60;
        unsigned shiftamount=(opcode&0x10)?(armregs[(opcode>>8)&15]&0xFF):((opcode>>7)&31);
        uint32_t rm=armregs[RM];
        if ((shiftamount-1)>=31)
        {
                return shift5(opcode,shiftmode,shiftamount,rm);
        }
        else
        {
                switch (shiftmode)
                {
                        case 0: /*LSL*/
                        return rm<<shiftamount;
                        case 0x20: /*LSR*/
                        return rm>>shiftamount;
                        case 0x40: /*ASR*/
                        return (int)rm>>shiftamount;
                        default: /*ROR*/
                        return (rm>>shiftamount)|(rm<<(32-shiftamount));
                }
        }
#endif
}

#define shift2(o) ((o&0xFF0)?shift4(o):armregs[RM])

Value *
arch_arm_translate_cond(cpu_t *cpu, addr_t pc, BasicBlock *bb) {
	switch (*(uint32_t*)&cpu->RAM[pc] >> 28) {
		case 0x0: /* EQ */
			return LOAD(ptr_Z);
		case 0x1: /* NE */
			return NOT(LOAD(ptr_Z));
		case 0x2: /* CS */
			return LOAD(ptr_C);
		case 0x3: /* CC */
			return NOT(LOAD(ptr_C));
		case 0x4: /* MI */
			return LOAD(ptr_N);
		case 0x5: /* PL */
			return NOT(LOAD(ptr_N));
		case 0x6: /* VS */
			return LOAD(ptr_V);
		case 0x7: /* VC */
			return NOT(LOAD(ptr_V));
		case 0x8: /* HI */
			return AND(LOAD(ptr_C),NOT(LOAD(ptr_Z)));
		case 0x9: /* LS */
			return NOT(AND(LOAD(ptr_C),NOT(LOAD(ptr_Z))));
		case 0xA: /* GE */
			return ICMP_EQ(LOAD(ptr_N),LOAD(ptr_V));
		case 0xB: /* LT */
			return NOT(ICMP_EQ(LOAD(ptr_N),LOAD(ptr_V)));
		case 0xC: /* GT */
			return AND(NOT(LOAD(ptr_Z)),ICMP_EQ(LOAD(ptr_N),LOAD(ptr_V)));
		case 0xD: /* LE */
			return NOT(AND(NOT(LOAD(ptr_Z)),ICMP_EQ(LOAD(ptr_N),LOAD(ptr_V))));
		case 0xE: /* AL */
			return NULL; /* no condition; this should never happen */
		case 0xF: /* NV */
			return FALSE;
		default:
			assert(0 && "Cannot happen");
      return FALSE;
	}
}

Value *operand(cpu_t *cpu, addr_t pc, BasicBlock *bb)
{
	uint32_t instr = *(uint32_t*)&cpu->RAM[pc];
	if (I) { /* 32-bit immediate */
		//XXX TODO: shifter carry out
		uint32_t immed_8 = instr & 0xFF;
		int rotate_imm = ((instr >> 8) & 0xF) << 1;
		return CONST((immed_8 >> rotate_imm) | (immed_8 << (32 - rotate_imm)));
	} else {
		if (!BIT(4)) { /* Immediate shifts */
			int shift = BITS(5,6);
			int shift_imm = BITS(7,11);
			log("shift=%x\n", shift);
			log("shift_imm=%x\n", shift_imm);
			if (!shift && !shift_imm) { /* Register */
				return R(RM);
			} else {
				BAD;
			}
		} else {
			if (!BIT(7)) { /* Register shifts */
				BAD;
			} else { /* arithmetic or Load/Store instruction extension space */
				BAD;
			}
		}
	}
}
#define OPERAND operand(cpu,pc,bb)

static void
setsub(cpu_t *cpu, Value *op1, Value *op2, BasicBlock *bb)
{
	Value *v = BinaryOperator::Create(Instruction::Sub, op1, op2, "", bb);
	/* Z */	new StoreInst(ICMP_EQ(v, CONST(0)), ptr_Z, bb);
	/* N */	new StoreInst(ICMP_SLT(v, CONST(0)), ptr_N, bb);
	/* C */	new StoreInst(ICMP_SLE(v, op1), ptr_C, false, bb);
	/* V */	new StoreInst(TRUNC1(LSHR(AND(XOR(op1, op2),XOR(op1,v)),CONST(31))), ptr_V, false, bb);
	return;
}

#define LET1(a,b) new StoreInst(b, a, false, bb)

#define SET_NZ(a) { Value *t = a; LET1(ptr_Z, ICMP_EQ(t, CONST(0))); LET1(ptr_N, ICMP_SLT(t, CONST(0))); }

#define COMPUTE_CARRY(src1, src2, result) \
	(AND(ICMP_NE(src2, CONST(0)), ICMP_ULT(result, src1)))

#define LINK LET32(14, CONST((uint64_t)(sint64_t)(sint32_t)pc+8))

int arch_arm_translate_instr(cpu_t *cpu, addr_t pc, BasicBlock *bb) {
log("%s:%d pc=%llx\n", __func__, __LINE__, pc);
	uint32_t instr = *(uint32_t*)&cpu->RAM[pc];

//	int cond = instr >> 28;
//	int op1 = (instr>>20)&0xFF;
//	int op2 = (instr>>4)&0xF;
//	int shift_bits = (instr>>4)&0xFF;
//	log("cond=%x, op1=%x, op2=%x, shift_bits=%x\n", cond, op1, op2, shift_bits);

	int opcode = ((instr >> 21) & 0x0F);
	log("opcode=%d\n", opcode);

	switch ((instr >> 26) & 3) { /* bits 26 and 27 */
		case 0:
			switch(opcode) {
				case 2:
					{
						Value *op1 = R(RN);
						Value *op2 = OPERAND;
						Value *res = SUB(op1,op2);
						LET(RD, res);
						if (S) {
							BAD;
							//XXX TODO overflow!
						}
					}
				case 4: /* ADD */
					{
						Value *op1 = R(RN);
						Value *op2 = OPERAND;
						Value *res = ADD(op1,op2);
						LET(RD, res);
						if (S) {
							SET_NZ(res);
							LET1(ptr_C, COMPUTE_CARRY(op1, op2, res));
							BAD;
							//XXX TODO overflow!
						}
					}
					break;
				case 10: /* CMP */
					if (!S) /* CMP without S bit */
						BAD;
					setsub(cpu, R(RN), OPERAND, bb);
					break;
				case 13: /* MOV */
					if (S)
						BAD;
					if (RD == 15) {
						new StoreInst(SUB(R(14),CONST(4)), cpu->ptr_PC, bb);
						break;
					}
					LET(RD, OPERAND);
					break;
				default:
					BAD;
			}
			break;
		case 1:
			BAD;
		case 2:
			if (BIT(25)) {
				if (BIT(24))
					LINK;
				break;
			} else { /* LDM/STM */
				if (BIT(20))
					BAD;		/* LDM */
				if (BIT(22))	/* S bit */
					BAD;		/* trying to CPSR form SPSR */
				if (!BITS(0,15))
					BAD;		/* unpredictable */

				if (BIT(20))
					BAD;		/* LDM */

				int i;
				Value *addr = R(RN);
				for (i = 0; i <= 15; i++) {
					if (BIT(i)) {
						if (BIT(24)) /* before */
							if (BIT(23)) /* increment */
								addr = ADD(addr,CONST(4));
							else
								addr = SUB(addr,CONST(4));
						STORE32(R(i),addr);
						if (!BIT(24)) /* after */
							if (BIT(23)) /* increment */
								addr = ADD(addr,CONST(4));
							else
								addr = SUB(addr,CONST(4));
					}
				}
				if (BIT(21))	/* W (1 = write back register) */
					LET(RN, addr);
				break;
			}
		case 3:
			BAD;

	}

	LOG;
	return 4;
}

#define N_SHIFT 31
#define Z_SHIFT 30
#define C_SHIFT 29
#define V_SHIFT 28
#define I_SHIFT 27

static Value *
arch_arm_flags_encode(cpu_t *cpu, BasicBlock *bb)
{
	Value *flags = ConstantInt::get(getIntegerType(32), 0);

	flags = arch_encode_bit(flags, ptr_N, N_SHIFT, 32, bb);
	flags = arch_encode_bit(flags, ptr_Z, Z_SHIFT, 32, bb);
	flags = arch_encode_bit(flags, ptr_C, C_SHIFT, 32, bb);
	flags = arch_encode_bit(flags, ptr_V, V_SHIFT, 32, bb);
	flags = arch_encode_bit(flags, ptr_I, I_SHIFT, 32, bb);

	return flags;
}

static void
arch_arm_flags_decode(cpu_t *cpu, Value *flags, BasicBlock *bb)
{
	arch_decode_bit(flags, ptr_N, N_SHIFT, 32, bb);
	arch_decode_bit(flags, ptr_Z, Z_SHIFT, 32, bb);
	arch_decode_bit(flags, ptr_C, C_SHIFT, 32, bb);
	arch_decode_bit(flags, ptr_V, V_SHIFT, 32, bb);
	arch_decode_bit(flags, ptr_I, I_SHIFT, 32, bb);
}

void
arch_arm_emit_decode_reg(cpu_t *cpu, BasicBlock *bb)
{
	// declare flags
	ptr_N = new AllocaInst(getIntegerType(1), "N", bb);
	ptr_Z = new AllocaInst(getIntegerType(1), "Z", bb);
	ptr_C = new AllocaInst(getIntegerType(1), "C", bb);
	ptr_V = new AllocaInst(getIntegerType(1), "V", bb);
	ptr_I = new AllocaInst(getIntegerType(1), "I", bb);

	// decode CPSR
	Value *flags = new LoadInst(ptr_CPSR, "", false, bb);
	arch_arm_flags_decode(cpu, flags, bb);
}

void
arch_arm_spill_reg_state(cpu_t *cpu, BasicBlock *bb)
{
	Value *flags = arch_arm_flags_encode(cpu, bb);
	new StoreInst(flags, ptr_CPSR, false, bb);
}
//printf("%s:%d PC=$%04X\n", __func__, __LINE__, pc);
//printf("%s:%d\n", __func__, __LINE__);
<commit_msg>arm: disambiguate if/else to make gcc happy.<commit_after>#include "libcpu.h"
#include "frontend.h"
#include "arm_internal.h"
#include "tag.h"

using namespace llvm;

#define ptr_N			((ccarm_t*)cpu->feptr)->ptr_N
#define ptr_Z			((ccarm_t*)cpu->feptr)->ptr_Z
#define ptr_C			((ccarm_t*)cpu->feptr)->ptr_C
#define ptr_V			((ccarm_t*)cpu->feptr)->ptr_V
#define ptr_I			((ccarm_t*)cpu->feptr)->ptr_I
#define ptr_CPSR	cpu->ptr_xr[0]

#define BAD do { printf("%s:%d\n", __func__, __LINE__); exit(1); } while(0)
#define LOG do { log("%s:%d\n", __func__, __LINE__); } while(0)

#define ARM_BRANCH_TARGET ((((int)BITS(0,23) << 8) >> 6) + pc + 8)

#define RD ((instr >> 12) & 0xF)
#define RN ((instr >> 16) & 0xF)
#define RM (instr & 0xF)
#define I ((instr >> 25) & 1)
#define BIT(n) ((instr >> (n)) & 1)
#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1))
#define S BIT(20)

#define GETADDR(r) ((r==15)?(armregs[15]&r15mask):armregs[r])

//////////////////////////////////////////////////////////////////////
// tagging
//////////////////////////////////////////////////////////////////////

int arch_arm_tag_instr(cpu_t *cpu, addr_t pc, tag_t *tag, addr_t *new_pc, addr_t *next_pc) {
	uint32_t instr = *(uint32_t*)&cpu->RAM[pc];

	if (instr == 0xE1A0F00E) /* MOV r15, r0, r14 */
		*tag = TAG_RET;
	else if (BITS(24,27) == 10) { /* branch */
		*new_pc = ARM_BRANCH_TARGET;
		*tag = TAG_BRANCH;
	} else if (BITS(24,27) == 11) { /* branch and link */
		*new_pc = ARM_BRANCH_TARGET;
		*tag = TAG_CALL;
	} else
		*tag = TAG_CONTINUE;

	if (instr >> 28 != 0xE)
		*tag |= TAG_CONDITIONAL;

	*next_pc = pc + 4;
	return 4;
}

static inline unsigned shift4(unsigned opcode)
{
	BAD;
#if 0
        unsigned shiftmode=opcode&0x60;
        unsigned shiftamount=(opcode&0x10)?(armregs[(opcode>>8)&15]&0xFF):((opcode>>7)&31);
        uint32_t rm=armregs[RM];
        if ((shiftamount-1)>=31)
        {
                return shift5(opcode,shiftmode,shiftamount,rm);
        }
        else
        {
                switch (shiftmode)
                {
                        case 0: /*LSL*/
                        return rm<<shiftamount;
                        case 0x20: /*LSR*/
                        return rm>>shiftamount;
                        case 0x40: /*ASR*/
                        return (int)rm>>shiftamount;
                        default: /*ROR*/
                        return (rm>>shiftamount)|(rm<<(32-shiftamount));
                }
        }
#endif
}

#define shift2(o) ((o&0xFF0)?shift4(o):armregs[RM])

Value *
arch_arm_translate_cond(cpu_t *cpu, addr_t pc, BasicBlock *bb) {
	switch (*(uint32_t*)&cpu->RAM[pc] >> 28) {
		case 0x0: /* EQ */
			return LOAD(ptr_Z);
		case 0x1: /* NE */
			return NOT(LOAD(ptr_Z));
		case 0x2: /* CS */
			return LOAD(ptr_C);
		case 0x3: /* CC */
			return NOT(LOAD(ptr_C));
		case 0x4: /* MI */
			return LOAD(ptr_N);
		case 0x5: /* PL */
			return NOT(LOAD(ptr_N));
		case 0x6: /* VS */
			return LOAD(ptr_V);
		case 0x7: /* VC */
			return NOT(LOAD(ptr_V));
		case 0x8: /* HI */
			return AND(LOAD(ptr_C),NOT(LOAD(ptr_Z)));
		case 0x9: /* LS */
			return NOT(AND(LOAD(ptr_C),NOT(LOAD(ptr_Z))));
		case 0xA: /* GE */
			return ICMP_EQ(LOAD(ptr_N),LOAD(ptr_V));
		case 0xB: /* LT */
			return NOT(ICMP_EQ(LOAD(ptr_N),LOAD(ptr_V)));
		case 0xC: /* GT */
			return AND(NOT(LOAD(ptr_Z)),ICMP_EQ(LOAD(ptr_N),LOAD(ptr_V)));
		case 0xD: /* LE */
			return NOT(AND(NOT(LOAD(ptr_Z)),ICMP_EQ(LOAD(ptr_N),LOAD(ptr_V))));
		case 0xE: /* AL */
			return NULL; /* no condition; this should never happen */
		case 0xF: /* NV */
			return FALSE;
		default:
			assert(0 && "Cannot happen");
      return FALSE;
	}
}

Value *operand(cpu_t *cpu, addr_t pc, BasicBlock *bb)
{
	uint32_t instr = *(uint32_t*)&cpu->RAM[pc];
	if (I) { /* 32-bit immediate */
		//XXX TODO: shifter carry out
		uint32_t immed_8 = instr & 0xFF;
		int rotate_imm = ((instr >> 8) & 0xF) << 1;
		return CONST((immed_8 >> rotate_imm) | (immed_8 << (32 - rotate_imm)));
	} else {
		if (!BIT(4)) { /* Immediate shifts */
			int shift = BITS(5,6);
			int shift_imm = BITS(7,11);
			log("shift=%x\n", shift);
			log("shift_imm=%x\n", shift_imm);
			if (!shift && !shift_imm) { /* Register */
				return R(RM);
			} else {
				BAD;
			}
		} else {
			if (!BIT(7)) { /* Register shifts */
				BAD;
			} else { /* arithmetic or Load/Store instruction extension space */
				BAD;
			}
		}
	}
}
#define OPERAND operand(cpu,pc,bb)

static void
setsub(cpu_t *cpu, Value *op1, Value *op2, BasicBlock *bb)
{
	Value *v = BinaryOperator::Create(Instruction::Sub, op1, op2, "", bb);
	/* Z */	new StoreInst(ICMP_EQ(v, CONST(0)), ptr_Z, bb);
	/* N */	new StoreInst(ICMP_SLT(v, CONST(0)), ptr_N, bb);
	/* C */	new StoreInst(ICMP_SLE(v, op1), ptr_C, false, bb);
	/* V */	new StoreInst(TRUNC1(LSHR(AND(XOR(op1, op2),XOR(op1,v)),CONST(31))), ptr_V, false, bb);
	return;
}

#define LET1(a,b) new StoreInst(b, a, false, bb)

#define SET_NZ(a) { Value *t = a; LET1(ptr_Z, ICMP_EQ(t, CONST(0))); LET1(ptr_N, ICMP_SLT(t, CONST(0))); }

#define COMPUTE_CARRY(src1, src2, result) \
	(AND(ICMP_NE(src2, CONST(0)), ICMP_ULT(result, src1)))

#define LINK LET32(14, CONST((uint64_t)(sint64_t)(sint32_t)pc+8))

int arch_arm_translate_instr(cpu_t *cpu, addr_t pc, BasicBlock *bb) {
log("%s:%d pc=%llx\n", __func__, __LINE__, pc);
	uint32_t instr = *(uint32_t*)&cpu->RAM[pc];

//	int cond = instr >> 28;
//	int op1 = (instr>>20)&0xFF;
//	int op2 = (instr>>4)&0xF;
//	int shift_bits = (instr>>4)&0xFF;
//	log("cond=%x, op1=%x, op2=%x, shift_bits=%x\n", cond, op1, op2, shift_bits);

	int opcode = ((instr >> 21) & 0x0F);
	log("opcode=%d\n", opcode);

	switch ((instr >> 26) & 3) { /* bits 26 and 27 */
		case 0:
			switch(opcode) {
				case 2:
					{
						Value *op1 = R(RN);
						Value *op2 = OPERAND;
						Value *res = SUB(op1,op2);
						LET(RD, res);
						if (S) {
							BAD;
							//XXX TODO overflow!
						}
					}
				case 4: /* ADD */
					{
						Value *op1 = R(RN);
						Value *op2 = OPERAND;
						Value *res = ADD(op1,op2);
						LET(RD, res);
						if (S) {
							SET_NZ(res);
							LET1(ptr_C, COMPUTE_CARRY(op1, op2, res));
							BAD;
							//XXX TODO overflow!
						}
					}
					break;
				case 10: /* CMP */
					if (!S) /* CMP without S bit */
						BAD;
					setsub(cpu, R(RN), OPERAND, bb);
					break;
				case 13: /* MOV */
					if (S)
						BAD;
					if (RD == 15) {
						new StoreInst(SUB(R(14),CONST(4)), cpu->ptr_PC, bb);
						break;
					}
					LET(RD, OPERAND);
					break;
				default:
					BAD;
			}
			break;
		case 1:
			BAD;
		case 2:
			if (BIT(25)) {
				if (BIT(24))
					LINK;
				break;
			} else { /* LDM/STM */
				if (BIT(20))
					BAD;		/* LDM */
				if (BIT(22))	/* S bit */
					BAD;		/* trying to CPSR form SPSR */
				if (!BITS(0,15))
					BAD;		/* unpredictable */

				if (BIT(20))
					BAD;		/* LDM */

				int i;
				Value *addr = R(RN);
				for (i = 0; i <= 15; i++) {
					if (BIT(i)) {
						if (BIT(24)) { /* before */
							if (BIT(23)) /* increment */
								addr = ADD(addr,CONST(4));
							else
								addr = SUB(addr,CONST(4));
						}
						STORE32(R(i),addr);
						if (!BIT(24)) { /* after */
							if (BIT(23)) /* increment */
								addr = ADD(addr,CONST(4));
							else
								addr = SUB(addr,CONST(4));
						}
					}
				}
				if (BIT(21))	/* W (1 = write back register) */
					LET(RN, addr);
				break;
			}
		case 3:
			BAD;

	}

	LOG;
	return 4;
}

#define N_SHIFT 31
#define Z_SHIFT 30
#define C_SHIFT 29
#define V_SHIFT 28
#define I_SHIFT 27

static Value *
arch_arm_flags_encode(cpu_t *cpu, BasicBlock *bb)
{
	Value *flags = ConstantInt::get(getIntegerType(32), 0);

	flags = arch_encode_bit(flags, ptr_N, N_SHIFT, 32, bb);
	flags = arch_encode_bit(flags, ptr_Z, Z_SHIFT, 32, bb);
	flags = arch_encode_bit(flags, ptr_C, C_SHIFT, 32, bb);
	flags = arch_encode_bit(flags, ptr_V, V_SHIFT, 32, bb);
	flags = arch_encode_bit(flags, ptr_I, I_SHIFT, 32, bb);

	return flags;
}

static void
arch_arm_flags_decode(cpu_t *cpu, Value *flags, BasicBlock *bb)
{
	arch_decode_bit(flags, ptr_N, N_SHIFT, 32, bb);
	arch_decode_bit(flags, ptr_Z, Z_SHIFT, 32, bb);
	arch_decode_bit(flags, ptr_C, C_SHIFT, 32, bb);
	arch_decode_bit(flags, ptr_V, V_SHIFT, 32, bb);
	arch_decode_bit(flags, ptr_I, I_SHIFT, 32, bb);
}

void
arch_arm_emit_decode_reg(cpu_t *cpu, BasicBlock *bb)
{
	// declare flags
	ptr_N = new AllocaInst(getIntegerType(1), "N", bb);
	ptr_Z = new AllocaInst(getIntegerType(1), "Z", bb);
	ptr_C = new AllocaInst(getIntegerType(1), "C", bb);
	ptr_V = new AllocaInst(getIntegerType(1), "V", bb);
	ptr_I = new AllocaInst(getIntegerType(1), "I", bb);

	// decode CPSR
	Value *flags = new LoadInst(ptr_CPSR, "", false, bb);
	arch_arm_flags_decode(cpu, flags, bb);
}

void
arch_arm_spill_reg_state(cpu_t *cpu, BasicBlock *bb)
{
	Value *flags = arch_arm_flags_encode(cpu, bb);
	new StoreInst(flags, ptr_CPSR, false, bb);
}
//printf("%s:%d PC=$%04X\n", __func__, __LINE__, pc);
//printf("%s:%d\n", __func__, __LINE__);
<|endoftext|>


<commit_before>//============================================================================
// vSMC/include/vsmc/math/cblas.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2016, Yan Zhou
// 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.
//
// 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.
//============================================================================

#ifndef VSMC_MATH_CBLAS_HPP
#define VSMC_MATH_CBLAS_HPP

#include <vsmc/internal/config.h>
#include <vsmc/internal/defines.hpp>
#include <algorithm>
#include <cmath>
#include <numeric>

#if VSMC_HAS_MKL
#include <mkl.h>
#define VSMC_CBLAS_INT MKL_INT
#else
#include <cblas.h>
#ifndef VSMC_CBLAS_INT
#define VSMC_CBLAS_INT int
#endif
#endif

#endif // VSMC_MATH_CBLAS_HPP
<commit_msg>remove unused headers<commit_after>//============================================================================
// vSMC/include/vsmc/math/cblas.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2016, Yan Zhou
// 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.
//
// 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.
//============================================================================

#ifndef VSMC_MATH_CBLAS_HPP
#define VSMC_MATH_CBLAS_HPP

#include <vsmc/internal/config.h>

#if VSMC_HAS_MKL
#include <mkl.h>
#define VSMC_CBLAS_INT MKL_INT
#else
#include <cblas.h>
#ifndef VSMC_CBLAS_INT
#define VSMC_CBLAS_INT int
#endif
#endif

#endif // VSMC_MATH_CBLAS_HPP
<|endoftext|>


<commit_before>/*
 *  This file is parte of grammargen. A tool to generate sequences of
 *  characters from a given grammar.
 *  Copyright (C) 2015 Raphael Santos, http://www.raphaelss.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef GRAMMAR_HPP_INCLUDED
#define GRAMMAR_HPP_INCLUDED

#include <random>
#include <unordered_map>
#include <vector>

#include "branched_seq.hpp"

/*
namespace impl {
template <class T>
constexpr const T &get(const T &x) {
  return x;
}

template <class T>
const T &get(
}
*/

template <class T>
class Grammar {
public:
  Grammar(T axiom): _axiom(axiom), rules() {}

  void add_rule(T lhs, branched_seq<T> rhs, double prob) {
    rules[std::move(lhs)].addClause(std::move(rhs), prob);
  }

  template <class Rndgen>
  const branched_seq<T>& operator()(const T &ch, Rndgen &rndgen) {
    return rules.at(ch).choose(distr, rndgen);
  }

  bool has_rule(const T &x) const {
    return rules.count(x);
  }

  template <class Rndgen, class Op>
  void apply_rule(unsigned k, const T &x, Rndgen &rndgen, Op &op) {
    if (has_rule(x)) {
      const auto &seq = operator()(x, rndgen);
      if (--k) {
        for (const auto &elem : seq) {
          apply_rule(k, boost::get<T>(elem), rndgen, op);
        }
      } else {
        for (const auto &elem : seq) {
          op(boost::get<T>(elem));
        }
      }
    } else {
      op(x);
    }
  }

  template <class Rndgen, class Op>
  void gen_seq(unsigned k, Rndgen &rndgen, Op op = Op()) {
    if (k) {
      apply_rule(k, _axiom, rndgen, op);
      return;
    }
    op(_axiom);
  }

private:
  struct Rule {
    void addClause(branched_seq<T> str, double prob=1) {
      clauses.emplace_back(std::move(str));
      probs.emplace_back(prob);
    }

    template <class Rndgen>
    const branched_seq<T>& choose(
        std::discrete_distribution<unsigned>& distr, Rndgen& rndgen)
    {
      if (clauses.size() == 1) {
        return clauses[0];
      }
      distr.param(
          std::discrete_distribution<unsigned>::param_type(probs.cbegin(),
                                                           probs.cend()));
      return clauses[distr(rndgen)];
    }

    std::vector<branched_seq<T>> clauses;
    std::vector<double> probs;
  };

  T _axiom;

  std::unordered_map<T, Rule> rules;
  std::discrete_distribution<unsigned> distr;
};

#endif
<commit_msg>container agnostic (vector or branched_seq) get function<commit_after>/*
 *  This file is parte of grammargen. A tool to generate sequences of
 *  characters from a given grammar.
 *  Copyright (C) 2015 Raphael Santos, http://www.raphaelss.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef GRAMMAR_HPP_INCLUDED
#define GRAMMAR_HPP_INCLUDED

#include <random>
#include <unordered_map>
#include <vector>

#include "branched_seq.hpp"

namespace impl {

template <class T>
constexpr const T &get(const T &x) {
  return x;
}

template <class T>
const T &get(const typename branched_seq<T>::value_type &x) {
  return boost::get<T>(x);
}

}

template <class T>
class Grammar {
public:
  Grammar(T axiom): _axiom(axiom), rules() {}

  void add_rule(T lhs, branched_seq<T> rhs, double prob) {
    rules[std::move(lhs)].addClause(std::move(rhs), prob);
  }

  template <class Rndgen>
  const branched_seq<T>& operator()(const T &ch, Rndgen &rndgen) {
    return rules.at(ch).choose(distr, rndgen);
  }

  bool has_rule(const T &x) const {
    return rules.count(x);
  }

  template <class Rndgen, class Op>
  void apply_rule(unsigned k, const T &x, Rndgen &rndgen, Op &op) {
    if (has_rule(x)) {
      const auto &seq = operator()(x, rndgen);
      if (--k) {
        for (const auto &elem : seq) {
          apply_rule(k, impl::get<T>(elem), rndgen, op);
        }
      } else {
        for (const auto &elem : seq) {
          op(impl::get<T>(elem));
        }
      }
    } else {
      op(x);
    }
  }

  template <class Rndgen, class Op>
  void gen_seq(unsigned k, Rndgen &rndgen, Op op = Op()) {
    if (k) {
      apply_rule(k, _axiom, rndgen, op);
      return;
    }
    op(_axiom);
  }

private:
  struct Rule {
    void addClause(branched_seq<T> str, double prob=1) {
      clauses.emplace_back(std::move(str));
      probs.emplace_back(prob);
    }

    template <class Rndgen>
    const branched_seq<T>& choose(
        std::discrete_distribution<unsigned>& distr, Rndgen& rndgen)
    {
      if (clauses.size() == 1) {
        return clauses[0];
      }
      distr.param(
          std::discrete_distribution<unsigned>::param_type(probs.cbegin(),
                                                           probs.cend()));
      return clauses[distr(rndgen)];
    }

    std::vector<branched_seq<T>> clauses;
    std::vector<double> probs;
  };

  T _axiom;

  std::unordered_map<T, Rule> rules;
  std::discrete_distribution<unsigned> distr;
};

#endif
<|endoftext|>