<commit_before>#include "stdafx.h"
#include "asdf_multiplat.h"
#include "spritebatch.h"
#include "content_manager.h"

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtx/rotate_vector.hpp>

using namespace std;
using namespace glm;
using namespace asdf::util;

namespace asdf {

    spritebatch_t::spritebatch_t()
    {
        glGenBuffers(1, &vertex_buffer);
        glGenBuffers(1, &index_buffer);
    }

    spritebatch_t::~spritebatch_t() {
        glDeleteBuffers(1, &vertex_buffer);
        glDeleteBuffers(1, &index_buffer);
    }

    /************************************************************************/
    /* Spritebatch Begin
    /* Initializes a batch with an optional view and/or proj matrix
    /************************************************************************/
    void spritebatch_t::begin(glm::mat4 const& view_matrix/*mat4()*/) {
        float halfwidth = app.settings.resolution_width / 2.0f;
        float halfheight = app.settings.resolution_height / 2.0f;

        mat4 proj = ortho<float>(-halfwidth, halfwidth,
                            -halfheight, halfheight,
                            -1000, 1000);

        begin(view_matrix, proj);
    }
    void spritebatch_t::begin(glm::mat4 const& view_matrix, glm::mat4 const& projection_matrix) {
        ASSERT(spritebatch_shader, "Trying to begin() without a shader");
        ASSERT(!has_begun, "beginning spritebatch before current batch has ended");
        ASSERT(!CheckGLError(), "GL Error before spritebatch_t::begin()");

        has_begun = true;
        spritebatch_shader->view_matrix = view_matrix;
        spritebatch_shader->projection_matrix = projection_matrix;
    }

    /************************************************************************/
    /* Spritebatch Draw
    /* Add a sprite to a map indexed by texture used
    /************************************************************************/
    void spritebatch_t::draw(std::shared_ptr<texture_t> const& texture, rectf_t dest_rect, color_t const& color/*vec4(1.0f)*/, float rotation/*0*/) {
        ASSERT(texture != nullptr, "Drawing a sprite with a null texture");
        glm::vec2 scale(dest_rect.width / texture->get_width(), dest_rect.height / texture->get_width());
        draw(texture, glm::vec2(dest_rect.x, dest_rect.y), color, scale, rotation);
    }
    void spritebatch_t::draw(std::shared_ptr<texture_t> const& texture, glm::vec2 const& position, color_t const& color/*vec4(1.0f)*/, glm::vec2 const& scale/*vec2(1,1)*/, float rotation/*0*/) {
        ASSERT(texture != nullptr, "Drawing a sprite with a null texture");
        rect_t rect(0, 0, texture->get_width(), texture->get_height());
        draw(texture, position, rect, color, scale, rotation);
    }
    void spritebatch_t::draw(std::shared_ptr<texture_t> const& texture, glm::vec2 const& position, rect_t const& src_rect, color_t const& color/*vec4(1.0f)*/, glm::vec2 const& scale/*vec2(1,1)*/, float rotation/*0*/) {
        ASSERT(texture != nullptr, "Drawing a sprite with a null texture");
        // LOG_IF(scale.x == 0 && scale.y == 0, "Drawing a sprite with no scale");

        sprite_map[texture].push_back(sprite_t(texture, position, src_rect, color, scale, rotation));
    }

    /************************************************************************/
    /* Spritebatch DrawText
    /* All text is batched and rendered at the end
    /*
    /* Todo: implement Z sorting so the text isn't just rendered on top
    /************************************************************************/
    void spritebatch_t::draw_text(std::string const& str, FTFont* font, size_t face_size, glm::vec2 const& position, color_t color, float rotation) {
        ASSERT(font != nullptr, "Spritebatching text without a font");

        if(str.size() > 0)
        {
            batched_text.push_back( text_sprite_t(str, font, face_size, position, color, rotation) );
        }
    }

    /************************************************************************/
    /* Spritebatch End
    /* Sets up consistent openGL state and renders out a batch for each texture
    /************************************************************************/
    void spritebatch_t::end() {
        ASSERT(has_begun, "ending spritebatch that hasn't begun");
        ASSERT(!CheckGLError(), "GL Error before spritebatch_t::end()");

        glEnable(GL_BLEND); //enable alpha blending
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //set blend function

        spritebatch_shader->use_program();

        spritebatch_shader->world_matrix = mat4(1.0f);
        spritebatch_shader->update_wvp_uniform();

        //glUniform1i(spritebatch_shader->uniforms.at("TextureMap"), 0);  //set the GLSL sampler to texture unit 0
        glActiveTexture(GL_TEXTURE0); //set current texture unit to 0
        glBindSampler(0, Content.samplers["LinearClamp"]);
        //glBindSampler(0, Content.samplers["LinearRepeat"]);

        auto textures_used = GetMapKeys<std::shared_ptr<texture_t>, std::vector <sprite_t>> (sprite_map);

        if (textures_used.size() > 0) {
            for (auto const& texture : textures_used)
                render_batch(texture);
        } else {
            // LOG("--Ended a spritebatch with no draw calls")
        }
        sprite_map.clear();

        glUseProgram(0);
        //render text
        for (text_sprite_t const& text : batched_text)
        {
            //assumes orthographic projection where 2/[0,0] = screen width and 2/[1,1] = screen_height
            float screen_halfw = 1 / spritebatch_shader->projection_matrix[0][0];
            float screen_halfh = 1 / spritebatch_shader->projection_matrix[1][1];
            glm::vec2 ftfont_pos = text.position;
            ftfont_pos.x += screen_halfw;
            ftfont_pos.y += screen_halfh;

            //don't render things we can't see
            if(ftfont_pos.x < (screen_halfw * 2) && ftfont_pos.y > 0)
            {
                text.font->FaceSize(text.face_size);
                //text.font->Render(text.str.c_str(), -1, FTPoint(ftfont_pos.x, ftfont_pos.y));  /// FIXME
            }
        }

        batched_text.clear();

        has_begun = false;

        ASSERT(!CheckGLError(), "GL Error in spritebatch_t::end()");
    }

    /************************************************************************/
    /* Spritebatch End
    /* Builds the sprite quads, sends them to openGL, and renders
    /*
    /* Todo: Refactor this function and trim it down
    /************************************************************************/
    void spritebatch_t::render_batch(shared_ptr<texture_t> const& texture)
    {
        uint16_t numBatchedSprites = 0;

        sprite_vertex_t spriteVertices[9001];
        uint16_t spriteIndices[9001];

        //todo: refactor this
        for (sprite_t const& sprite : sprite_map[texture]) {
            vec2 up(0.0f, 1.0f);
            vec2 right(1.0f, 0.0f);

            up = rotate(up, -sprite.rotation);
            right = rotate(right, -sprite.rotation);

            rectf_t src_rect_f(
                  static_cast<float>(sprite.src_rect.x)
                , static_cast<float>(sprite.src_rect.y)
                , static_cast<float>(sprite.src_rect.width)
                , static_cast<float>(sprite.src_rect.height)
                );

            uint16_t vertNum = numBatchedSprites * 4;
            float hwidth = src_rect_f.width  / 2.0f;
            float hheight = src_rect_f.height / 2.0f;
            float spritehwidth = hwidth * sprite.scale[0];
            float spritehheight = hheight * sprite.scale[1];

            ///FIXME precision
            float minX = src_rect_f.x / static_cast<float>(texture->get_width());
            float minY = src_rect_f.y / static_cast<float>(texture->get_height());
            float maxX = static_cast<float>(sprite.src_rect.x + sprite.src_rect.width) / static_cast<float>(texture->get_width());
            float maxY = static_cast<float>(sprite.src_rect.y + sprite.src_rect.height) / static_cast<float>(texture->get_height());

            /*  0 _________ 1
            *    |        /|
            *    |      /  |
            *    |    /    |
            *    |  /      |
            *    |/________|
            *   2           3
            */

            //v0 - top left
            spriteVertices[vertNum].position = sprite.position + right*(-spritehwidth) + up*(spritehheight);
            spriteVertices[vertNum].tex_coord = vec2(minX, maxY);
            spriteVertices[vertNum].color = sprite.color;

            //v1 - top right
            spriteVertices[vertNum + 1].position = sprite.position + right*(spritehwidth)+up*(spritehheight);
            spriteVertices[vertNum + 1].tex_coord = vec2(maxX, maxY);
            spriteVertices[vertNum + 1].color = sprite.color;

            //v2 - bottom left
            spriteVertices[vertNum + 2].position = sprite.position + right*(-spritehwidth) + up*(-spritehheight);
            spriteVertices[vertNum + 2].tex_coord = vec2(minX, minY);
            spriteVertices[vertNum + 2].color = sprite.color;

            //v3- bottom right
            spriteVertices[vertNum + 3].position = sprite.position + right*(spritehwidth)+up*(-spritehheight);
            spriteVertices[vertNum + 3].tex_coord = vec2(maxX, minY);
            spriteVertices[vertNum + 3].color = sprite.color;

            size_t indexNum = numBatchedSprites * 6;

            spriteIndices[indexNum + 0] = vertNum + 0;
            spriteIndices[indexNum + 1] = vertNum + 1;
            spriteIndices[indexNum + 2] = vertNum + 2;

            spriteIndices[indexNum + 3] = vertNum + 2;
            spriteIndices[indexNum + 4] = vertNum + 1;
            spriteIndices[indexNum + 5] = vertNum + 3;

            //--- DEBUG ---
            //todo: refactor
            if (debugging_sprites) {
                LOG_IF(CheckGLError(), "Error before drawing spritebatch debug information");

                auto passthrough = Content.shaders["passthrough"];
                passthrough->use_program();
                passthrough->world_matrix       = spritebatch_shader->world_matrix;
                passthrough->view_matrix        = spritebatch_shader->view_matrix;
                passthrough->projection_matrix  = spritebatch_shader->projection_matrix;

                passthrough->update_wvp_uniform();
                glUniform4f(passthrough->uniforms["Color"], 1.0f, 0.0f, 0.0f, 1.0f);

                glDisable(GL_CULL_FACE);
                glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
                glLineWidth(6.0f);

                glBegin(GL_POLYGON);
                glTexCoord2f(0.01f, 0.99f); glVertex2f(spriteVertices[vertNum + 0].position.x, spriteVertices[vertNum + 2].position.y); //BOTTOM LEFT
                glTexCoord2f(0.01f, 0.01f); glVertex2f(spriteVertices[vertNum + 1].position.x, spriteVertices[vertNum + 1].position.y);  //TOP LEFT
                glTexCoord2f(0.99f, 0.01f); glVertex2f(spriteVertices[vertNum + 2].position.x, spriteVertices[vertNum + 0].position.y);   //TOP RIGHT
                glTexCoord2f(0.99f, 0.99f); glVertex2f(spriteVertices[vertNum + 3].position.x, spriteVertices[vertNum + 3].position.y);  //BOTTOM RIGHT
                glEnd();

                spritebatch_shader->use_program();
                LOG_IF(CheckGLError(), "Error drawing spritebatch debug information");
            }
            //---

            numBatchedSprites++;
        }

        //bind/push the index data
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, numBatchedSprites * 6 * sizeof(short),
                     reinterpret_cast<void*>(spriteIndices), GL_STREAM_DRAW);

        //bind the vbo and push the vertex data
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
        glBufferData(GL_ARRAY_BUFFER, numBatchedSprites * 4 * sizeof(sprite_vertex_t),
                     reinterpret_cast<void*>(spriteVertices), GL_STREAM_DRAW);

        //enable position, texCoord, color
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        glEnableVertexAttribArray(2);

        //set up vertex attrib size / types. stride is just the total size of the vertex
        GLsizei stride = sizeof(sprite_vertex_t);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, stride, 0);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<void*>(sizeof(glm::vec2)) ); //MUST STILL PROVIDE OFFSET
        glVertexAttribPointer(2, 4, GL_FLOAT, GL_TRUE, stride, reinterpret_cast<void*>(sizeof(glm::vec2) * 2) );

        LOG_IF(CheckGLError(), "Error after setting up spritebatch vertex attributes");

        //set openGL state
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, texture->get_textureID()); //bind the texture. Sampler is set in End()
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glDisable(GL_CULL_FACE);

        glDrawElements(GL_TRIANGLES, numBatchedSprites * 6, GL_UNSIGNED_SHORT, 0);

        if (debugging_sprites) {
            Content.shaders["passthrough"]->use_program();
            glUniform4f(Content.shaders["passthrough"]->uniforms["Color"], 0.0f, 0.0f, 1.0f, 1.0f);
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            glLineWidth(2.0f);

            glDrawElements(GL_TRIANGLES, numBatchedSprites * 6, GL_UNSIGNED_SHORT, 0);
        }

        //reset opengl state
        //glEnable(GL_CULL_FACE);
        glBindTexture(GL_TEXTURE_2D, 0);

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(2);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

        LOG_IF(CheckGLError(), "Error after drawing spritebatch polygons");
        ASSERT(!CheckGLError(), "");
    }

}<commit_msg>minor useful comment<commit_after>#include "stdafx.h"
#include "asdf_multiplat.h"
#include "spritebatch.h"
#include "content_manager.h"

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtx/rotate_vector.hpp>

using namespace std;
using namespace glm;
using namespace asdf::util;

namespace asdf {

    spritebatch_t::spritebatch_t()
    {
        glGenBuffers(1, &vertex_buffer);
        glGenBuffers(1, &index_buffer);
    }

    spritebatch_t::~spritebatch_t() {
        glDeleteBuffers(1, &vertex_buffer);
        glDeleteBuffers(1, &index_buffer);
    }

    /************************************************************************/
    /* Spritebatch Begin
    /* Initializes a batch with an optional view and/or proj matrix
    /************************************************************************/
    void spritebatch_t::begin(glm::mat4 const& view_matrix/*mat4()*/) {
        float halfwidth = app.settings.resolution_width / 2.0f;
        float halfheight = app.settings.resolution_height / 2.0f;

        mat4 proj = ortho<float>(-halfwidth, halfwidth,
                            -halfheight, halfheight,
                            -1000, 1000);

        begin(view_matrix, proj);
    }
    void spritebatch_t::begin(glm::mat4 const& view_matrix, glm::mat4 const& projection_matrix) {
        ASSERT(spritebatch_shader, "Trying to begin() without a shader");
        ASSERT(!has_begun, "beginning spritebatch before current batch has ended");
        ASSERT(!CheckGLError(), "GL Error before spritebatch_t::begin()");

        has_begun = true;
        spritebatch_shader->view_matrix = view_matrix;
        spritebatch_shader->projection_matrix = projection_matrix;
    }

    /************************************************************************/
    /* Spritebatch Draw
    /* Add a sprite to a map indexed by texture used
    /* src_rect is relative to the bottom_left of the texture (since that's the openGL {0,0} point)
    /************************************************************************/
    void spritebatch_t::draw(std::shared_ptr<texture_t> const& texture, rectf_t dest_rect, color_t const& color/*vec4(1.0f)*/, float rotation/*0*/) {
        ASSERT(texture != nullptr, "Drawing a sprite with a null texture");
        glm::vec2 scale(dest_rect.width / texture->get_width(), dest_rect.height / texture->get_width());
        draw(texture, glm::vec2(dest_rect.x, dest_rect.y), color, scale, rotation);
    }
    void spritebatch_t::draw(std::shared_ptr<texture_t> const& texture, glm::vec2 const& position, color_t const& color/*vec4(1.0f)*/, glm::vec2 const& scale/*vec2(1,1)*/, float rotation/*0*/) {
        ASSERT(texture != nullptr, "Drawing a sprite with a null texture");
        rect_t rect(0, 0, texture->get_width(), texture->get_height());
        draw(texture, position, rect, color, scale, rotation);
    }
    void spritebatch_t::draw(std::shared_ptr<texture_t> const& texture, glm::vec2 const& position, rect_t const& src_rect, color_t const& color/*vec4(1.0f)*/, glm::vec2 const& scale/*vec2(1,1)*/, float rotation/*0*/) {
        ASSERT(texture != nullptr, "Drawing a sprite with a null texture");
        // LOG_IF(scale.x == 0 && scale.y == 0, "Drawing a sprite with no scale");

        sprite_map[texture].push_back(sprite_t(texture, position, src_rect, color, scale, rotation));
    }

    /************************************************************************/
    /* Spritebatch DrawText
    /* All text is batched and rendered at the end
    /*
    /* Todo: implement Z sorting so the text isn't just rendered on top
    /************************************************************************/
    void spritebatch_t::draw_text(std::string const& str, FTFont* font, size_t face_size, glm::vec2 const& position, color_t color, float rotation) {
        ASSERT(font != nullptr, "Spritebatching text without a font");

        if(str.size() > 0)
        {
            batched_text.push_back( text_sprite_t(str, font, face_size, position, color, rotation) );
        }
    }

    /************************************************************************/
    /* Spritebatch End
    /* Sets up consistent openGL state and renders out a batch for each texture
    /************************************************************************/
    void spritebatch_t::end() {
        ASSERT(has_begun, "ending spritebatch that hasn't begun");
        ASSERT(!CheckGLError(), "GL Error before spritebatch_t::end()");

        glEnable(GL_BLEND); //enable alpha blending
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //set blend function

        spritebatch_shader->use_program();

        spritebatch_shader->world_matrix = mat4(1.0f);
        spritebatch_shader->update_wvp_uniform();

        //glUniform1i(spritebatch_shader->uniforms.at("TextureMap"), 0);  //set the GLSL sampler to texture unit 0
        glActiveTexture(GL_TEXTURE0); //set current texture unit to 0
        glBindSampler(0, Content.samplers["LinearClamp"]);
        //glBindSampler(0, Content.samplers["LinearRepeat"]);

        auto textures_used = GetMapKeys<std::shared_ptr<texture_t>, std::vector <sprite_t>> (sprite_map);

        if (textures_used.size() > 0) {
            for (auto const& texture : textures_used)
                render_batch(texture);
        } else {
            // LOG("--Ended a spritebatch with no draw calls")
        }
        sprite_map.clear();

        glUseProgram(0);
        //render text
        for (text_sprite_t const& text : batched_text)
        {
            //assumes orthographic projection where 2/[0,0] = screen width and 2/[1,1] = screen_height
            float screen_halfw = 1 / spritebatch_shader->projection_matrix[0][0];
            float screen_halfh = 1 / spritebatch_shader->projection_matrix[1][1];
            glm::vec2 ftfont_pos = text.position;
            ftfont_pos.x += screen_halfw;
            ftfont_pos.y += screen_halfh;

            //don't render things we can't see
            if(ftfont_pos.x < (screen_halfw * 2) && ftfont_pos.y > 0)
            {
                text.font->FaceSize(text.face_size);
                //text.font->Render(text.str.c_str(), -1, FTPoint(ftfont_pos.x, ftfont_pos.y));  /// FIXME
            }
        }

        batched_text.clear();

        has_begun = false;

        ASSERT(!CheckGLError(), "GL Error in spritebatch_t::end()");
    }

    /************************************************************************/
    /* Spritebatch End
    /* Builds the sprite quads, sends them to openGL, and renders
    /*
    /* Todo: Refactor this function and trim it down
    /************************************************************************/
    void spritebatch_t::render_batch(shared_ptr<texture_t> const& texture)
    {
        uint16_t numBatchedSprites = 0;

        sprite_vertex_t spriteVertices[9001];
        uint16_t spriteIndices[9001];

        //todo: refactor this
        for (sprite_t const& sprite : sprite_map[texture]) {
            vec2 up(0.0f, 1.0f);
            vec2 right(1.0f, 0.0f);

            up = rotate(up, -sprite.rotation);
            right = rotate(right, -sprite.rotation);

            rectf_t src_rect_f(
                  static_cast<float>(sprite.src_rect.x)
                , static_cast<float>(sprite.src_rect.y)
                , static_cast<float>(sprite.src_rect.width)
                , static_cast<float>(sprite.src_rect.height)
                );

            uint16_t vertNum = numBatchedSprites * 4;
            float hwidth = src_rect_f.width  / 2.0f;
            float hheight = src_rect_f.height / 2.0f;
            float spritehwidth = hwidth * sprite.scale[0];
            float spritehheight = hheight * sprite.scale[1];

            ///FIXME precision
            float minX = src_rect_f.x / static_cast<float>(texture->get_width());
            float minY = src_rect_f.y / static_cast<float>(texture->get_height());
            float maxX = static_cast<float>(sprite.src_rect.x + sprite.src_rect.width) / static_cast<float>(texture->get_width());
            float maxY = static_cast<float>(sprite.src_rect.y + sprite.src_rect.height) / static_cast<float>(texture->get_height());

            /*  0 _________ 1
            *    |        /|
            *    |      /  |
            *    |    /    |
            *    |  /      |
            *    |/________|
            *   2           3
            */

            //v0 - top left
            spriteVertices[vertNum].position = sprite.position + right*(-spritehwidth) + up*(spritehheight);
            spriteVertices[vertNum].tex_coord = vec2(minX, maxY);
            spriteVertices[vertNum].color = sprite.color;

            //v1 - top right
            spriteVertices[vertNum + 1].position = sprite.position + right*(spritehwidth)+up*(spritehheight);
            spriteVertices[vertNum + 1].tex_coord = vec2(maxX, maxY);
            spriteVertices[vertNum + 1].color = sprite.color;

            //v2 - bottom left
            spriteVertices[vertNum + 2].position = sprite.position + right*(-spritehwidth) + up*(-spritehheight);
            spriteVertices[vertNum + 2].tex_coord = vec2(minX, minY);
            spriteVertices[vertNum + 2].color = sprite.color;

            //v3- bottom right
            spriteVertices[vertNum + 3].position = sprite.position + right*(spritehwidth)+up*(-spritehheight);
            spriteVertices[vertNum + 3].tex_coord = vec2(maxX, minY);
            spriteVertices[vertNum + 3].color = sprite.color;

            size_t indexNum = numBatchedSprites * 6;

            spriteIndices[indexNum + 0] = vertNum + 0;
            spriteIndices[indexNum + 1] = vertNum + 1;
            spriteIndices[indexNum + 2] = vertNum + 2;

            spriteIndices[indexNum + 3] = vertNum + 2;
            spriteIndices[indexNum + 4] = vertNum + 1;
            spriteIndices[indexNum + 5] = vertNum + 3;

            //--- DEBUG ---
            //todo: refactor
            if (debugging_sprites) {
                LOG_IF(CheckGLError(), "Error before drawing spritebatch debug information");

                auto passthrough = Content.shaders["passthrough"];
                passthrough->use_program();
                passthrough->world_matrix       = spritebatch_shader->world_matrix;
                passthrough->view_matrix        = spritebatch_shader->view_matrix;
                passthrough->projection_matrix  = spritebatch_shader->projection_matrix;

                passthrough->update_wvp_uniform();
                glUniform4f(passthrough->uniforms["Color"], 1.0f, 0.0f, 0.0f, 1.0f);

                glDisable(GL_CULL_FACE);
                glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
                glLineWidth(6.0f);

                glBegin(GL_POLYGON);
                glTexCoord2f(0.01f, 0.99f); glVertex2f(spriteVertices[vertNum + 0].position.x, spriteVertices[vertNum + 2].position.y); //BOTTOM LEFT
                glTexCoord2f(0.01f, 0.01f); glVertex2f(spriteVertices[vertNum + 1].position.x, spriteVertices[vertNum + 1].position.y);  //TOP LEFT
                glTexCoord2f(0.99f, 0.01f); glVertex2f(spriteVertices[vertNum + 2].position.x, spriteVertices[vertNum + 0].position.y);   //TOP RIGHT
                glTexCoord2f(0.99f, 0.99f); glVertex2f(spriteVertices[vertNum + 3].position.x, spriteVertices[vertNum + 3].position.y);  //BOTTOM RIGHT
                glEnd();

                spritebatch_shader->use_program();
                LOG_IF(CheckGLError(), "Error drawing spritebatch debug information");
            }
            //---

            numBatchedSprites++;
        }

        //bind/push the index data
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, numBatchedSprites * 6 * sizeof(short),
                     reinterpret_cast<void*>(spriteIndices), GL_STREAM_DRAW);

        //bind the vbo and push the vertex data
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
        glBufferData(GL_ARRAY_BUFFER, numBatchedSprites * 4 * sizeof(sprite_vertex_t),
                     reinterpret_cast<void*>(spriteVertices), GL_STREAM_DRAW);

        //enable position, texCoord, color
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        glEnableVertexAttribArray(2);

        //set up vertex attrib size / types. stride is just the total size of the vertex
        GLsizei stride = sizeof(sprite_vertex_t);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, stride, 0);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<void*>(sizeof(glm::vec2)) ); //MUST STILL PROVIDE OFFSET
        glVertexAttribPointer(2, 4, GL_FLOAT, GL_TRUE, stride, reinterpret_cast<void*>(sizeof(glm::vec2) * 2) );

        LOG_IF(CheckGLError(), "Error after setting up spritebatch vertex attributes");

        //set openGL state
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, texture->get_textureID()); //bind the texture. Sampler is set in End()
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glDisable(GL_CULL_FACE);

        glDrawElements(GL_TRIANGLES, numBatchedSprites * 6, GL_UNSIGNED_SHORT, 0);

        if (debugging_sprites) {
            Content.shaders["passthrough"]->use_program();
            glUniform4f(Content.shaders["passthrough"]->uniforms["Color"], 0.0f, 0.0f, 1.0f, 1.0f);
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            glLineWidth(2.0f);

            glDrawElements(GL_TRIANGLES, numBatchedSprites * 6, GL_UNSIGNED_SHORT, 0);
        }

        //reset opengl state
        //glEnable(GL_CULL_FACE);
        glBindTexture(GL_TEXTURE_2D, 0);

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(2);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

        LOG_IF(CheckGLError(), "Error after drawing spritebatch polygons");
        ASSERT(!CheckGLError(), "");
    }

}<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "videowidget.h"
#include "videowidget_p.h"
#include "videowidgetinterface.h"
#include "factory.h"
#include "phonondefs_p.h"
#include "phononnamespace_p.h"

#include <QtGui/QAction>

#define PHONON_INTERFACENAME VideoWidgetInterface

namespace Phonon
{

VideoWidget::VideoWidget(QWidget *parent)
    : QWidget(parent)
    , Phonon::AbstractVideoOutput(*new VideoWidgetPrivate(this))
{
    K_D(VideoWidget);
    d->init();
    d->createBackendObject();
    setMouseTracking(true);
}

VideoWidget::VideoWidget(VideoWidgetPrivate &dd, QWidget *parent)
    : QWidget(parent),
    Phonon::AbstractVideoOutput(dd)
{
    K_D(VideoWidget);
    d->init();
}

void VideoWidgetPrivate::init()
{
    Q_Q(VideoWidget);
    QObject::connect(&cursorTimer, SIGNAL(timeout()), q, SLOT(_k_cursorTimeout()));
    cursorTimer.start();
}

void VideoWidget::mouseMoveEvent(QMouseEvent *)
{
    K_D(VideoWidget);
    if (k_ptr->backendObject()) {
        QWidget *w = INTERFACE_CALL(widget());
        if (w && Qt::BlankCursor == w->cursor().shape()) {
            unsetCursor();
            d->cursorTimer.start();
        }
    }
}

void VideoWidgetPrivate::_k_cursorTimeout()
{
    if (m_backendObject) {
        QWidget *w = pINTERFACE_CALL(widget());
        if (w && Qt::ArrowCursor == w->cursor().shape()) {
            q_func()->setCursor(Qt::BlankCursor);
        }
    }
}
void VideoWidgetPrivate::createBackendObject()
{
    if (m_backendObject)
        return;
    Q_Q(VideoWidget);
    m_backendObject = Factory::createVideoWidget(q);
    if (m_backendObject) {
        setupBackendObject();
    }
}

#define PHONON_CLASSNAME VideoWidget

PHONON_INTERFACE_GETTER(Phonon::VideoWidget::AspectRatio, aspectRatio, d->aspectRatio)
PHONON_INTERFACE_SETTER(setAspectRatio, aspectRatio, Phonon::VideoWidget::AspectRatio)

PHONON_INTERFACE_GETTER(Phonon::VideoWidget::ScaleMode, scaleMode, d->scaleMode)
PHONON_INTERFACE_SETTER(setScaleMode, scaleMode, Phonon::VideoWidget::ScaleMode)

PHONON_INTERFACE_GETTER(qreal, brightness, d->brightness)
PHONON_INTERFACE_SETTER(setBrightness, brightness, qreal)

PHONON_INTERFACE_GETTER(qreal, contrast, d->contrast)
PHONON_INTERFACE_SETTER(setContrast, contrast, qreal)

PHONON_INTERFACE_GETTER(qreal, hue, d->hue)
PHONON_INTERFACE_SETTER(setHue, hue, qreal)

PHONON_INTERFACE_GETTER(qreal, saturation, d->saturation)
PHONON_INTERFACE_SETTER(setSaturation, saturation, qreal)

void VideoWidget::setFullScreen(bool newFullScreen)
{
    pDebug() << Q_FUNC_INFO << newFullScreen;
    K_D(VideoWidget);
    // TODO: disable screensaver? or should we leave that responsibility to the
    // application?
    Qt::WindowFlags flags = windowFlags();
    if (newFullScreen) {
        d->changeFlags = !(flags & Qt::Window);
        if (d->changeFlags) {
            flags &= ~Qt::SubWindow;
            flags |= Qt::Window;
        } // else it's a toplevel window already
    } else if (d->changeFlags && parent()) {
        flags &= ~Qt::Window;
        flags |= Qt::SubWindow;
    }
    setWindowFlags(flags);
    if (newFullScreen) {
        showFullScreen();
    } else {
        showNormal();
    }
}

void VideoWidget::exitFullScreen()
{
    setFullScreen(false);
}

void VideoWidget::enterFullScreen()
{
    setFullScreen(true);
}

bool VideoWidgetPrivate::aboutToDeleteBackendObject()
{
    aspectRatio = pINTERFACE_CALL(aspectRatio());
    scaleMode = pINTERFACE_CALL(scaleMode());
    return AbstractVideoOutputPrivate::aboutToDeleteBackendObject();
}

void VideoWidgetPrivate::setupBackendObject()
{
    Q_Q(VideoWidget);
    Q_ASSERT(m_backendObject);
    //AbstractVideoOutputPrivate::setupBackendObject();
    pDebug() << "calling setAspectRatio on the backend " << aspectRatio;
    pINTERFACE_CALL(setAspectRatio(aspectRatio));
    pINTERFACE_CALL(setScaleMode(scaleMode));

    QWidget *w = pINTERFACE_CALL(widget());
    if (w) {
        layout.addWidget(w);
        q->setSizePolicy(w->sizePolicy());
        w->setMouseTracking(true);
    }
}

/*
QSize VideoWidget::sizeHint()
{
    if (k_ptr->backendObject())
    {
        QWidget *w = pINTERFACE_CALL(widget());
        if (w)
            return w->sizeHint();
    }
    return QSize(0, 0);
}

QSize VideoWidget::minimumSizeHint()
{
    if (k_ptr->backendObject())
    {
        QWidget *w = pINTERFACE_CALL(widget());
        if (w)
            return w->minimumSizeHint();
    }
    return QSize(0, 0);
} */

} //namespace Phonon

#include "moc_videowidget.cpp"

#undef PHONON_CLASSNAME
// vim: sw=4 ts=4 tw=80
<commit_msg>complementary update (removing useless code)<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "videowidget.h"
#include "videowidget_p.h"
#include "videowidgetinterface.h"
#include "factory.h"
#include "phonondefs_p.h"
#include "phononnamespace_p.h"

#include <QtGui/QAction>

#define PHONON_INTERFACENAME VideoWidgetInterface

namespace Phonon
{

VideoWidget::VideoWidget(QWidget *parent)
    : QWidget(parent)
    , Phonon::AbstractVideoOutput(*new VideoWidgetPrivate(this))
{
    K_D(VideoWidget);
    d->init();
    d->createBackendObject();
    setMouseTracking(true);
}

VideoWidget::VideoWidget(VideoWidgetPrivate &dd, QWidget *parent)
    : QWidget(parent),
    Phonon::AbstractVideoOutput(dd)
{
    K_D(VideoWidget);
    d->init();
}

void VideoWidgetPrivate::init()
{
    Q_Q(VideoWidget);
    QObject::connect(&cursorTimer, SIGNAL(timeout()), q, SLOT(_k_cursorTimeout()));
    cursorTimer.start();
}

void VideoWidget::mouseMoveEvent(QMouseEvent *)
{
    K_D(VideoWidget);
    if (Qt::BlankCursor == cursor().shape()) {
        unsetCursor();
        d->cursorTimer.start();
    }
}

void VideoWidgetPrivate::_k_cursorTimeout()
{
    Q_Q(VideoWidget);
    if (Qt::ArrowCursor == q->cursor().shape()) {
        q->setCursor(Qt::BlankCursor);
    }
}

void VideoWidgetPrivate::createBackendObject()
{
    if (m_backendObject)
        return;
    Q_Q(VideoWidget);
    m_backendObject = Factory::createVideoWidget(q);
    if (m_backendObject) {
        setupBackendObject();
    }
}

#define PHONON_CLASSNAME VideoWidget

PHONON_INTERFACE_GETTER(Phonon::VideoWidget::AspectRatio, aspectRatio, d->aspectRatio)
PHONON_INTERFACE_SETTER(setAspectRatio, aspectRatio, Phonon::VideoWidget::AspectRatio)

PHONON_INTERFACE_GETTER(Phonon::VideoWidget::ScaleMode, scaleMode, d->scaleMode)
PHONON_INTERFACE_SETTER(setScaleMode, scaleMode, Phonon::VideoWidget::ScaleMode)

PHONON_INTERFACE_GETTER(qreal, brightness, d->brightness)
PHONON_INTERFACE_SETTER(setBrightness, brightness, qreal)

PHONON_INTERFACE_GETTER(qreal, contrast, d->contrast)
PHONON_INTERFACE_SETTER(setContrast, contrast, qreal)

PHONON_INTERFACE_GETTER(qreal, hue, d->hue)
PHONON_INTERFACE_SETTER(setHue, hue, qreal)

PHONON_INTERFACE_GETTER(qreal, saturation, d->saturation)
PHONON_INTERFACE_SETTER(setSaturation, saturation, qreal)

void VideoWidget::setFullScreen(bool newFullScreen)
{
    pDebug() << Q_FUNC_INFO << newFullScreen;
    K_D(VideoWidget);
    // TODO: disable screensaver? or should we leave that responsibility to the
    // application?
    Qt::WindowFlags flags = windowFlags();
    if (newFullScreen) {
        d->changeFlags = !(flags & Qt::Window);
        if (d->changeFlags) {
            flags &= ~Qt::SubWindow;
            flags |= Qt::Window;
        } // else it's a toplevel window already
    } else if (d->changeFlags && parent()) {
        flags &= ~Qt::Window;
        flags |= Qt::SubWindow;
    }
    setWindowFlags(flags);
    if (newFullScreen) {
        showFullScreen();
    } else {
        showNormal();
    }
}

void VideoWidget::exitFullScreen()
{
    setFullScreen(false);
}

void VideoWidget::enterFullScreen()
{
    setFullScreen(true);
}

bool VideoWidgetPrivate::aboutToDeleteBackendObject()
{
    aspectRatio = pINTERFACE_CALL(aspectRatio());
    scaleMode = pINTERFACE_CALL(scaleMode());
    return AbstractVideoOutputPrivate::aboutToDeleteBackendObject();
}

void VideoWidgetPrivate::setupBackendObject()
{
    Q_Q(VideoWidget);
    Q_ASSERT(m_backendObject);
    //AbstractVideoOutputPrivate::setupBackendObject();
    pDebug() << "calling setAspectRatio on the backend " << aspectRatio;
    pINTERFACE_CALL(setAspectRatio(aspectRatio));
    pINTERFACE_CALL(setScaleMode(scaleMode));

    QWidget *w = pINTERFACE_CALL(widget());
    if (w) {
        layout.addWidget(w);
        q->setSizePolicy(w->sizePolicy());
        w->setMouseTracking(true);
    }
}

/*
QSize VideoWidget::sizeHint()
{
    if (k_ptr->backendObject())
    {
        QWidget *w = pINTERFACE_CALL(widget());
        if (w)
            return w->sizeHint();
    }
    return QSize(0, 0);
}

QSize VideoWidget::minimumSizeHint()
{
    if (k_ptr->backendObject())
    {
        QWidget *w = pINTERFACE_CALL(widget());
        if (w)
            return w->minimumSizeHint();
    }
    return QSize(0, 0);
} */

} //namespace Phonon

#include "moc_videowidget.cpp"

#undef PHONON_CLASSNAME
// vim: sw=4 ts=4 tw=80
<|endoftext|>


<commit_before>#include <QApplication>
#include <QWebSettings>
#include "KVMainWindow.h"
#include "KVProxyServer.h"

int main(int argc, char *argv[])
{
	QApplication app(argc, argv);
	QCoreApplication::setApplicationName("KCTViewer");
	QCoreApplication::setApplicationVersion("0.2.0");
	QCoreApplication::setOrganizationName("MacaroniCode");

	QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true);

	QStringList args = QCoreApplication::arguments();

	// The --debug-proxy argument starts the program in Proxy Debug mode, with no
	// GUI and only the proxy server running on IPv4 port 12345.
	if(args.contains("--debug-proxy"))
	{
		KVProxyServer *proxy = new KVProxyServer();
		proxy->listen(QHostAddress::LocalHost, 12345);
	}
	// If we're not debugging the proxy, just start normally.
	else
	{
		KVMainWindow *win = new KVMainWindow();
		win->show();
	}

	app.exec();
}
<commit_msg>Qt Creator on windows complains about this<commit_after>#include <QApplication>
#include <QWebSettings>
#include "KVMainWindow.h"
#include "KVProxyServer.h"

int main(int argc, char *argv[])
{
	QApplication app(argc, argv);
	QCoreApplication::setApplicationName("KCTViewer");
	QCoreApplication::setApplicationVersion("0.2.0");
	QCoreApplication::setOrganizationName("MacaroniCode");

	QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true);

	QStringList args = QCoreApplication::arguments();

	// The --debug-proxy argument starts the program in Proxy Debug mode, with no
	// GUI and only the proxy server running on IPv4 port 12345.
	if(args.contains("--debug-proxy"))
	{
		KVProxyServer *proxy = new KVProxyServer();
		proxy->listen(QHostAddress::LocalHost, 12345);
	}
	// If we're not debugging the proxy, just start normally.
	else
	{
		KVMainWindow *win = new KVMainWindow();
		win->show();
	}

	return app.exec();
}
<|endoftext|>


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

#ifdef PCH
#include "filt_pch.hxx"
#endif

#pragma hdrstop

//___________________________________________________________________

#ifndef _XMLOFF_PROGRESSBARHELPER_HXX
#include "ProgressBarHelper.hxx"
#endif

using namespace ::com::sun::star;

const sal_Int32 nDefaultProgressBarRange = 1000000;
const sal_Int16 nProgressStep = 2;

ProgressBarHelper::ProgressBarHelper(const ::com::sun::star::uno::Reference < ::com::sun::star::task::XStatusIndicator>& xTempStatusIndicator,
                                    const ::rtl::OUString& rText)
    : nOldPercent(0),
    nRange(nDefaultProgressBarRange),
    xStatusIndicator(xTempStatusIndicator)
{
    if (xStatusIndicator.is())
        xStatusIndicator->setText(rText);
//      xStatusIndicator->start(rText, nProgressBarRange);
}

ProgressBarHelper::~ProgressBarHelper()
{
//  if (xStatusIndicator.is())
//      xStatusIndicator->end();
}

void ProgressBarHelper::SetValue(sal_Int32 nTempValue)
{
    nValue = nTempValue;
    if (xStatusIndicator.is())
    {
        double fValue(nValue);
        double fNewValue ((fValue * nRange) / nReference);
        double fPercent ((fNewValue * 100) / nRange);
        if ((sal_Int16)fPercent >= (nOldPercent + nProgressStep))
        {
            xStatusIndicator->setValue((sal_Int32)fNewValue);
            nOldPercent = (sal_Int16)fPercent;
        }
    }
}

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

#ifdef PCH
#include "filt_pch.hxx"
#endif

#pragma hdrstop

//___________________________________________________________________

#ifndef _XMLOFF_PROGRESSBARHELPER_HXX
#include "ProgressBarHelper.hxx"
#endif

using namespace ::com::sun::star;

const sal_Int32 nDefaultProgressBarRange = 1000000;
const sal_Int16 nProgressStep = 2;

ProgressBarHelper::ProgressBarHelper(const ::com::sun::star::uno::Reference < ::com::sun::star::task::XStatusIndicator>& xTempStatusIndicator,
                                    const ::rtl::OUString& rText)
    : nOldPercent(0),
    nRange(nDefaultProgressBarRange),
    xStatusIndicator(xTempStatusIndicator)
{
//  if (xStatusIndicator.is())
//      xStatusIndicator->setText(rText);
//      xStatusIndicator->start(rText, nProgressBarRange);
}

ProgressBarHelper::~ProgressBarHelper()
{
//  if (xStatusIndicator.is())
//      xStatusIndicator->end();
}

void ProgressBarHelper::SetValue(sal_Int32 nTempValue)
{
    nValue = nTempValue;
    if (xStatusIndicator.is())
    {
        double fValue(nValue);
        double fNewValue ((fValue * nRange) / nReference);
        double fPercent ((fNewValue * 100) / nRange);
        if ((sal_Int16)fPercent >= (nOldPercent + nProgressStep))
        {
            xStatusIndicator->setValue((sal_Int32)fNewValue);
            nOldPercent = (sal_Int16)fPercent;
        }
    }
}

<|endoftext|>


<commit_before>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "heuristic_greedy.hh"
#include "alg_bdfs.hh"
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <algorithm>

extern int _g_simulation_depth_hint;

Heuristic_greedy::Heuristic_greedy(Log& l, std::string params) :
  Heuristic(l), m_search_depth(0), m_burst(false)
{
  m_search_depth = atoi(params.c_str());
  if (strchr(params.c_str(), 'b')) {
    m_burst = true;
  }
}

bool Heuristic_greedy::execute(int action)
{
  if (m_path.size() > 0) {
    int planned_action = m_path.back();
    if (planned_action != action) // invalidate planned path
      m_path.resize(0);
    else
      m_path.pop_back();
  }
  return Heuristic::execute(action);
}

int Heuristic_greedy::getAction()
{
  int* actions;
  int i = model->getActions(&actions);

  if (i==0) {
    return Alphabet::DEADLOCK;
  }

  float* f=new float[i];
  int pos=my_coverage->fitness(actions,i,f);
  float score = f[pos];
  delete [] f;

  if (score > 0.0) {
    log.debug("Greedy selected %i (out of %i)\n",
              pos,i);
    return actions[pos];
  }

  /* Fall back to random selection */
  pos=(((float)random())/RAND_MAX)*i;
  return actions[pos];
}

int Heuristic_greedy::getIAction()
{
  if (!status) {
    return 0;
  }

  int* actions;
  int i = model->getIActions(&actions);
  int pos = -1;

  log.debug("greedy getIACtion %i",i);

  for(int u=0;u<i;u++) {
    log.debug("iaction %i %i",u,actions[u]);
  }

  if (i==0) {
    // No input actions. See if there are output actions available.
    i=model->getActions(&actions);
    if (i==0) {
      return Alphabet::DEADLOCK;
    }
    return Alphabet::OUTPUT_ONLY;
  }

  if (m_search_depth < 1) {
    /* Do a very fast lookup */
    float* f=new float[i];
    pos=my_coverage->fitness(actions,i,f);
    float score = f[pos];
    delete [] f;

    if (score > 0.0) {
      log.debug("Greedy selected %i (out of %i)\n",
                pos,i);
      return actions[pos];
    }
  } else {
    /* In burst mode new path is not searched before previosly found
     * path is fully consumed */
    if (!m_burst || m_path.empty() ) {
      /* Spend more time for better coverage */
      AlgPathToBestCoverage alg(m_search_depth);
      /* Use precalculated path (m_path) as a hint. */
      std::reverse(m_path.begin(), m_path.end());
      double score = alg.search(*model, *my_coverage, m_path);

      if (!alg.status) {
        status=false;
      }

      if (m_path.size() > 0) {
        std::reverse(m_path.begin(), m_path.end());
        log.debug("score: %f, path length: %d", score, m_path.size());
      }
    }
    if (m_path.size() > 0) {
      log.debug("path %i",m_path.back());
      i = model->getIActions(&actions);
      if (i==0) {
        return Alphabet::ERROR;
      }
      bool broken=true;
      int ret=m_path.back();
      for(int j=0;j<i;j++) {
        if (actions[j]==ret) {
          broken=false;
        }
      }
      if (broken) {
        log.print("<ERROR msg=\"%s (%s)\"/>","suggesting disabled action",
                  model->getActionName(ret).c_str());
        abort();
      }
      return m_path.back();
    }
  }

  /* Fall back to random selection. Input actions table might not be
   * valid anymore (execute might have happened), ask it again. */
  i = model->getIActions(&actions);
  pos=(((float)random())/RAND_MAX)*i;

  return actions[pos];
}

FACTORY_DEFAULT_CREATOR(Heuristic, Heuristic_greedy, "greedy")
FACTORY_DEFAULT_CREATOR(Heuristic, Heuristic_greedy, "lookahead")
FACTORY_DEFAULT_CREATOR(Heuristic, Heuristic_greedy, "action_fitness")
<commit_msg>on remote AAL, getIActions is expensive. So try to avoid calling...<commit_after>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "heuristic_greedy.hh"
#include "alg_bdfs.hh"
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <algorithm>

extern int _g_simulation_depth_hint;

Heuristic_greedy::Heuristic_greedy(Log& l, std::string params) :
  Heuristic(l), m_search_depth(0), m_burst(false)
{
  m_search_depth = atoi(params.c_str());
  if (strchr(params.c_str(), 'b')) {
    m_burst = true;
  }
}

bool Heuristic_greedy::execute(int action)
{
  if (m_path.size() > 0) {
    int planned_action = m_path.back();
    if (planned_action != action) // invalidate planned path
      m_path.resize(0);
    else
      m_path.pop_back();
  }
  return Heuristic::execute(action);
}

int Heuristic_greedy::getAction()
{
  int* actions;
  int i = model->getActions(&actions);

  if (i==0) {
    return Alphabet::DEADLOCK;
  }

  float* f=new float[i];
  int pos=my_coverage->fitness(actions,i,f);
  float score = f[pos];
  delete [] f;

  if (score > 0.0) {
    log.debug("Greedy selected %i (out of %i)\n",
              pos,i);
    return actions[pos];
  }

  /* Fall back to random selection */
  pos=(((float)random())/RAND_MAX)*i;
  return actions[pos];
}

int Heuristic_greedy::getIAction()
{
  if (!status) {
    return 0;
  }

  int* actions;
  int i = model->getIActions(&actions);
  int pos = -1;

  log.debug("greedy getIACtion %i",i);

  for(int u=0;u<i;u++) {
    log.debug("iaction %i %i",u,actions[u]);
  }

  if (i==0) {
    // No input actions. See if there are output actions available.
    i=model->getActions(&actions);
    if (i==0) {
      return Alphabet::DEADLOCK;
    }
    return Alphabet::OUTPUT_ONLY;
  }

  int actions_save[i];

  actions_save[0]=0;

  if (m_search_depth < 1) {
    /* Do a very fast lookup */
    float* f=new float[i];
    pos=my_coverage->fitness(actions,i,f);
    float score = f[pos];
    delete [] f;

    if (score > 0.0) {
      log.debug("Greedy selected %i (out of %i)\n",
                pos,i);
      return actions[pos];
    }
  } else {
    memcpy(actions_save,actions,i*sizeof(int));
    /* In burst mode new path is not searched before previosly found
     * path is fully consumed */
    if (!m_burst || m_path.empty() ) {
      /* Spend more time for better coverage */
      AlgPathToBestCoverage alg(m_search_depth);
      /* Use precalculated path (m_path) as a hint. */
      std::reverse(m_path.begin(), m_path.end());
      double score = alg.search(*model, *my_coverage, m_path);

      if (!alg.status) {
	errormsg = "Algorithm error:"+alg.errormsg;
        status=false;
      }

      if (m_path.size() > 0) {
        std::reverse(m_path.begin(), m_path.end());
        log.debug("score: %f, path length: %d", score, m_path.size());
      }
    }
    if (m_path.size() > 0) {
      log.debug("path %i",m_path.back());
      //i = model->getIActions(&actions);
      if (i==0) {
        return Alphabet::ERROR;
      }
      bool broken=true;
      int ret=m_path.back();
      for(int j=0;j<i;j++) {
        if (actions_save[j]==ret) {
          broken=false;
        }
      }
      if (broken) {
        log.print("<ERROR msg=\"%s (%s)\"/>","suggesting disabled action",
                  model->getActionName(ret).c_str());
        abort();
      }
      return m_path.back();
    }
  }

  /* Fall back to random selection. Input actions table might not be
   * valid anymore (execute might have happened), ask it again. */
  i = model->getIActions(&actions);
  pos=(((float)random())/RAND_MAX)*i;

  if (actions_save[0]) {
    return actions_save[pos];
  }

  return actions[pos];
}

FACTORY_DEFAULT_CREATOR(Heuristic, Heuristic_greedy, "greedy")
FACTORY_DEFAULT_CREATOR(Heuristic, Heuristic_greedy, "lookahead")
FACTORY_DEFAULT_CREATOR(Heuristic, Heuristic_greedy, "action_fitness")
<|endoftext|>


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

#include <core/FileLock.hpp>

#include <boost/scope_exit.hpp>

#include <core/Error.hpp>
#include <core/Log.hpp>
#include <core/FilePath.hpp>
#include <core/FileSerializer.hpp>
#include <core/StringUtils.hpp>

#include <core/BoostErrors.hpp>

// we define BOOST_USE_WINDOWS_H on mingw64 to work around some
// incompatabilities. however, this prevents the interprocess headers
// from compiling so we undef it in this localized context
#if defined(__GNUC__) && defined(_WIN64)
   #undef BOOST_USE_WINDOWS_H
#endif
#include <boost/interprocess/sync/file_lock.hpp>

namespace rstudio {
namespace core {

namespace {
typedef boost::interprocess::file_lock BoostFileLock;
}

struct AdvisoryFileLock::Impl
{
   FilePath lockFilePath;
   BoostFileLock lock;
};

bool AdvisoryFileLock::isLocked(const FilePath& lockFilePath) const
{
   // if the lock file doesn't exist then it's not locked
   if (!lockFilePath.exists())
      return false;

   // check if it is locked
   try
   {
      BoostFileLock lock(string_utils::utf8ToSystem(lockFilePath.absolutePath()).c_str());

      if (lock.try_lock())
      {
         lock.unlock();
         return false;
      }
      else
      {
         return true;
      }
   }
   catch(boost::interprocess::interprocess_exception& e)
   {
      Error error(boost::interprocess::ec_from_exception(e), ERROR_LOCATION);
      error.addProperty("lock-file", lockFilePath);
      LOG_ERROR(error);
      return false;
   }
}

AdvisoryFileLock::AdvisoryFileLock()
   : pImpl_(new Impl())
{
}

AdvisoryFileLock::~AdvisoryFileLock()
{
}

Error AdvisoryFileLock::acquire(const FilePath& lockFilePath)
{
   using namespace boost::interprocess;

   // make sure the lock file exists
   if (!lockFilePath.exists())
   {
      Error error = core::writeStringToFile(lockFilePath, "");
      if (error)
         return error;
   }

   // try to acquire the lock
   try
   {
      BoostFileLock lock(string_utils::utf8ToSystem(lockFilePath.absolutePath()).c_str());

      if (lock.try_lock())
      {
         // set members
         pImpl_->lockFilePath = lockFilePath;
         pImpl_->lock.swap(lock);

         return Success();
      }
      else
      {
         return systemError(boost::system::errc::no_lock_available,
                            ERROR_LOCATION);
      }
   }
   catch(interprocess_exception& e)
   {
      Error error(ec_from_exception(e), ERROR_LOCATION);
      error.addProperty("lock-file", lockFilePath);
      return error;
   }

   return Success();
}

Error AdvisoryFileLock::release()
{
   using namespace boost::interprocess;

   // make sure the lock file exists
   if (!pImpl_->lockFilePath.exists())
   {
      return systemError(boost::system::errc::no_lock_available,
                         ERROR_LOCATION);
   }

   // always cleanup the lock file on exit
   FilePath lockFilePath = pImpl_->lockFilePath;
   BOOST_SCOPE_EXIT( (&lockFilePath) )
   {
      Error error = lockFilePath.remove();
      if (error)
         LOG_ERROR(error);
   }
   BOOST_SCOPE_EXIT_END

   // try to unlock it
   try
   {
      pImpl_->lock.unlock();
      pImpl_->lock = BoostFileLock();
      pImpl_->lockFilePath = FilePath();
      return Success();
   }
   catch(interprocess_exception& e)
   {
      Error error(ec_from_exception(e), ERROR_LOCATION);
      error.addProperty("lock-file", pImpl_->lockFilePath);
      return error;
   }

   return Success();
}

FilePath AdvisoryFileLock::lockFilePath() const
{
   return pImpl_->lockFilePath;
}

void AdvisoryFileLock::refresh()
{
}

void AdvisoryFileLock::cleanUp()
{
}

} // namespace core
} // namespace rstudio

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

#include <sstream>

#include <core/FileLock.hpp>

#include <boost/scope_exit.hpp>

#include <core/Error.hpp>
#include <core/Log.hpp>
#include <core/FilePath.hpp>
#include <core/FileSerializer.hpp>
#include <core/StringUtils.hpp>

#include <core/BoostErrors.hpp>

#define DEBUG(__X__)                                                           \
   do                                                                          \
   {                                                                           \
      if (::rstudio::core::FileLock::isLoggingEnabled())                       \
      {                                                                        \
         std::stringstream ss;                                                 \
         ss << "(PID " << ::getpid() << "): " << __X__;                        \
         LOG_DEBUG_MESSAGE(ss.str());                                          \
      }                                                                        \
   } while (0)

// we define BOOST_USE_WINDOWS_H on mingw64 to work around some
// incompatabilities. however, this prevents the interprocess headers
// from compiling so we undef it in this localized context
#if defined(__GNUC__) && defined(_WIN64)
   #undef BOOST_USE_WINDOWS_H
#endif
#include <boost/interprocess/sync/file_lock.hpp>

namespace rstudio {
namespace core {

namespace {
typedef boost::interprocess::file_lock BoostFileLock;
}

struct AdvisoryFileLock::Impl
{
   FilePath lockFilePath;
   BoostFileLock lock;
};

bool AdvisoryFileLock::isLocked(const FilePath& lockFilePath) const
{
   // if the lock file doesn't exist then it's not locked
   if (!lockFilePath.exists())
      return false;

   // check if it is locked
   try
   {
      BoostFileLock lock(string_utils::utf8ToSystem(lockFilePath.absolutePath()).c_str());

      if (lock.try_lock())
      {
         lock.unlock();
         return false;
      }
      else
      {
         return true;
      }
   }
   catch(boost::interprocess::interprocess_exception& e)
   {
      Error error(boost::interprocess::ec_from_exception(e), ERROR_LOCATION);
      error.addProperty("lock-file", lockFilePath);
      LOG_ERROR(error);
      return false;
   }
}

AdvisoryFileLock::AdvisoryFileLock()
   : pImpl_(new Impl())
{
}

AdvisoryFileLock::~AdvisoryFileLock()
{
}

Error AdvisoryFileLock::acquire(const FilePath& lockFilePath)
{
   using namespace boost::interprocess;

   // make sure the lock file exists
   if (!lockFilePath.exists())
   {
      Error error = core::writeStringToFile(lockFilePath, "");
      if (error)
         return error;
   }

   // try to acquire the lock
   try
   {
      BoostFileLock lock(string_utils::utf8ToSystem(lockFilePath.absolutePath()).c_str());

      if (lock.try_lock())
      {
         DEBUG("Acquired lock: " << lockFilePath.absolutePath());
         // set members
         pImpl_->lockFilePath = lockFilePath;
         pImpl_->lock.swap(lock);

         return Success();
      }
      else
      {
         DEBUG("Failed to acquire lock: " << lockFilePath.absolutePath());
         return systemError(boost::system::errc::no_lock_available,
                            ERROR_LOCATION);
      }
   }
   catch(interprocess_exception& e)
   {
      Error error(ec_from_exception(e), ERROR_LOCATION);
      error.addProperty("lock-file", lockFilePath);
      return error;
   }

   return Success();
}

Error AdvisoryFileLock::release()
{
   using namespace boost::interprocess;

   // make sure the lock file exists
   if (!pImpl_->lockFilePath.exists())
   {
      return systemError(boost::system::errc::no_lock_available,
                         ERROR_LOCATION);
   }

   // always cleanup the lock file on exit
   FilePath lockFilePath = pImpl_->lockFilePath;
   BOOST_SCOPE_EXIT( (&lockFilePath) )
   {
      Error error = lockFilePath.remove();
      if (error)
         LOG_ERROR(error);
   }
   BOOST_SCOPE_EXIT_END

   // try to unlock it
   try
   {
      pImpl_->lock.unlock();
      pImpl_->lock = BoostFileLock();
      DEBUG("Released lock: " << pImpl_->lockFilePath.absolutePath());
      pImpl_->lockFilePath = FilePath();
      return Success();
   }
   catch(interprocess_exception& e)
   {
      Error error(ec_from_exception(e), ERROR_LOCATION);
      error.addProperty("lock-file", pImpl_->lockFilePath);
      return error;
   }

   return Success();
}

FilePath AdvisoryFileLock::lockFilePath() const
{
   return pImpl_->lockFilePath;
}

void AdvisoryFileLock::refresh()
{
}

void AdvisoryFileLock::cleanUp()
{
}

} // namespace core
} // namespace rstudio

<|endoftext|>


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

#include "html5_filesystem.h"

#include <fcntl.h>
#include <sstream>
#include <string.h>
#include <unistd.h>

#include "naclfs.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_file_io.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/dev/directory_entry_dev.h"
#include "ppapi/cpp/dev/directory_reader_dev.h"
#include "ppapi/cpp/file_io.h"
#include "ppapi/cpp/file_ref.h"
#include "ppapi/cpp/file_system.h"
#include "ppapi/cpp/var.h"

namespace {

class Html5FileSystemDir : public naclfs::FileSystem::Dir {
 public:
  Html5FileSystemDir(naclfs::Html5FileSystem* owner,
		     const pp::FileRef& directory_ref)
    : Dir(owner),
      reader_(new pp::DirectoryReader_Dev(directory_ref)) {}
  virtual ~Html5FileSystemDir() {}

  int32_t ReadDir(const pp::CompletionCallback& cc) {
    return reader_->GetNextEntry(&entry_, cc);
  }

  struct dirent* ReadDirComplete() {
    memset(&dirent_, 0, sizeof(struct dirent));
    /*
    switch (entry_.file_type()) {
      case PP_FILETYPE_REGULAR:
	dirent_.d_type = DT_REG;
	break;
      case PP_FILETYPE_DIRECTORY
	dirent._d_type = DT_DIR;
	break;
      case PP_FILETYPE_OTHER:
      default:
	dirent._d_type = DT_UNKNOWN;
	break;
    }
    */
    std::string name = entry_.file_ref().GetName().AsString();
    strncpy(dirent_.d_name, name.c_str(), 256);
    if (name.length() > 255)
      dirent_.d_name[255] = 0;
    return &dirent_;
  }

 private:
  pp::DirectoryReader_Dev* reader_;
  pp::DirectoryEntry_Dev entry_;
  struct dirent dirent_;
};

};  // namespace

namespace naclfs {

pp::FileSystem* Html5FileSystem::filesystem_ = NULL;

Html5FileSystem::Html5FileSystem(NaClFs* naclfs)
    : file_ref_(NULL),
      file_io_(NULL),
      naclfs_(naclfs),
      waiting_(false),
      querying_(false),
      offset_(0) {
}

Html5FileSystem::~Html5FileSystem() {
  // TODO: Fix memory leaks on file_io_ and file_ref_.
  delete file_io_;
  delete file_ref_;
}

int Html5FileSystem::OpenCall(Arguments* arguments,
			      const char* path,
			      int oflag, ...) {
  if (!filesystem_)
    return Initialize(arguments);

  if (waiting_) {
    waiting_ = false;
    if (arguments->result.callback != 0)
      return -1;
    querying_ = true;
    file_io_->Query(&file_info_, callback_);
    arguments->chaining = true;
    return 0;
  }

  if (querying_) {
    querying_ = false;
    if (arguments->result.callback != 0)
      return -1;
    if (oflag & O_APPEND)
      offset_ = file_info_.size;
    return 0;
  }

  file_ref_ = new pp::FileRef(*filesystem_, path);
  file_io_ = new pp::FileIO(naclfs_->GetInstance());
  int32_t flags = 0;
  switch (oflag & O_ACCMODE) {
    case O_RDONLY:
      flags = PP_FILEOPENFLAG_READ;
      oflag &= ~O_ACCMODE;
      break;
    case O_WRONLY:
      flags = PP_FILEOPENFLAG_WRITE;
      oflag &= ~O_ACCMODE;
      break;
    case O_RDWR:
      flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE;
      oflag &= ~O_ACCMODE;
      break;
  }
  if (oflag & O_CREAT)
    flags |= PP_FILEOPENFLAG_CREATE;
  if (oflag & O_TRUNC)
    flags |= PP_FILEOPENFLAG_TRUNCATE;
  if (oflag & O_EXCL)
    flags |= PP_FILEOPENFLAG_EXCLUSIVE;
  oflag &= ~(O_CREAT | O_TRUNC | O_EXCL | O_APPEND);
  if (oflag) {
    std::stringstream ss;
    ss << "Html5FileSystem::Open ignore unsupporting oflag: " << oflag <<
        std::endl;
    naclfs_->Log(ss.str().c_str());
  }
  if (file_io_->Open(*file_ref_, flags, callback_) !=
      PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::Open doesn't return PP_OK_COMPLETIONPENDING\n");
    return -1;
  }
  waiting_ = true;
  arguments->chaining = true;
  return 0;
}

ssize_t Html5FileSystem::ReadCall(Arguments* arguments,
				  void* buf,
				  size_t nbytes) {
  if (waiting_) {
    waiting_ = false;
    if (0 == arguments->result.callback)
      return EOF;
    offset_ += arguments->result.callback;
    return arguments->result.callback;
  }

  if (file_io_->Read(offset_, static_cast<char*>(buf), nbytes, callback_) !=
      PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::Read doesn't return PP_OK_COMPLETIONPENDING\n");
    return -1;
  }
  waiting_ = true;
  arguments->chaining = true;
  return 0;
}

ssize_t Html5FileSystem::WriteCall(Arguments* arguments,
				   const void* buf,
				   size_t nbytes) {
  if (waiting_) {
    waiting_ = false;
    offset_ += arguments->result.callback;
    return arguments->result.callback;
  }

  if (file_io_->Write(
          offset_, static_cast<const char*>(buf), nbytes, callback_) !=
      PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::Write doesn't return PP_OK_COMPLETIONPENDING\n");
    return -1;
  }
  waiting_ = true;
  arguments->chaining = true;
  return 0;
}

off_t Html5FileSystem::LseekCall(Arguments* arguments,
				 off_t offset,
				 int whence) {
  switch (whence) {
    case SEEK_SET:
      offset_ = offset;
      break;
    case SEEK_CUR:
      offset_ += offset;
      break;
    case SEEK_END:
      offset_ = file_info_.size + offset;
      break;
    default:
      naclfs_->Log("Html5FileSystem::Lseek invalid whence\n");
      return -1;
  }
  return offset_;
}

int Html5FileSystem::FcntlCall(Arguments* arguments, int cmd, ...) {
  naclfs_->Log("Html5FileSystem::Fcntl not supported\n");
  return -1;
}

int Html5FileSystem::CloseCall(Arguments* arguments) {
  file_io_->Close();
  return 0;
}

int Html5FileSystem::StatCall(Arguments* arguments,
			      const char* path,
			      struct stat* buf) {
  if (!filesystem_)
    return Initialize(arguments);

  if (waiting_) {
    waiting_ = false;
    // TODO: Queries on directories seem to fail with error code -2.
    if (arguments->result.callback != 0)
      return -1;
    querying_ = true;
    file_io_->Query(&file_info_, callback_);
    arguments->chaining = true;
    return 0;
  }

  if (querying_) {
    querying_ = false;
    if (arguments->result.callback != 0)
      return -1;
    if (NULL == buf)
      return 0;
    memset(buf, 0, sizeof(struct stat));
    buf->st_mode = S_IRUSR | S_IWUSR | S_IXUSR;
    buf->st_size = file_info_.size;
    buf->st_atime = file_info_.last_access_time;
    buf->st_mtime = file_info_.last_modified_time;
    buf->st_ctime = file_info_.creation_time;
    buf->st_blksize = 512;  // pseudo value for compatilibity
    buf->st_blocks = (file_info_.size + 511) >> 9;
    switch (file_info_.type) {
      case PP_FILETYPE_REGULAR:
	buf->st_mode |= S_IFREG;
	break;
      case PP_FILETYPE_DIRECTORY:
	buf->st_mode |= S_IFDIR;
	break;
      case PP_FILETYPE_OTHER:
      default:
	break;
    }
    return 0;
  }

  file_ref_ = new pp::FileRef(*filesystem_, path);
  file_io_ = new pp::FileIO(naclfs_->GetInstance());
  if (file_io_->Open(*file_ref_, 0, callback_) != PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::Open doesn't return PP_OK_COMPLETIONPENDING\n");
    waiting_ = false;
    return -1;
  }
  waiting_ = true;
  arguments->chaining = true;
  return 0;
}

DIR* Html5FileSystem::OpenDirCall(Arguments* arguments, const char* dirname) {
  if (!filesystem_) {
    Initialize(arguments);
    return NULL;
  }

  pp::FileRef file_ref(*filesystem_, dirname);
  Html5FileSystemDir* dir = new Html5FileSystemDir(this, file_ref);
  return reinterpret_cast<DIR*>(dir);
}

void Html5FileSystem::RewindDirCall(Arguments* arguments, DIR* dirp) {
  // TODO
}

struct dirent* Html5FileSystem::ReadDirCall(Arguments* arguments, DIR* dirp) {
  Html5FileSystemDir* dir = reinterpret_cast<Html5FileSystemDir*>(dirp);
  if (!dir)
    return NULL;

  if (waiting_) {
    waiting_ = false;
    if (arguments->result.callback != 0) {
      // TODO: Oops, DirectoryReader doesn't work in NaCl yet.
      // See, http://crbug.com/106129
      std::stringstream ss;
      ss << "Html5FileSystem::ReadDir failed with error code " <<
	  arguments->result.callback << "\n";
      naclfs_->Log(ss.str().c_str());
      return NULL;
    }
    return dir->ReadDirComplete();
  }

  if (dir->ReadDir(callback_) != PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::ReadDir doesn't return PP_OK_COMPLETIONPENDING\n");
    return NULL;
  }
  waiting_ = true;
  arguments->chaining = true;
  return NULL;
}

int Html5FileSystem::CloseDirCall(Arguments* arguments, DIR* dirp) {
  // TODO
  return -1;
}

bool Html5FileSystem::HandleMessage(const pp::Var& message) {
  return false;
}

int Html5FileSystem::Initialize(Arguments* arguments) {
  naclfs_->Log("Html5FileSystem: initializing file system...");
  filesystem_ = new pp::FileSystem(naclfs_->GetInstance(),
				   PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  filesystem_->Open(1024 * 1024, callback_);
  naclfs_->Log("done\n");
  arguments->chaining = true;
  return 0;
}

}  // namespace naclfs

<commit_msg>Style fix and add crbug reference<commit_after>//
// Copyright (c) 2012, Takashi TOYOSHIMA <toyoshim@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// - Neither the name of the authors nor the names of its contributors may be
//   used to endorse or promote products derived from this software with out
//   specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUE
// NTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//

#include "html5_filesystem.h"

#include <fcntl.h>
#include <sstream>
#include <string.h>
#include <unistd.h>

#include "naclfs.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_file_io.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/dev/directory_entry_dev.h"
#include "ppapi/cpp/dev/directory_reader_dev.h"
#include "ppapi/cpp/file_io.h"
#include "ppapi/cpp/file_ref.h"
#include "ppapi/cpp/file_system.h"
#include "ppapi/cpp/var.h"

namespace {

class Html5FileSystemDir : public naclfs::FileSystem::Dir {
 public:
  Html5FileSystemDir(naclfs::Html5FileSystem* owner,
                     const pp::FileRef& directory_ref)
    : Dir(owner),
      reader_(new pp::DirectoryReader_Dev(directory_ref)) {}
  virtual ~Html5FileSystemDir() {}

  int32_t ReadDir(const pp::CompletionCallback& cc) {
    return reader_->GetNextEntry(&entry_, cc);
  }

  struct dirent* ReadDirComplete() {
    memset(&dirent_, 0, sizeof(struct dirent));
    switch (entry_.file_type()) {
      case PP_FILETYPE_REGULAR:
        dirent_.d_type = DT_REG;
        break;
      case PP_FILETYPE_DIRECTORY
        dirent._d_type = DT_DIR;
        break;
      case PP_FILETYPE_OTHER:
      default:
        dirent._d_type = DT_UNKNOWN;
        break;
    }
    std::string name = entry_.file_ref().GetName().AsString();
    strncpy(dirent_.d_name, name.c_str(), 256);
    if (name.length() > 255)
      dirent_.d_name[255] = 0;
    return &dirent_;
  }

 private:
  pp::DirectoryReader_Dev* reader_;
  pp::DirectoryEntry_Dev entry_;
  struct dirent dirent_;
};

};  // namespace

namespace naclfs {

pp::FileSystem* Html5FileSystem::filesystem_ = NULL;

Html5FileSystem::Html5FileSystem(NaClFs* naclfs)
    : file_ref_(NULL),
      file_io_(NULL),
      naclfs_(naclfs),
      waiting_(false),
      querying_(false),
      offset_(0) {
}

Html5FileSystem::~Html5FileSystem() {
  // TODO: Fix memory leaks on file_io_ and file_ref_.
  delete file_io_;
  delete file_ref_;
}

int Html5FileSystem::OpenCall(Arguments* arguments,
                              const char* path,
                              int oflag, ...) {
  if (!filesystem_)
    return Initialize(arguments);

  if (waiting_) {
    waiting_ = false;
    if (arguments->result.callback != 0)
      return -1;
    querying_ = true;
    file_io_->Query(&file_info_, callback_);
    arguments->chaining = true;
    return 0;
  }

  if (querying_) {
    querying_ = false;
    if (arguments->result.callback != 0)
      return -1;
    if (oflag & O_APPEND)
      offset_ = file_info_.size;
    return 0;
  }

  file_ref_ = new pp::FileRef(*filesystem_, path);
  file_io_ = new pp::FileIO(naclfs_->GetInstance());
  int32_t flags = 0;
  switch (oflag & O_ACCMODE) {
    case O_RDONLY:
      flags = PP_FILEOPENFLAG_READ;
      oflag &= ~O_ACCMODE;
      break;
    case O_WRONLY:
      flags = PP_FILEOPENFLAG_WRITE;
      oflag &= ~O_ACCMODE;
      break;
    case O_RDWR:
      flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE;
      oflag &= ~O_ACCMODE;
      break;
  }
  if (oflag & O_CREAT)
    flags |= PP_FILEOPENFLAG_CREATE;
  if (oflag & O_TRUNC)
    flags |= PP_FILEOPENFLAG_TRUNCATE;
  if (oflag & O_EXCL)
    flags |= PP_FILEOPENFLAG_EXCLUSIVE;
  oflag &= ~(O_CREAT | O_TRUNC | O_EXCL | O_APPEND);
  if (oflag) {
    std::stringstream ss;
    ss << "Html5FileSystem::Open ignore unsupporting oflag: " << oflag <<
        std::endl;
    naclfs_->Log(ss.str().c_str());
  }
  if (file_io_->Open(*file_ref_, flags, callback_) !=
      PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::Open doesn't return PP_OK_COMPLETIONPENDING\n");
    return -1;
  }
  waiting_ = true;
  arguments->chaining = true;
  return 0;
}

ssize_t Html5FileSystem::ReadCall(Arguments* arguments,
                                  void* buf,
                                  size_t nbytes) {
  if (waiting_) {
    waiting_ = false;
    if (0 == arguments->result.callback)
      return EOF;
    offset_ += arguments->result.callback;
    return arguments->result.callback;
  }

  if (file_io_->Read(offset_, static_cast<char*>(buf), nbytes, callback_) !=
      PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::Read doesn't return PP_OK_COMPLETIONPENDING\n");
    return -1;
  }
  waiting_ = true;
  arguments->chaining = true;
  return 0;
}

ssize_t Html5FileSystem::WriteCall(Arguments* arguments,
                                   const void* buf,
                                   size_t nbytes) {
  if (waiting_) {
    waiting_ = false;
    offset_ += arguments->result.callback;
    return arguments->result.callback;
  }

  if (file_io_->Write(
          offset_, static_cast<const char*>(buf), nbytes, callback_) !=
      PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::Write doesn't return PP_OK_COMPLETIONPENDING\n");
    return -1;
  }
  waiting_ = true;
  arguments->chaining = true;
  return 0;
}

off_t Html5FileSystem::LseekCall(Arguments* arguments,
                                 off_t offset,
                                 int whence) {
  switch (whence) {
    case SEEK_SET:
      offset_ = offset;
      break;
    case SEEK_CUR:
      offset_ += offset;
      break;
    case SEEK_END:
      offset_ = file_info_.size + offset;
      break;
    default:
      naclfs_->Log("Html5FileSystem::Lseek invalid whence\n");
      return -1;
  }
  return offset_;
}

int Html5FileSystem::FcntlCall(Arguments* arguments, int cmd, ...) {
  naclfs_->Log("Html5FileSystem::Fcntl not supported\n");
  return -1;
}

int Html5FileSystem::CloseCall(Arguments* arguments) {
  file_io_->Close();
  return 0;
}

int Html5FileSystem::StatCall(Arguments* arguments,
                              const char* path,
                              struct stat* buf) {
  if (!filesystem_)
    return Initialize(arguments);

  if (waiting_) {
    waiting_ = false;
    // TODO: Queries on directories seem to fail with error code -2.
    // See, http://crbug.com/132201
    if (arguments->result.callback != 0)
      return -1;
    querying_ = true;
    file_io_->Query(&file_info_, callback_);
    arguments->chaining = true;
    return 0;
  }

  if (querying_) {
    querying_ = false;
    if (arguments->result.callback != 0)
      return -1;
    if (NULL == buf)
      return 0;
    memset(buf, 0, sizeof(struct stat));
    buf->st_mode = S_IRUSR | S_IWUSR | S_IXUSR;
    buf->st_size = file_info_.size;
    buf->st_atime = file_info_.last_access_time;
    buf->st_mtime = file_info_.last_modified_time;
    buf->st_ctime = file_info_.creation_time;
    buf->st_blksize = 512;  // pseudo value for compatilibity
    buf->st_blocks = (file_info_.size + 511) >> 9;
    switch (file_info_.type) {
      case PP_FILETYPE_REGULAR:
        buf->st_mode |= S_IFREG;
        break;
      case PP_FILETYPE_DIRECTORY:
        buf->st_mode |= S_IFDIR;
        break;
      case PP_FILETYPE_OTHER:
      default:
        break;
    }
    return 0;
  }

  file_ref_ = new pp::FileRef(*filesystem_, path);
  file_io_ = new pp::FileIO(naclfs_->GetInstance());
  if (file_io_->Open(*file_ref_, 0, callback_) != PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::Open doesn't return PP_OK_COMPLETIONPENDING\n");
    waiting_ = false;
    return -1;
  }
  waiting_ = true;
  arguments->chaining = true;
  return 0;
}

DIR* Html5FileSystem::OpenDirCall(Arguments* arguments, const char* dirname) {
  if (!filesystem_) {
    Initialize(arguments);
    return NULL;
  }

  pp::FileRef file_ref(*filesystem_, dirname);
  Html5FileSystemDir* dir = new Html5FileSystemDir(this, file_ref);
  return reinterpret_cast<DIR*>(dir);
}

void Html5FileSystem::RewindDirCall(Arguments* arguments, DIR* dirp) {
  // TODO
}

struct dirent* Html5FileSystem::ReadDirCall(Arguments* arguments, DIR* dirp) {
  Html5FileSystemDir* dir = reinterpret_cast<Html5FileSystemDir*>(dirp);
  if (!dir)
    return NULL;

  if (waiting_) {
    waiting_ = false;
    if (arguments->result.callback != 0) {
      // TODO: Oops, DirectoryReader doesn't work in NaCl yet.
      // See, http://crbug.com/106129
      std::stringstream ss;
      ss << "Html5FileSystem::ReadDir failed with error code " <<
          arguments->result.callback << "\n";
      naclfs_->Log(ss.str().c_str());
      return NULL;
    }
    return dir->ReadDirComplete();
  }

  if (dir->ReadDir(callback_) != PP_OK_COMPLETIONPENDING) {
    naclfs_->Log(
        "Html5FileSystem::ReadDir doesn't return PP_OK_COMPLETIONPENDING\n");
    return NULL;
  }
  waiting_ = true;
  arguments->chaining = true;
  return NULL;
}

int Html5FileSystem::CloseDirCall(Arguments* arguments, DIR* dirp) {
  // TODO
  return -1;
}

bool Html5FileSystem::HandleMessage(const pp::Var& message) {
  return false;
}

int Html5FileSystem::Initialize(Arguments* arguments) {
  naclfs_->Log("Html5FileSystem: initializing file system...");
  filesystem_ = new pp::FileSystem(naclfs_->GetInstance(),
                                   PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  filesystem_->Open(1024 * 1024, callback_);
  naclfs_->Log("done\n");
  arguments->chaining = true;
  return 0;
}

}  // namespace naclfs

<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Hunspell, based on MySpell.
 *
 * The Initial Developers of the Original Code are
 * Kevin Hendricks (MySpell) and Németh László (Hunspell).
 * Portions created by the Initial Developers are Copyright (C) 2002-2005
 * the Initial Developers. All Rights Reserved.
 *
 * Contributor(s): David Einstein, Davide Prina, Giuseppe Modugno,
 * Gianluca Turconi, Simon Brouwer, Noll János, Bíró Árpád,
 * Goldman Eleonóra, Sarlós Tamás, Bencsáth Boldizsár, Halácsy Péter,
 * Dvornik László, Gefferth András, Nagy Viktor, Varga Dániel, Chris Halls,
 * Rene Engelhard, Bram Moolenaar, Dafydd Jones, Harri Pitkänen
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#ifndef W_CHAR_HXX_
#define W_CHAR_HXX_

#include <string>
#include <vector>

#ifndef GCC
struct w_char {
#else
struct __attribute__((packed)) w_char {
#endif
  unsigned char l;
  unsigned char h;

  friend bool operator<(const w_char a, const w_char b) {
    unsigned short a_idx = (a.h << 8) + a.l;
    unsigned short b_idx = (b.h << 8) + b.l;
    return a_idx < b_idx;
  }

  friend bool operator==(const w_char a, const w_char b) {
    return (((a).l == (b).l) && ((a).h == (b).h));
  }

  friend bool operator!=(const w_char a, const w_char b) {
    return !(a == b);;
  }
};

// two character arrays
struct replentry {
  std::string pattern;
  std::string outstrings[4]; // med, ini, fin, isol
};

namespace wide
{
#if __cplusplus >= 201103L
    typedef std::basic_string<w_char> string;
#else
    typedef vector<w_char> string;
#endif
}

#endif
<commit_msg>looks like none of the ci are c++11<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Hunspell, based on MySpell.
 *
 * The Initial Developers of the Original Code are
 * Kevin Hendricks (MySpell) and Németh László (Hunspell).
 * Portions created by the Initial Developers are Copyright (C) 2002-2005
 * the Initial Developers. All Rights Reserved.
 *
 * Contributor(s): David Einstein, Davide Prina, Giuseppe Modugno,
 * Gianluca Turconi, Simon Brouwer, Noll János, Bíró Árpád,
 * Goldman Eleonóra, Sarlós Tamás, Bencsáth Boldizsár, Halácsy Péter,
 * Dvornik László, Gefferth András, Nagy Viktor, Varga Dániel, Chris Halls,
 * Rene Engelhard, Bram Moolenaar, Dafydd Jones, Harri Pitkänen
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#ifndef W_CHAR_HXX_
#define W_CHAR_HXX_

#include <string>
#include <vector>

#ifndef GCC
struct w_char {
#else
struct __attribute__((packed)) w_char {
#endif
  unsigned char l;
  unsigned char h;

  friend bool operator<(const w_char a, const w_char b) {
    unsigned short a_idx = (a.h << 8) + a.l;
    unsigned short b_idx = (b.h << 8) + b.l;
    return a_idx < b_idx;
  }

  friend bool operator==(const w_char a, const w_char b) {
    return (((a).l == (b).l) && ((a).h == (b).h));
  }

  friend bool operator!=(const w_char a, const w_char b) {
    return !(a == b);;
  }
};

// two character arrays
struct replentry {
  std::string pattern;
  std::string outstrings[4]; // med, ini, fin, isol
};

namespace wide
{
#if __cplusplus >= 201103L
    typedef std::basic_string<w_char> string;
#else
    typedef std::vector<w_char> string;
#endif
}

#endif
<|endoftext|>