<commit_before>#include "Game.hpp"
#include "../Window/GlfwError.hpp"
#include "../Util/WarnGuard.hpp"
WARN_GUARD_ON
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "../Graphics/Image/Jpeg/JpegLoader.hpp"
#include "../Graphics/Image/Png/Png.hpp"
#include "../Graphics/Model/ModelLoader.hpp"
WARN_GUARD_OFF
#include "../Util/FileLoad.hpp"

///==============================================================
///= Game
///==============================================================
// BufferType for the files loaded
using BufferType = std::vector<std::uint8_t>;

Game::Game()
{
}

void Game::Init()
{
    // Setup window and input
    SetupWindow();

    // Initialize the renderer
    renderer.Init();

    // Set the initial draw mode
    mDrawMode = GL_FILL;

    // Cube rotation state
    mRotationData.degreesInc = 0.05f;
    mRotationData.rotating = false;

    // Camera initial position
    mCamera.SetPos(glm::vec3(0, 0, 8));

    // Load the textures
    LoadTextures();

    // Load the models
    LoadModels();

    // Load the shaders
    LoadShaders();

    // Create world objects
    SetupWorld();
}

void Game::SetupWorld()
{
    // Retrieve the world from the renderer
    auto& world = renderer.GetWorld();

    //
    // Normal objects
    //
    std::vector<Renderer::WorldObject> normalObjects;
    // Create various Cube instances in the world
    std::vector<glm::vec3> cubePositions = {
        glm::vec3(0.0f, 0.0f, 0.0f),
        glm::vec3(4.0f, 10.0f, -20.0f),
        glm::vec3(-3.0f, -4.4f, -5.0f),
        glm::vec3(-7.6f, -4.0f, -14.0f),
        glm::vec3(4.4f, -3.5f, -4.0f),
        glm::vec3(-3.4f, 6.0f, -15.0f),
        glm::vec3(2.6f, -4.0f, -17.0f),
        glm::vec3(4.0f, 3.0f, -5.0f),
        glm::vec3(3.0f, 0.4f, -12.0f),
        glm::vec3(-3.5f, 2.0f, -3.0f)
    };
    for (std::size_t i = 0; i < cubePositions.size(); ++i)
    {
        const auto& pos = cubePositions[i];

        Transform trans;
        trans.Move(pos);
        trans.Scale(glm::vec3(2.0f));
        trans.RotateX(20.0f * i);
        trans.RotateY(7.0f * i);
        trans.RotateZ(10.0f * i);
        normalObjects.push_back({trans, "cube"});
    }

    // Add house
    {
        Transform trans;
        trans.Move(glm::vec3(0.0f, -10.0f, -40.0f));
        trans.Scale(glm::vec3(0.3f));
        normalObjects.push_back({trans, "house"});
    }
    world.insert({"normal", normalObjects});

    //
    // Light objects
    //
    std::vector<Renderer::WorldObject> lightObjects;

    // Add cube lights
    {
        Transform trans;
        trans.Move(glm::vec3(4.0f, 0.0f, 0.0f));
        trans.Scale(glm::vec3(0.3f));
        lightObjects.push_back({trans, "teapot"});
    }
    world.insert({"light", lightObjects});
    renderer.mLight = &world["light"].back();
}

void Game::SetupWindow()
{
    // Setup window
    bool success = mWindow.Create(800, 600, "TheRoom", Window::Mode::Windowed);
    if (!success)
        throw std::runtime_error(GetLastGlfwError().GetDescription());

    mWindow.SetShowFPS(true);
    mWindow.SetCloseHandler(mExitHandler);

    // Setup input event handlers
    mWindow.SetMouseButtonPressHandler(
        [this](MouseButton mb, ButtonAction ba)
        {
            if (mb == MouseButton::Left && ba == ButtonAction::Press)
                mWindow.SetMouseGrabEnabled(true);
        }
    );
    mWindow.SetKeyPressedHandler(
        [this](Key k, KeyAction ka)
        {
            // Exit
            if(k == Key::Escape && ka == KeyAction::Release)
                mExitHandler();
            // Ungrab mouse
            if(k == Key::RightControl && ka == KeyAction::Release)
                mWindow.SetMouseGrabEnabled(false);
            // Toggle polygon mode
            if(k == Key::P && ka == KeyAction::Release)
            {
                if (mDrawMode == GL_FILL)
                    mDrawMode = GL_POINT;
                else if (mDrawMode == GL_POINT)
                    mDrawMode = GL_LINE;
                else if (mDrawMode == GL_LINE)
                    mDrawMode = GL_FILL;
            }
            if(k == Key::R && ka == KeyAction::Release)
                mRotationData.rotating = !mRotationData.rotating;
        }
    );
}

void Game::LoadShaders()
{
    // Retrieve the shaderStore from the renderer
    auto& shaderStore = renderer.GetShaderStore();

    // The shader map
    std::unordered_map<std::string, std::vector<std::pair<ShaderStore::ShaderType,std::string>>> shaders =
    {
        {
            "normal",
            {
                { ShaderStore::ShaderType::Vertex,   "res/normal_vert.glsl" },
                { ShaderStore::ShaderType::Fragment, "res/normal_frag.glsl" },
            }
        },
        {
            "light",
            {
                { ShaderStore::ShaderType::Vertex,   "res/light_vert.glsl" },
                { ShaderStore::ShaderType::Fragment, "res/light_frag.glsl" },
            }
        }
    };

    // Load shaders
    for (const auto& p : shaders)
    {
        // Will temporarily store the id's of the compiled shaders
        std::unordered_map<ShaderStore::ShaderType, GLuint> shaderIds;
        for (const auto& f : p.second)
        {
            // Load file
            auto shaderFile = FileLoad<BufferType>(f.second);
            if (!shaderFile)
                throw std::runtime_error("Could not find shader file: \n" + f.second);
            // Convert it to std::string containter
            std::string shaderSrc((*shaderFile).begin(), (*shaderFile).end());
            GLuint sId = shaderStore.LoadShader(shaderSrc, f.first);
            if (sId == 0)
                throw std::runtime_error("Shader compilation error: \n" + shaderStore.GetLastCompileError());
            // Insert loaded shader id to temp map
            shaderIds.insert({f.first, sId});
        }
        // Fetch vert and frag shader id's from temp map and link
        bool s = shaderStore.LinkProgram(p.first,
            shaderIds[ShaderStore::ShaderType::Vertex],
            shaderIds[ShaderStore::ShaderType::Fragment]);
        if (!s)
            throw std::runtime_error("OpenGL program link error: \n" + shaderStore.GetLastLinkError());
    }
}

void Game::LoadTextures()
{
    // Retrieve the textureStore from the renderer
    auto& textureStore = renderer.GetTextureStore();

    // The JpegLoader object
    JpegLoader jL;

    // The texture map
    std::unordered_map<std::string, std::string> textures =
    {
        {"ext/mahogany_wood.jpg", "mahogany_wood"},
        {"ext/mahogany_wood_spec.jpg", "mahogany_wood_spec"},
        {"ext/WoodenCabin/WoodCabinDif.jpg", "house_diff"},
        {"ext/WoodenCabin/WoodCabinSM.jpg", "house_spec"},
    };

    // Load the textures
    for (const auto& p : textures)
    {
        auto textureFile = FileLoad<BufferType>(p.first);
        if (!textureFile)
            throw std::runtime_error("Could not find file: \n" + p.first);
        RawImage<> pb = jL.Load(*textureFile);
        textureStore.Load(p.second, pb);
    }
}

void Game::LoadModels()
{
    // Retrieve the model and texture stores from the renderer
    auto& modelStore = renderer.GetModelStore();
    auto& textureStore = renderer.GetTextureStore();

    // Model loader instance
    ModelLoader modelLoader;

    // TODO: Add error handling
    // Load the cube
    auto cubeFile = FileLoad<BufferType>("ext/Cube/cube.obj");
    Model cube = modelLoader.Load(*cubeFile, "obj");
    modelStore.Load("cube", std::move(cube));
    modelStore["cube"]->diffTexId = textureStore["mahogany_wood"]->texId;
    modelStore["cube"]->specTexId = textureStore["mahogany_wood_spec"]->texId;

    // Load teapot
    auto teapotFile = FileLoad<BufferType>("ext/teapot.obj");
    Model teapot = modelLoader.Load(*teapotFile, "obj");
    modelStore.Load("teapot", std::move(teapot));

    // Load house
    auto houseFile = FileLoad<BufferType>("ext/WoodenCabin/WoodenCabin.dae");
    Model house = modelLoader.Load(*houseFile, "dae");
    modelStore.Load("house", std::move(house));
    modelStore["house"]->diffTexId = textureStore["house_diff"]->texId;
    modelStore["house"]->specTexId = textureStore["house_spec"]->texId;
}

std::vector<Camera::MoveDirection> Game::CameraMoveDirections()
{
    std::vector<Camera::MoveDirection> mds;
    if(mWindow.IsKeyPressed(Key::W))
        mds.push_back(Camera::MoveDirection::Forward);
    if(mWindow.IsKeyPressed(Key::A))
        mds.push_back(Camera::MoveDirection::Left);
    if(mWindow.IsKeyPressed(Key::S))
        mds.push_back(Camera::MoveDirection::BackWard);
    if(mWindow.IsKeyPressed(Key::D))
        mds.push_back(Camera::MoveDirection::Right);
    return mds;
}

std::tuple<float, float> Game::CameraLookOffset()
{
    std::tuple<double, double> curDiff = mWindow.GetCursorDiff();
    return std::make_tuple(
        static_cast<float>(std::get<0>(curDiff)),
        static_cast<float>(std::get<1>(curDiff))
    );
}

void Game::Update(float dt)
{
    (void) dt;

    // Poll window events
    mWindow.Update();

    // Update the interpolation state of the world
    renderer.Update(dt);

    // Update camera euler angles
    if (mWindow.MouseGrabEnabled())
        mCamera.Look(CameraLookOffset());

    // Update camera position
    mCamera.Move(CameraMoveDirections());

    // Update light position
    auto& trans = renderer.mLight->transform;
    float increase = 0.3f;
    if(mWindow.IsKeyPressed(Key::Kp8))
        trans.Move(glm::vec3(0.0f, increase, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp4))
        trans.Move(glm::vec3(increase, 0.0f, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp2))
        trans.Move(glm::vec3(0.0f, -increase, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp6))
        trans.Move(glm::vec3(-increase, 0.0f, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp5))
        trans.Move(glm::vec3(0.0f, 0.0f, increase));
    if(mWindow.IsKeyPressed(Key::Kp0))
        trans.Move(glm::vec3(0.0f, 0.0f, -increase));

    // Update cubes' rotations
    if (mRotationData.rotating)
    {
        for (auto& p : renderer.GetWorld())
            if (p.first == "normal")
                for (auto& gObj : p.second)
                    gObj.transform.RotateY(mRotationData.degreesInc);
    }
}

void Game::Render(float interpolation)
{
    // Set the polygon mode
    glPolygonMode(GL_FRONT_AND_BACK, mDrawMode);

    // View calculation with camera
    auto lookOffset = mWindow.MouseGrabEnabled() ? CameraLookOffset() : std::make_tuple(0.0f, 0.0f);
    auto iCamState = mCamera.Interpolate(CameraMoveDirections(), lookOffset, interpolation);

    // Create the view matrix and pass it to the renderer
    glm::mat4 view = glm::lookAt(iCamState.position, iCamState.position + iCamState.front, iCamState.up);
    renderer.SetView(view);

    // Render
    renderer.Render(interpolation);

    // Show it
    mWindow.SwapBuffers();
}

void Game::Shutdown()
{
    // Renderer
    renderer.Shutdown();

    // Window
    mWindow.Destroy();
}

void Game::SetExitHandler(std::function<void()> f)
{
    mExitHandler = f;
}
<commit_msg>Teapot now uses generated diffuse and specular texture<commit_after>#include "Game.hpp"
#include "../Window/GlfwError.hpp"
#include "../Util/WarnGuard.hpp"
WARN_GUARD_ON
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "../Graphics/Image/Jpeg/JpegLoader.hpp"
#include "../Graphics/Image/Png/Png.hpp"
#include "../Graphics/Model/ModelLoader.hpp"
WARN_GUARD_OFF
#include "../Util/FileLoad.hpp"

///==============================================================
///= Game
///==============================================================
// BufferType for the files loaded
using BufferType = std::vector<std::uint8_t>;

Game::Game()
{
}

void Game::Init()
{
    // Setup window and input
    SetupWindow();

    // Initialize the renderer
    renderer.Init();

    // Set the initial draw mode
    mDrawMode = GL_FILL;

    // Cube rotation state
    mRotationData.degreesInc = 0.05f;
    mRotationData.rotating = false;

    // Camera initial position
    mCamera.SetPos(glm::vec3(0, 0, 8));

    // Load the textures
    LoadTextures();

    // Load the models
    LoadModels();

    // Load the shaders
    LoadShaders();

    // Create world objects
    SetupWorld();
}

void Game::SetupWorld()
{
    // Retrieve the world from the renderer
    auto& world = renderer.GetWorld();

    //
    // Normal objects
    //
    std::vector<Renderer::WorldObject> normalObjects;
    // Create various Cube instances in the world
    std::vector<glm::vec3> cubePositions = {
        glm::vec3(0.0f, 0.0f, 0.0f),
        glm::vec3(4.0f, 10.0f, -20.0f),
        glm::vec3(-3.0f, -4.4f, -5.0f),
        glm::vec3(-7.6f, -4.0f, -14.0f),
        glm::vec3(4.4f, -3.5f, -4.0f),
        glm::vec3(-3.4f, 6.0f, -15.0f),
        glm::vec3(2.6f, -4.0f, -17.0f),
        glm::vec3(4.0f, 3.0f, -5.0f),
        glm::vec3(3.0f, 0.4f, -12.0f),
        glm::vec3(-3.5f, 2.0f, -3.0f)
    };
    for (std::size_t i = 0; i < cubePositions.size(); ++i)
    {
        const auto& pos = cubePositions[i];

        Transform trans;
        trans.Move(pos);
        trans.Scale(glm::vec3(2.0f));
        trans.RotateX(20.0f * i);
        trans.RotateY(7.0f * i);
        trans.RotateZ(10.0f * i);
        normalObjects.push_back({trans, "cube"});
    }

    // Add house
    {
        Transform trans;
        trans.Move(glm::vec3(0.0f, -10.0f, -40.0f));
        trans.Scale(glm::vec3(0.3f));
        normalObjects.push_back({trans, "house"});
    }
    world.insert({"normal", normalObjects});

    //
    // Light objects
    //
    std::vector<Renderer::WorldObject> lightObjects;

    // Add cube lights
    {
        Transform trans;
        trans.Move(glm::vec3(4.0f, 0.0f, 0.0f));
        trans.Scale(glm::vec3(0.3f));
        lightObjects.push_back({trans, "teapot"});
    }
    world.insert({"light", lightObjects});
    renderer.mLight = &world["light"].back();
}

void Game::SetupWindow()
{
    // Setup window
    bool success = mWindow.Create(800, 600, "TheRoom", Window::Mode::Windowed);
    if (!success)
        throw std::runtime_error(GetLastGlfwError().GetDescription());

    mWindow.SetShowFPS(true);
    mWindow.SetCloseHandler(mExitHandler);

    // Setup input event handlers
    mWindow.SetMouseButtonPressHandler(
        [this](MouseButton mb, ButtonAction ba)
        {
            if (mb == MouseButton::Left && ba == ButtonAction::Press)
                mWindow.SetMouseGrabEnabled(true);
        }
    );
    mWindow.SetKeyPressedHandler(
        [this](Key k, KeyAction ka)
        {
            // Exit
            if(k == Key::Escape && ka == KeyAction::Release)
                mExitHandler();
            // Ungrab mouse
            if(k == Key::RightControl && ka == KeyAction::Release)
                mWindow.SetMouseGrabEnabled(false);
            // Toggle polygon mode
            if(k == Key::P && ka == KeyAction::Release)
            {
                if (mDrawMode == GL_FILL)
                    mDrawMode = GL_POINT;
                else if (mDrawMode == GL_POINT)
                    mDrawMode = GL_LINE;
                else if (mDrawMode == GL_LINE)
                    mDrawMode = GL_FILL;
            }
            if(k == Key::R && ka == KeyAction::Release)
                mRotationData.rotating = !mRotationData.rotating;
        }
    );
}

void Game::LoadShaders()
{
    // Retrieve the shaderStore from the renderer
    auto& shaderStore = renderer.GetShaderStore();

    // The shader map
    std::unordered_map<std::string, std::vector<std::pair<ShaderStore::ShaderType,std::string>>> shaders =
    {
        {
            "normal",
            {
                { ShaderStore::ShaderType::Vertex,   "res/normal_vert.glsl" },
                { ShaderStore::ShaderType::Fragment, "res/normal_frag.glsl" },
            }
        },
        {
            "light",
            {
                { ShaderStore::ShaderType::Vertex,   "res/light_vert.glsl" },
                { ShaderStore::ShaderType::Fragment, "res/light_frag.glsl" },
            }
        }
    };

    // Load shaders
    for (const auto& p : shaders)
    {
        // Will temporarily store the id's of the compiled shaders
        std::unordered_map<ShaderStore::ShaderType, GLuint> shaderIds;
        for (const auto& f : p.second)
        {
            // Load file
            auto shaderFile = FileLoad<BufferType>(f.second);
            if (!shaderFile)
                throw std::runtime_error("Could not find shader file: \n" + f.second);
            // Convert it to std::string containter
            std::string shaderSrc((*shaderFile).begin(), (*shaderFile).end());
            GLuint sId = shaderStore.LoadShader(shaderSrc, f.first);
            if (sId == 0)
                throw std::runtime_error("Shader compilation error: \n" + shaderStore.GetLastCompileError());
            // Insert loaded shader id to temp map
            shaderIds.insert({f.first, sId});
        }
        // Fetch vert and frag shader id's from temp map and link
        bool s = shaderStore.LinkProgram(p.first,
            shaderIds[ShaderStore::ShaderType::Vertex],
            shaderIds[ShaderStore::ShaderType::Fragment]);
        if (!s)
            throw std::runtime_error("OpenGL program link error: \n" + shaderStore.GetLastLinkError());
    }
}

void Game::LoadTextures()
{
    // Retrieve the textureStore from the renderer
    auto& textureStore = renderer.GetTextureStore();

    // The JpegLoader object
    JpegLoader jL;

    // The texture map
    std::unordered_map<std::string, std::string> textures =
    {
        {"ext/mahogany_wood.jpg", "mahogany_wood"},
        {"ext/mahogany_wood_spec.jpg", "mahogany_wood_spec"},
        {"ext/WoodenCabin/WoodCabinDif.jpg", "house_diff"},
        {"ext/WoodenCabin/WoodCabinSM.jpg", "house_spec"},
    };

    // Load the textures
    for (const auto& p : textures)
    {
        auto textureFile = FileLoad<BufferType>(p.first);
        if (!textureFile)
            throw std::runtime_error("Could not find file: \n" + p.first);
        RawImage<> pb = jL.Load(*textureFile);
        textureStore.Load(p.second, pb);
    }

    // Add calculated textures
    RawImage<> pb({0xFF, 0xFF, 0xFF}, {1, 1, 3});
    textureStore.Load("white", pb);
    RawImage<> pb2({0x00, 0x00, 0x00}, {1, 1, 3});
    textureStore.Load("white_spec", pb2);
}

void Game::LoadModels()
{
    // Retrieve the model and texture stores from the renderer
    auto& modelStore = renderer.GetModelStore();
    auto& textureStore = renderer.GetTextureStore();

    // Model loader instance
    ModelLoader modelLoader;

    // TODO: Add error handling
    // Load the cube
    auto cubeFile = FileLoad<BufferType>("ext/Cube/cube.obj");
    Model cube = modelLoader.Load(*cubeFile, "obj");
    modelStore.Load("cube", std::move(cube));
    modelStore["cube"]->diffTexId = textureStore["mahogany_wood"]->texId;
    modelStore["cube"]->specTexId = textureStore["mahogany_wood_spec"]->texId;

    // Load teapot
    auto teapotFile = FileLoad<BufferType>("ext/teapot.obj");
    Model teapot = modelLoader.Load(*teapotFile, "obj");
    modelStore.Load("teapot", std::move(teapot));
    modelStore["teapot"]->diffTexId = textureStore["white"]->texId;
    modelStore["teapot"]->specTexId = textureStore["white_spec"]->texId;

    // Load house
    auto houseFile = FileLoad<BufferType>("ext/WoodenCabin/WoodenCabin.dae");
    Model house = modelLoader.Load(*houseFile, "dae");
    modelStore.Load("house", std::move(house));
    modelStore["house"]->diffTexId = textureStore["house_diff"]->texId;
    modelStore["house"]->specTexId = textureStore["house_spec"]->texId;
}

std::vector<Camera::MoveDirection> Game::CameraMoveDirections()
{
    std::vector<Camera::MoveDirection> mds;
    if(mWindow.IsKeyPressed(Key::W))
        mds.push_back(Camera::MoveDirection::Forward);
    if(mWindow.IsKeyPressed(Key::A))
        mds.push_back(Camera::MoveDirection::Left);
    if(mWindow.IsKeyPressed(Key::S))
        mds.push_back(Camera::MoveDirection::BackWard);
    if(mWindow.IsKeyPressed(Key::D))
        mds.push_back(Camera::MoveDirection::Right);
    return mds;
}

std::tuple<float, float> Game::CameraLookOffset()
{
    std::tuple<double, double> curDiff = mWindow.GetCursorDiff();
    return std::make_tuple(
        static_cast<float>(std::get<0>(curDiff)),
        static_cast<float>(std::get<1>(curDiff))
    );
}

void Game::Update(float dt)
{
    (void) dt;

    // Poll window events
    mWindow.Update();

    // Update the interpolation state of the world
    renderer.Update(dt);

    // Update camera euler angles
    if (mWindow.MouseGrabEnabled())
        mCamera.Look(CameraLookOffset());

    // Update camera position
    mCamera.Move(CameraMoveDirections());

    // Update light position
    auto& trans = renderer.mLight->transform;
    float increase = 0.3f;
    if(mWindow.IsKeyPressed(Key::Kp8))
        trans.Move(glm::vec3(0.0f, increase, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp4))
        trans.Move(glm::vec3(increase, 0.0f, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp2))
        trans.Move(glm::vec3(0.0f, -increase, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp6))
        trans.Move(glm::vec3(-increase, 0.0f, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp5))
        trans.Move(glm::vec3(0.0f, 0.0f, increase));
    if(mWindow.IsKeyPressed(Key::Kp0))
        trans.Move(glm::vec3(0.0f, 0.0f, -increase));

    // Update cubes' rotations
    if (mRotationData.rotating)
    {
        for (auto& p : renderer.GetWorld())
            if (p.first == "normal")
                for (auto& gObj : p.second)
                    gObj.transform.RotateY(mRotationData.degreesInc);
    }
}

void Game::Render(float interpolation)
{
    // Set the polygon mode
    glPolygonMode(GL_FRONT_AND_BACK, mDrawMode);

    // View calculation with camera
    auto lookOffset = mWindow.MouseGrabEnabled() ? CameraLookOffset() : std::make_tuple(0.0f, 0.0f);
    auto iCamState = mCamera.Interpolate(CameraMoveDirections(), lookOffset, interpolation);

    // Create the view matrix and pass it to the renderer
    glm::mat4 view = glm::lookAt(iCamState.position, iCamState.position + iCamState.front, iCamState.up);
    renderer.SetView(view);

    // Render
    renderer.Render(interpolation);

    // Show it
    mWindow.SwapBuffers();
}

void Game::Shutdown()
{
    // Renderer
    renderer.Shutdown();

    // Window
    mWindow.Destroy();
}

void Game::SetExitHandler(std::function<void()> f)
{
    mExitHandler = f;
}
<|endoftext|>


<commit_before>#include "ImageNode.h"
#include "Context.h"
#include "Audio.h"
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QImageReader>
#include <QtQml>
#include "Paths.h"

ImageNode::ImageNode(Context *context, QString file)
    : VideoNode(new ImageNodePrivate(context))
{
    d()->m_openGLWorker = QSharedPointer<ImageNodeOpenGLWorker>(new ImageNodeOpenGLWorker(*this), &QObject::deleteLater);

    setInputCount(1);
    setFile(file);
}

ImageNode::ImageNode(const ImageNode &other)
    : VideoNode(other)
{
}

ImageNode::ImageNode(QSharedPointer<ImageNodePrivate> other_ptr)
    : VideoNode(other_ptr.staticCast<VideoNodePrivate>())
{
}

ImageNode *ImageNode::clone() const {
    return new ImageNode(*this);
}

QSharedPointer<ImageNodePrivate> ImageNode::d() const {
    return d_ptr.staticCast<ImageNodePrivate>();
}

QJsonObject ImageNode::serialize() {
    QJsonObject o = VideoNode::serialize();
    o.insert("file", file());
    return o;
}

QString ImageNode::file() {
    QMutexLocker locker(&d()->m_stateLock);
    return d()->m_file;
}

QString ImageNode::fileToName() {
    return QFileInfo(d()->m_file).baseName();
}

QString ImageNode::name() {
    QMutexLocker locker(&d()->m_stateLock);
    return fileToName();
}

void ImageNode::setFile(QString file) {
    file = Paths::contractLibraryPath(file);
    bool wasFileChanged = false;
    bool wasNameChanged = false;
    QString newName;
    {
        QMutexLocker locker(&d()->m_stateLock);
        auto oldName = fileToName();
        if (file != d()->m_file) {
            wasFileChanged = true;
            d()->m_file = file;
            d()->m_ready = false;
            newName = fileToName();
            if (newName != oldName) wasNameChanged = true;
        }
    }
    if (wasFileChanged) {
        setNodeState(VideoNode::Loading);
        bool result = QMetaObject::invokeMethod(d()->m_openGLWorker.data(), "initialize", Q_ARG(QString, file));
        Q_ASSERT(result);
        emit fileChanged(file);
    }
    if (wasNameChanged) emit nameChanged(newName);
}

GLuint ImageNode::paint(Chain chain, QVector<GLuint> inputTextures) {
    int totalDelay;
    QVector<int> frameDelays;
    QVector<QSharedPointer<QOpenGLTexture>> frameTextures;
    {
        QMutexLocker locker(&d()->m_stateLock);
        if (!d()->m_ready || d()->m_frameTextures.empty())
            return 0;

        totalDelay = d()->m_totalDelay;
        frameDelays = d()->m_frameDelays;
        frameTextures = d()->m_frameTextures;
    }

    auto currentMs = int64_t(context()->timebase()->beat() *  500);
    auto extraMs = currentMs;
    if (totalDelay) {
        extraMs = currentMs % totalDelay;
        if (frameDelays.empty()) {
            for (auto i = 0; i < frameDelays.size(); ++i) {
                if (frameDelays.at(i) >= extraMs)
                    return frameTextures.at(i)->textureId();
            }
        } else {
            auto perFrame = totalDelay / frameTextures.size();;
            auto idx = std::min((unsigned long)(extraMs / perFrame), (unsigned long)(frameTextures.size() - 1));
            return frameTextures.at(idx)->textureId();
        }
    }
    return 0;
}

// ImageNodeOpenGLWorker methods

ImageNodeOpenGLWorker::ImageNodeOpenGLWorker(ImageNode p)
    : OpenGLWorker(p.context()->openGLWorkerContext())
    , m_p(p) {
    connect(this, &ImageNodeOpenGLWorker::message, &p, &ImageNode::message);
    connect(this, &ImageNodeOpenGLWorker::warning, &p, &ImageNode::warning);
    connect(this, &ImageNodeOpenGLWorker::error,   &p, &ImageNode::error);
}

void ImageNodeOpenGLWorker::initialize(QString filename) {
    auto d = m_p.toStrongRef();
    if (d.isNull()) return; // ImageNode was deleted
    ImageNode p(d);

    filename = Paths::expandLibraryPath(filename);
    qDebug() << "New imagenode" << filename;
    QFile file(filename);

    QFileInfo check_file(filename);
    if (!(check_file.exists() && check_file.isFile())) {
        emit error(QString("Could not find \"%1\"").arg(filename));
        p.setNodeState(VideoNode::Broken);
    }

    QImageReader imageReader(filename);
    int nFrames = imageReader.imageCount();
    if (nFrames == 0)
        nFrames = 1; // Returns 0 if animation isn't supported

    int totalDelay;
    QVector<int> frameDelays;
    QVector<QSharedPointer<QOpenGLTexture>> frameTextures;

    frameTextures.resize(nFrames);
    frameDelays.resize(nFrames);

    for (int i = 0; i < nFrames; i++) {
        auto frame = imageReader.read();
        if (frame.isNull()) {
            emit error(QString("Unable to read frame %1 of image: %2").arg(i).arg(imageReader.errorString()));
            p.setNodeState(VideoNode::Broken);
            return;
        }

        frameDelays[i] = imageReader.nextImageDelay();
        if(!frameDelays[i])
            frameDelays[i] = 10;
        frameTextures[i] = QSharedPointer<QOpenGLTexture>::create(frame.mirrored(), QOpenGLTexture::MipMapGeneration::GenerateMipMaps);
    }
    std::partial_sum(frameDelays.begin(),frameDelays.end(),frameDelays.begin());
    totalDelay = frameDelays.back();
    qDebug() << "Successfully loaded image " << filename << " with " << nFrames << "frames, and a total delay of " << totalDelay << "ms";

    {
        QMutexLocker locker(&p.d()->m_stateLock);
        p.d()->m_totalDelay = totalDelay;
        p.d()->m_frameTextures = frameTextures;
        p.d()->m_frameDelays = frameDelays;
        p.d()->m_ready = true;
    }
    glFlush();
    p.setNodeState(VideoNode::Ready);
}

QString ImageNode::typeName() {
    return "ImageNode";
}

VideoNode *ImageNode::deserialize(Context *context, QJsonObject obj) {
    QString name = obj.value("file").toString();
    if (obj.isEmpty()) {
        return nullptr;
    }
    ImageNode *e = new ImageNode(context, name);
    return e;
}

bool ImageNode::canCreateFromFile(QString filename) {
    return QImageReader(filename).canRead();
}

VideoNode *ImageNode::fromFile(Context *context, QString filename) {
    ImageNode *e = new ImageNode(context, filename);
    return e;
}

QMap<QString, QString> ImageNode::customInstantiators() {
    return QMap<QString, QString>();
}

WeakImageNode::WeakImageNode()
{
}

WeakImageNode::WeakImageNode(const ImageNode &other)
    : d_ptr(other.d())
{
}

QSharedPointer<ImageNodePrivate> WeakImageNode::toStrongRef() {
    return d_ptr.toStrongRef();
}

ImageNodePrivate::ImageNodePrivate(Context *context)
    : VideoNodePrivate(context)
{
}
<commit_msg>Remove debug print<commit_after>#include "ImageNode.h"
#include "Context.h"
#include "Audio.h"
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QImageReader>
#include <QtQml>
#include "Paths.h"

ImageNode::ImageNode(Context *context, QString file)
    : VideoNode(new ImageNodePrivate(context))
{
    d()->m_openGLWorker = QSharedPointer<ImageNodeOpenGLWorker>(new ImageNodeOpenGLWorker(*this), &QObject::deleteLater);

    setInputCount(1);
    setFile(file);
}

ImageNode::ImageNode(const ImageNode &other)
    : VideoNode(other)
{
}

ImageNode::ImageNode(QSharedPointer<ImageNodePrivate> other_ptr)
    : VideoNode(other_ptr.staticCast<VideoNodePrivate>())
{
}

ImageNode *ImageNode::clone() const {
    return new ImageNode(*this);
}

QSharedPointer<ImageNodePrivate> ImageNode::d() const {
    return d_ptr.staticCast<ImageNodePrivate>();
}

QJsonObject ImageNode::serialize() {
    QJsonObject o = VideoNode::serialize();
    o.insert("file", file());
    return o;
}

QString ImageNode::file() {
    QMutexLocker locker(&d()->m_stateLock);
    return d()->m_file;
}

QString ImageNode::fileToName() {
    return QFileInfo(d()->m_file).baseName();
}

QString ImageNode::name() {
    QMutexLocker locker(&d()->m_stateLock);
    return fileToName();
}

void ImageNode::setFile(QString file) {
    file = Paths::contractLibraryPath(file);
    bool wasFileChanged = false;
    bool wasNameChanged = false;
    QString newName;
    {
        QMutexLocker locker(&d()->m_stateLock);
        auto oldName = fileToName();
        if (file != d()->m_file) {
            wasFileChanged = true;
            d()->m_file = file;
            d()->m_ready = false;
            newName = fileToName();
            if (newName != oldName) wasNameChanged = true;
        }
    }
    if (wasFileChanged) {
        setNodeState(VideoNode::Loading);
        bool result = QMetaObject::invokeMethod(d()->m_openGLWorker.data(), "initialize", Q_ARG(QString, file));
        Q_ASSERT(result);
        emit fileChanged(file);
    }
    if (wasNameChanged) emit nameChanged(newName);
}

GLuint ImageNode::paint(Chain chain, QVector<GLuint> inputTextures) {
    int totalDelay;
    QVector<int> frameDelays;
    QVector<QSharedPointer<QOpenGLTexture>> frameTextures;
    {
        QMutexLocker locker(&d()->m_stateLock);
        if (!d()->m_ready || d()->m_frameTextures.empty())
            return 0;

        totalDelay = d()->m_totalDelay;
        frameDelays = d()->m_frameDelays;
        frameTextures = d()->m_frameTextures;
    }

    auto currentMs = int64_t(context()->timebase()->beat() *  500);
    auto extraMs = currentMs;
    if (totalDelay) {
        extraMs = currentMs % totalDelay;
        if (frameDelays.empty()) {
            for (auto i = 0; i < frameDelays.size(); ++i) {
                if (frameDelays.at(i) >= extraMs)
                    return frameTextures.at(i)->textureId();
            }
        } else {
            auto perFrame = totalDelay / frameTextures.size();;
            auto idx = std::min((unsigned long)(extraMs / perFrame), (unsigned long)(frameTextures.size() - 1));
            return frameTextures.at(idx)->textureId();
        }
    }
    return 0;
}

// ImageNodeOpenGLWorker methods

ImageNodeOpenGLWorker::ImageNodeOpenGLWorker(ImageNode p)
    : OpenGLWorker(p.context()->openGLWorkerContext())
    , m_p(p) {
    connect(this, &ImageNodeOpenGLWorker::message, &p, &ImageNode::message);
    connect(this, &ImageNodeOpenGLWorker::warning, &p, &ImageNode::warning);
    connect(this, &ImageNodeOpenGLWorker::error,   &p, &ImageNode::error);
}

void ImageNodeOpenGLWorker::initialize(QString filename) {
    auto d = m_p.toStrongRef();
    if (d.isNull()) return; // ImageNode was deleted
    ImageNode p(d);

    filename = Paths::expandLibraryPath(filename);
    QFile file(filename);

    QFileInfo check_file(filename);
    if (!(check_file.exists() && check_file.isFile())) {
        emit error(QString("Could not find \"%1\"").arg(filename));
        p.setNodeState(VideoNode::Broken);
    }

    QImageReader imageReader(filename);
    int nFrames = imageReader.imageCount();
    if (nFrames == 0)
        nFrames = 1; // Returns 0 if animation isn't supported

    int totalDelay;
    QVector<int> frameDelays;
    QVector<QSharedPointer<QOpenGLTexture>> frameTextures;

    frameTextures.resize(nFrames);
    frameDelays.resize(nFrames);

    for (int i = 0; i < nFrames; i++) {
        auto frame = imageReader.read();
        if (frame.isNull()) {
            emit error(QString("Unable to read frame %1 of image: %2").arg(i).arg(imageReader.errorString()));
            p.setNodeState(VideoNode::Broken);
            return;
        }

        frameDelays[i] = imageReader.nextImageDelay();
        if(!frameDelays[i])
            frameDelays[i] = 10;
        frameTextures[i] = QSharedPointer<QOpenGLTexture>::create(frame.mirrored(), QOpenGLTexture::MipMapGeneration::GenerateMipMaps);
    }
    std::partial_sum(frameDelays.begin(),frameDelays.end(),frameDelays.begin());
    totalDelay = frameDelays.back();
    qDebug() << "Successfully loaded image " << filename << " with " << nFrames << "frames, and a total delay of " << totalDelay << "ms";

    {
        QMutexLocker locker(&p.d()->m_stateLock);
        p.d()->m_totalDelay = totalDelay;
        p.d()->m_frameTextures = frameTextures;
        p.d()->m_frameDelays = frameDelays;
        p.d()->m_ready = true;
    }
    glFlush();
    p.setNodeState(VideoNode::Ready);
}

QString ImageNode::typeName() {
    return "ImageNode";
}

VideoNode *ImageNode::deserialize(Context *context, QJsonObject obj) {
    QString name = obj.value("file").toString();
    if (obj.isEmpty()) {
        return nullptr;
    }
    ImageNode *e = new ImageNode(context, name);
    return e;
}

bool ImageNode::canCreateFromFile(QString filename) {
    return QImageReader(filename).canRead();
}

VideoNode *ImageNode::fromFile(Context *context, QString filename) {
    ImageNode *e = new ImageNode(context, filename);
    return e;
}

QMap<QString, QString> ImageNode::customInstantiators() {
    return QMap<QString, QString>();
}

WeakImageNode::WeakImageNode()
{
}

WeakImageNode::WeakImageNode(const ImageNode &other)
    : d_ptr(other.d())
{
}

QSharedPointer<ImageNodePrivate> WeakImageNode::toStrongRef() {
    return d_ptr.toStrongRef();
}

ImageNodePrivate::ImageNodePrivate(Context *context)
    : VideoNodePrivate(context)
{
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "Operators.hpp"
#include "Options.hpp"
#include "ByteCodeFileWriter.hpp"
#include "Variables.hpp"

#include <cassert>

using std::string;

using namespace eddic;

//Checks

void BinaryOperator::checkVariables(Variables& variables) {
    lhs->checkVariables(variables);
    rhs->checkVariables(variables);

    m_type = checkTypes(lhs->type(), rhs->type());
}

void BinaryOperator::checkStrings(StringPool& pool){
    lhs->checkStrings(pool);
    rhs->checkStrings(pool);
}

Type BinaryOperator::checkTypes(Type left, Type right) {
    if(left != right || left != INT) {
        throw CompilerException("Can only compute two integers");
    }

    return left;
}

Type Addition::checkTypes(Type left, Type right) {
    if(left != right) {
        throw CompilerException("Can only add two values of the same type");
    }

    return left;
}

//Writes

void Addition::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    static int labelCopy = 0;

    if(m_type == INT) {
        writer.stream() << "movl (%esp), %eax" << std::endl;
        writer.stream() << "movl 4(%esp), %ecx" << std::endl;
        writer.stream() << "addl %ecx, %eax" << std::endl;
        writer.stream() << "addl $8, %esp" << std::endl;
        writer.stream() << "pushl %eax" << std::endl;
    } else {
        writer.stream() << "movl 12(%esp), %edx" << std::endl;
        writer.stream() << "movl 4(%esp), %ecx" << std::endl;
        writer.stream() << "addl %ecx, %edx" << std::endl;

        writer.stream() << "pushl %edx" << std::endl;
        writer.stream() << "call malloc" << std::endl;
        writer.stream() << "addl $4, %esp" << std::endl;

        writer.stream() << "movl %eax, -4(%esp)" << std::endl;

        writer.stream() << "movl 12(%esp), %ebx" << std::endl;
        writer.stream() << "movl %eax, %ecx" << std::endl;
        writer.stream() << "movl 8(%esp), %edx" << std::endl;

        writer.stream() << "copy" << labelCopy << ":" << std::endl;
        writer.stream() << "cmpl $0, %ebx" << std::endl;
        writer.stream() << "je end" << labelCopy  << std::endl;
        writer.stream() << "movl (%edx), %eax" << std::endl;
        writer.stream() << "movl %eax, (%ecx)" << std::endl;
        writer.stream() << "addl $4, %edx" << std::endl;
        writer.stream() << "subl $1, %ebx" << std::endl;
        writer.stream() << "jmp copy" << labelCopy << std::endl;
        writer.stream() << "end" << labelCopy << ":" << std::endl;

        labelCopy++;

        writer.stream() << "movl 4(%esp), %ebx" << std::endl;
        writer.stream() << "movl (%esp), %edx" << std::endl;

        writer.stream() << "copy" << labelCopy << ":" << std::endl;
        writer.stream() << "cmpl $0, %ebx" << std::endl;
        writer.stream() << "je end" << labelCopy  << std::endl;
        writer.stream() << "movl (%edx), %eax" << std::endl;
        writer.stream() << "movl %eax, (%ecx)" << std::endl;
        writer.stream() << "addl $4, %edx" << std::endl;
        writer.stream() << "subl $1, %ebx" << std::endl;
        writer.stream() << "jmp copy" << labelCopy << std::endl;
        writer.stream() << "end" << labelCopy << ":" << std::endl;

        writer.stream() << "movl 12(%esp), %edx" << std::endl;
        writer.stream() << "movl 4(%esp), %ecx" << std::endl;
        writer.stream() << "addl %ecx, %edx" << std::endl;

        labelCopy++;

        writer.stream() << "movl -4(%esp), %eax" << std::endl;

        writer.stream() << "addl $16, %esp" << std::endl;

        writer.stream() << "pushl %eax" << std::endl;
        writer.stream() << "pushl %edx" << std::endl;
    }
}

void Subtraction::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    writer.stream() << "movl (%esp), %ecx" << std::endl;
    writer.stream() << "movl 4(%esp), %eax" << std::endl;
    writer.stream() << "subl %ecx, %eax" << std::endl;
    writer.stream() << "addl $8, %esp" << std::endl;
    writer.stream() << "pushl %eax" << std::endl;
}

void Multiplication::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    writer.stream() << "movl (%esp), %eax" << std::endl;
    writer.stream() << "movl 4(%esp), %ecx" << std::endl;
    writer.stream() << "mull %ecx" << std::endl;
    writer.stream() << "addl $8, %esp" << std::endl;
    writer.stream() << "pushl %eax" << std::endl;
}

void Division::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    writer.stream() << "movl (%esp), %ecx" << std::endl;
    writer.stream() << "movl 4(%esp), %eax" << std::endl;
    writer.stream() << "movl $0, %edx" << std::endl;
    writer.stream() << "divl %ecx" << std::endl;
    writer.stream() << "addl $8, %esp" << std::endl;
    writer.stream() << "pushl %eax" << std::endl;
}

void Modulo::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    writer.stream() << "movl (%esp), %ecx" << std::endl;
    writer.stream() << "movl 4(%esp), %eax" << std::endl;
    writer.stream() << "movl $0, %edx" << std::endl;
    writer.stream() << "divl %ecx" << std::endl;
    writer.stream() << "addl $8, %esp" << std::endl;
    writer.stream() << "pushl %edx" << std::endl;
}

//Constantness

bool BinaryOperator::isConstant() {
    return lhs->isConstant() && rhs->isConstant();
}

//Values

int BinaryOperator::getIntValue() {
    if(type() != INT) {
        throw "Invalid type";
    }

    if(!isConstant()) {
        throw "Not a constant";
    }

    return compute(lhs->getIntValue(), rhs->getIntValue());
}

string BinaryOperator::getStringValue() {
    if(type() != STRING) {
        throw "Invalid type";
    }

    if(!isConstant()) {
        throw "Not a constant";
    }

    return compute(lhs->getStringValue(), rhs->getStringValue());
}

int BinaryOperator::compute(int left, int right) {
    throw "Invalid type";
}

string BinaryOperator::compute(const std::string& left, const std::string& right) {
    throw "Invalid type";
}

int Addition::compute(int left, int right) {
    return left + right;
}

string Addition::compute(const std::string& left, const std::string& right) {
    return left + right;
}

int Subtraction::compute(int left, int right) {
    return left - right;
}

int Multiplication::compute(int left, int right) {
    return left * right;
}

int Division::compute(int left, int right) {
    return left / right;
}

int Modulo::compute(int left, int right) {
    return left % right;
}

//Optimizations

void BinaryOperator::optimize() {
    if(isConstant()) {
        if(Options::isSet(OPTIMIZE_INTEGERS)) {
            Value* value = new Integer(getIntValue());

            parent->replace(this, value);
        }
    }

    lhs->optimize();
    rhs->optimize();
}

void Addition::optimize() {
    if(isConstant()) {
        if(type() == INT) {
            if(Options::isSet(OPTIMIZE_INTEGERS)) {
                Value* value = new Integer(getIntValue());

                parent->replace(this, value);
            }
        } else if(type() == STRING) {
            if(Options::isSet(OPTIMIZE_STRINGS)) {
                //No optimization at this time
            }
        }
    }

    lhs->optimize();
    rhs->optimize();
}
<commit_msg>Finalize the string concatenation<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "Operators.hpp"
#include "Options.hpp"
#include "ByteCodeFileWriter.hpp"
#include "Variables.hpp"

#include <cassert>

using std::string;

using namespace eddic;

//Checks

void BinaryOperator::checkVariables(Variables& variables) {
    lhs->checkVariables(variables);
    rhs->checkVariables(variables);

    m_type = checkTypes(lhs->type(), rhs->type());
}

void BinaryOperator::checkStrings(StringPool& pool){
    lhs->checkStrings(pool);
    rhs->checkStrings(pool);
}

Type BinaryOperator::checkTypes(Type left, Type right) {
    if(left != right || left != INT) {
        throw CompilerException("Can only compute two integers");
    }

    return left;
}

Type Addition::checkTypes(Type left, Type right) {
    if(left != right) {
        throw CompilerException("Can only add two values of the same type");
    }

    return left;
}

//Writes

void Addition::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    static int labelCopy = 0;

    if(m_type == INT) {
        writer.stream() << "movl (%esp), %eax" << std::endl;
        writer.stream() << "movl 4(%esp), %ecx" << std::endl;
        writer.stream() << "addl %ecx, %eax" << std::endl;
        writer.stream() << "addl $8, %esp" << std::endl;
        writer.stream() << "pushl %eax" << std::endl;
    } else {
        writer.stream() << "movl 8(%esp), %edx" << std::endl;
        writer.stream() << "movl (%esp), %ecx" << std::endl;
        writer.stream() << "addl %ecx, %edx" << std::endl;

        writer.stream() << "pushl %edx" << std::endl;
        writer.stream() << "call malloc" << std::endl;
        writer.stream() << "addl $4, %esp" << std::endl;

        writer.stream() << "movl %eax, -4(%esp)" << std::endl;
        writer.stream() << "movl %eax, %ecx" << std::endl;
        writer.stream() << "movl $0, %eax" << std::endl;

        writer.stream() << "movl 8(%esp), %ebx" << std::endl;
        writer.stream() << "movl 12(%esp), %edx" << std::endl;

        writer.stream() << "copy" << labelCopy << ":" << std::endl;
        writer.stream() << "cmpl $0, %ebx" << std::endl;
        writer.stream() << "je end" << labelCopy  << std::endl;
        writer.stream() << "movb (%edx), %al" << std::endl;
        writer.stream() << "movb %al, (%ecx)" << std::endl;
        writer.stream() << "addl $1, %ecx" << std::endl;
        writer.stream() << "addl $1, %edx" << std::endl;
        writer.stream() << "subl $1, %ebx" << std::endl;
        writer.stream() << "jmp copy" << labelCopy << std::endl;
        writer.stream() << "end" << labelCopy << ":" << std::endl;

        labelCopy++;

        writer.stream() << "movl (%esp), %ebx" << std::endl;
        writer.stream() << "movl 4(%esp), %edx" << std::endl;

        writer.stream() << "copy" << labelCopy << ":" << std::endl;
        writer.stream() << "cmpl $0, %ebx" << std::endl;
        writer.stream() << "je end" << labelCopy  << std::endl;
        writer.stream() << "movb (%edx), %al" << std::endl;
        writer.stream() << "movb %al, (%ecx)" << std::endl;
        writer.stream() << "addl $1, %ecx" << std::endl;
        writer.stream() << "addl $1, %edx" << std::endl;
        writer.stream() << "subl $1, %ebx" << std::endl;
        writer.stream() << "jmp copy" << labelCopy << std::endl;
        writer.stream() << "end" << labelCopy << ":" << std::endl;

        writer.stream() << "movl 8(%esp), %edx" << std::endl;
        writer.stream() << "movl (%esp), %ecx" << std::endl;
        writer.stream() << "addl %ecx, %edx" << std::endl;

        labelCopy++;

        writer.stream() << "movl -4(%esp), %eax" << std::endl;

        writer.stream() << "addl $16, %esp" << std::endl;

        writer.stream() << "pushl %eax" << std::endl;
        writer.stream() << "pushl %edx" << std::endl;
    }
}

void Subtraction::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    writer.stream() << "movl (%esp), %ecx" << std::endl;
    writer.stream() << "movl 4(%esp), %eax" << std::endl;
    writer.stream() << "subl %ecx, %eax" << std::endl;
    writer.stream() << "addl $8, %esp" << std::endl;
    writer.stream() << "pushl %eax" << std::endl;
}

void Multiplication::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    writer.stream() << "movl (%esp), %eax" << std::endl;
    writer.stream() << "movl 4(%esp), %ecx" << std::endl;
    writer.stream() << "mull %ecx" << std::endl;
    writer.stream() << "addl $8, %esp" << std::endl;
    writer.stream() << "pushl %eax" << std::endl;
}

void Division::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    writer.stream() << "movl (%esp), %ecx" << std::endl;
    writer.stream() << "movl 4(%esp), %eax" << std::endl;
    writer.stream() << "movl $0, %edx" << std::endl;
    writer.stream() << "divl %ecx" << std::endl;
    writer.stream() << "addl $8, %esp" << std::endl;
    writer.stream() << "pushl %eax" << std::endl;
}

void Modulo::write(ByteCodeFileWriter& writer) {
    lhs->write(writer);
    rhs->write(writer);

    writer.stream() << "movl (%esp), %ecx" << std::endl;
    writer.stream() << "movl 4(%esp), %eax" << std::endl;
    writer.stream() << "movl $0, %edx" << std::endl;
    writer.stream() << "divl %ecx" << std::endl;
    writer.stream() << "addl $8, %esp" << std::endl;
    writer.stream() << "pushl %edx" << std::endl;
}

//Constantness

bool BinaryOperator::isConstant() {
    return lhs->isConstant() && rhs->isConstant();
}

//Values

int BinaryOperator::getIntValue() {
    if(type() != INT) {
        throw "Invalid type";
    }

    if(!isConstant()) {
        throw "Not a constant";
    }

    return compute(lhs->getIntValue(), rhs->getIntValue());
}

string BinaryOperator::getStringValue() {
    if(type() != STRING) {
        throw "Invalid type";
    }

    if(!isConstant()) {
        throw "Not a constant";
    }

    return compute(lhs->getStringValue(), rhs->getStringValue());
}

int BinaryOperator::compute(int left, int right) {
    throw "Invalid type";
}

string BinaryOperator::compute(const std::string& left, const std::string& right) {
    throw "Invalid type";
}

int Addition::compute(int left, int right) {
    return left + right;
}

string Addition::compute(const std::string& left, const std::string& right) {
    return left + right;
}

int Subtraction::compute(int left, int right) {
    return left - right;
}

int Multiplication::compute(int left, int right) {
    return left * right;
}

int Division::compute(int left, int right) {
    return left / right;
}

int Modulo::compute(int left, int right) {
    return left % right;
}

//Optimizations

void BinaryOperator::optimize() {
    if(isConstant()) {
        if(Options::isSet(OPTIMIZE_INTEGERS)) {
            Value* value = new Integer(getIntValue());

            parent->replace(this, value);
        }
    }

    lhs->optimize();
    rhs->optimize();
}

void Addition::optimize() {
    if(isConstant()) {
        if(type() == INT) {
            if(Options::isSet(OPTIMIZE_INTEGERS)) {
                Value* value = new Integer(getIntValue());

                parent->replace(this, value);
            }
        } else if(type() == STRING) {
            if(Options::isSet(OPTIMIZE_STRINGS)) {
                //No optimization at this time
            }
        }
    }

    lhs->optimize();
    rhs->optimize();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004-2010  See the AUTHORS file for details.
 * Copyright (C) 2008 Michael "Svedrin" Ziegler diese-addy@funzt-halt.net
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#include "Modules.h"
#include "User.h"

class CAutoReplyMod : public CModule {
public:
	MODCONSTRUCTOR(CAutoReplyMod) {
		m_Messaged.SetTTL(1000 * 120);
	}

	virtual ~CAutoReplyMod() {}

	virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
		if (!sArgs.empty()) {
			SetReply(sArgs);
		}

		return true;
	}

	void SetReply(const CString& sReply) {
		SetNV("Reply", sReply);
	}

	CString GetReply() {
		CString sReply = GetNV("Reply");
		if (sReply.empty()) {
			sReply = "%nick% is currently away, try again later";
			SetReply(sReply);
		}

		return m_pUser->ExpandString(sReply);
	}

	void Handle(const CString& sNick) {
		if (m_Messaged.HasItem(sNick))
			return;

		if (m_pUser->IsUserAttached())
			return;

		m_Messaged.AddItem(sNick);
		PutIRC("PRIVMSG " + sNick + " :" + GetReply());
	}

	virtual EModRet OnPrivNotice(CNick& Nick, CString& sMessage) {
		Handle(Nick.GetNick());
		return CONTINUE;
	}

	virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage) {
		Handle(Nick.GetNick());
		return CONTINUE;
	}

	virtual void OnModCommand(const CString& sCommand) {
		const CString& sCmd = sCommand.Token(0);

		if (sCmd.Equals("SHOW")) {
			PutModule("Current reply is: " + GetNV("Reply")
					+ " (" + GetReply() + ")");
		} else if (sCmd.Equals("SET")) {
			SetReply(sCommand.Token(1, true));
			PutModule("New reply set");
		} else {
			PutModule("Available commands are:");
			PutModule("Show        - Displays the current query reply");
			PutModule("Set <reply> - Sets a new reply");
		}
	}

private:
	TCacheMap<CString>	m_Messaged;
};

MODULEDEFS(CAutoReplyMod, "Reply to queries when you are away")

<commit_msg>autoreply: Ignore messages from self<commit_after>/*
 * Copyright (C) 2004-2010  See the AUTHORS file for details.
 * Copyright (C) 2008 Michael "Svedrin" Ziegler diese-addy@funzt-halt.net
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#include "Modules.h"
#include "IRCSock.h"
#include "User.h"

class CAutoReplyMod : public CModule {
public:
	MODCONSTRUCTOR(CAutoReplyMod) {
		m_Messaged.SetTTL(1000 * 120);
	}

	virtual ~CAutoReplyMod() {}

	virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
		if (!sArgs.empty()) {
			SetReply(sArgs);
		}

		return true;
	}

	void SetReply(const CString& sReply) {
		SetNV("Reply", sReply);
	}

	CString GetReply() {
		CString sReply = GetNV("Reply");
		if (sReply.empty()) {
			sReply = "%nick% is currently away, try again later";
			SetReply(sReply);
		}

		return m_pUser->ExpandString(sReply);
	}

	void Handle(const CString& sNick) {
		CIRCSock *pIRCSock = GetUser()->GetIRCSock();
		if (!pIRCSock)
			// WTF?
			return;
		if (sNick == pIRCSock->GetNick())
			return;
		if (m_Messaged.HasItem(sNick))
			return;

		if (m_pUser->IsUserAttached())
			return;

		m_Messaged.AddItem(sNick);
		PutIRC("PRIVMSG " + sNick + " :" + GetReply());
	}

	virtual EModRet OnPrivNotice(CNick& Nick, CString& sMessage) {
		Handle(Nick.GetNick());
		return CONTINUE;
	}

	virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage) {
		Handle(Nick.GetNick());
		return CONTINUE;
	}

	virtual void OnModCommand(const CString& sCommand) {
		const CString& sCmd = sCommand.Token(0);

		if (sCmd.Equals("SHOW")) {
			PutModule("Current reply is: " + GetNV("Reply")
					+ " (" + GetReply() + ")");
		} else if (sCmd.Equals("SET")) {
			SetReply(sCommand.Token(1, true));
			PutModule("New reply set");
		} else {
			PutModule("Available commands are:");
			PutModule("Show        - Displays the current query reply");
			PutModule("Set <reply> - Sets a new reply");
		}
	}

private:
	TCacheMap<CString>	m_Messaged;
};

MODULEDEFS(CAutoReplyMod, "Reply to queries when you are away")

<|endoftext|>


<commit_before>
// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif

#include "ThermoPhase.h"
#include "PureFluidPhase.h"
#include <stdio.h>
#include "mix_defs.h"

using namespace std;

namespace Cantera {

  /**
   * Format a summary of the mixture state for output.
   */
  std::string report(const ThermoPhase& th, bool show_thermo) {
    return th.report(show_thermo);
  }

  void writephase(const ThermoPhase& th, bool show_thermo) {
    string s = report(th, show_thermo);
    writelog(s+"\n");
  }

  /**
   * Format a composition list for output.
   */
  std::string formatCompList(const Phase& mix, int xyc) {

    const doublereal Threshold = 1.e-20;

    char p[200];
    string s = "";
    int kk = mix.nSpecies();
    array_fp zz(kk);
    switch (xyc) {
    case 0: mix.getMoleFractions(&zz[0]); break;
    case 1: mix.getMassFractions(&zz[0]); break;
    case 2: mix.getConcentrations(&zz[0]); break;
    default: return "error: xyc must be 0, 1, or 2";
    }

    doublereal z;
    int k;
    for (k = 0; k < kk; k++) {
      z = fabs(zz[k]);
      if (z < Threshold) zz[k] = 0.0;
    }

    for (k = 0; k < kk; k++) {
      sprintf(p, "%18s\t %12.6e\n", mix.speciesName(k).c_str(),
	      zz[k]);
      s += p;
    }
    return s;
  }

}

<commit_msg>Doxygen update: commented routines<commit_after>/**
 *  @file phasereport.cpp
 *  Output routines for phases
 */

/*  $Author$
 *  $Date$
 *  $Revision$
 *
 *  Copyright 2001 California Institute of Technology
 *
 */

// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif

#include "ThermoPhase.h"
#include "PureFluidPhase.h"
#include <stdio.h>
#include "mix_defs.h"

using namespace std;

namespace Cantera {

  //! Format a summary of the mixture state for output.
  /*!
   * @param th  ThermoPhase object to create a report about
   * @param show_thermo Boolean indicating whether the thermo functions
   *                    of the phase should be written out
   *
   * @return  Returns a string containing the report
   */
  std::string report(const ThermoPhase& th, bool show_thermo) {
    return th.report(show_thermo);
  }

  //! Write a phase report to the screen device
  /*!
   *  This routine is a wrapper around the report() function.
   *  It writes to the screen device.
   *
   * @param th          ThermoPhase object to create a report about
   * @param show_thermo Boolean indicating whether the thermo functions
   *                    of the phase should be written out
   */
  void writephase(const ThermoPhase& th, bool show_thermo) {
    std::string s = report(th, show_thermo);
    writelog(s+"\n");
  }

  //! Format a composition list for output.
  /*!
   *  Depending upon xyc, this creates a list of
   *  mole fractions, mass fractions, or concentrations.
   *
   *  @param mix  Mixture to create a list from
   *  @param xyc  Integer 0  mole fractions
   *                      1  mass fractions
   *                      2 concentrations
   *
   * @return Returns a string containing the list
   */
  std::string formatCompList(const Phase& mix, int xyc) {

    const doublereal Threshold = 1.e-20;

    char p[200];
    string s = "";
    int kk = mix.nSpecies();
    array_fp zz(kk);
    switch (xyc) {
    case 0: mix.getMoleFractions(&zz[0]); break;
    case 1: mix.getMassFractions(&zz[0]); break;
    case 2: mix.getConcentrations(&zz[0]); break;
    default: return "error: xyc must be 0, 1, or 2";
    }

    doublereal z;
    int k;
    for (k = 0; k < kk; k++) {
      z = fabs(zz[k]);
      if (z < Threshold) zz[k] = 0.0;
    }

    for (k = 0; k < kk; k++) {
      sprintf(p, "%18s\t %12.6e\n", mix.speciesName(k).c_str(),
	      zz[k]);
      s += p;
    }
    return s;
  }

}

<|endoftext|>


<commit_before>#include "PtrStream.h"
#include <assert.h>
#include <string.h>

using namespace Framework;

CPtrStream::CPtrStream(void* pData, uint64 nSize)
{
	m_pData = (char*)pData;
	m_nSize = nSize;
	m_nPosition = 0;
	m_nEOF = false;
}

void CPtrStream::Seek(int64 nPosition, STREAM_SEEK_DIRECTION nDirection)
{
	m_nEOF = false;
	switch(nDirection)
	{
	case STREAM_SEEK_SET:
		assert((uint64)nPosition <= m_nSize);
		m_nPosition = nPosition;
		break;
	case STREAM_SEEK_CUR:
		assert((m_nPosition + nPosition) <= m_nSize);
		assert((m_nPosition + nPosition) >= 0);
		m_nPosition += nPosition;
	case STREAM_SEEK_END:
		m_nPosition = m_nSize;
		break;
	}
}

uint64 CPtrStream::Tell()
{
	return m_nPosition;
}

bool CPtrStream::IsEOF()
{
	return m_nEOF;
}

uint64 CPtrStream::Read(void* pBuffer, uint64 nSize)
{
	if(m_nPosition == m_nSize)
	{
		m_nEOF = true;
		return 0;
	}
	if((m_nPosition + nSize) > m_nSize)
	{
		nSize = (m_nSize - m_nPosition);
	}
	memcpy(pBuffer, m_pData + m_nPosition, (size_t)nSize);
	m_nPosition += nSize;
	return nSize;
}

uint64 CPtrStream::Write(const void* pBuffer, uint64 nSize)
{
	//Operation not supported
	assert(0);
	return 0;
}
<commit_msg><commit_after>#include "PtrStream.h"
#include <assert.h>
#include <string.h>

using namespace Framework;

CPtrStream::CPtrStream(void* pData, uint64 nSize)
{
	m_pData = (char*)pData;
	m_nSize = nSize;
	m_nPosition = 0;
	m_nEOF = false;
}

void CPtrStream::Seek(int64 nPosition, STREAM_SEEK_DIRECTION nDirection)
{
	m_nEOF = false;
	switch(nDirection)
	{
	case STREAM_SEEK_SET:
		assert((uint64)nPosition <= m_nSize);
		m_nPosition = nPosition;
		break;
	case STREAM_SEEK_CUR:
		assert((m_nPosition + nPosition) <= m_nSize);
		assert((m_nPosition + nPosition) >= 0);
		m_nPosition += nPosition;
        break;
	case STREAM_SEEK_END:
		m_nPosition = m_nSize;
		break;
	}
}

uint64 CPtrStream::Tell()
{
	return m_nPosition;
}

bool CPtrStream::IsEOF()
{
	return m_nEOF;
}

uint64 CPtrStream::Read(void* pBuffer, uint64 nSize)
{
	if(m_nPosition == m_nSize)
	{
		m_nEOF = true;
		return 0;
	}
	if((m_nPosition + nSize) > m_nSize)
	{
		nSize = (m_nSize - m_nPosition);
	}
	memcpy(pBuffer, m_pData + m_nPosition, (size_t)nSize);
	m_nPosition += nSize;
	return nSize;
}

uint64 CPtrStream::Write(const void* pBuffer, uint64 nSize)
{
	//Operation not supported
	assert(0);
	return 0;
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file Selection.cxx
 ** Classes maintaining the selection.
 **/
// Copyright 2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>

#include <vector>

#include "Platform.h"

#include "Scintilla.h"

#include "Selection.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) {
	if (insertion) {
		if (position == startChange) {
			int virtualLengthRemove = std::min(length, virtualSpace);
			virtualSpace -= virtualLengthRemove;
			position += virtualLengthRemove;
		} else if (position > startChange) {
			position += length;
		}
	} else {
		if (position == startChange) {
			virtualSpace = 0;
		}
		if (position > startChange) {
			int endDeletion = startChange + length;
			if (position > endDeletion) {
				position -= length;
			} else {
				position = startChange;
				virtualSpace = 0;
			}
		}
	}
}

bool SelectionPosition::operator <(const SelectionPosition &other) const {
	if (position == other.position)
		return virtualSpace < other.virtualSpace;
	else
		return position < other.position;
}

bool SelectionPosition::operator >(const SelectionPosition &other) const {
	if (position == other.position)
		return virtualSpace > other.virtualSpace;
	else
		return position > other.position;
}

bool SelectionPosition::operator <=(const SelectionPosition &other) const {
	if (position == other.position && virtualSpace == other.virtualSpace)
		return true;
	else
		return other > *this;
}

bool SelectionPosition::operator >=(const SelectionPosition &other) const {
	if (position == other.position && virtualSpace == other.virtualSpace)
		return true;
	else
		return *this > other;
}

int SelectionRange::Length() const {
	if (anchor > caret) {
		return anchor.Position() - caret.Position();
	} else {
		return caret.Position() - anchor.Position();
	}
}

bool SelectionRange::Contains(int pos) const {
	if (anchor > caret)
		return (pos >= caret.Position()) && (pos <= anchor.Position());
	else
		return (pos >= anchor.Position()) && (pos <= caret.Position());
}

bool SelectionRange::Contains(SelectionPosition sp) const {
	if (anchor > caret)
		return (sp >= caret) && (sp <= anchor);
	else
		return (sp >= anchor) && (sp <= caret);
}

bool SelectionRange::ContainsCharacter(int posCharacter) const {
	if (anchor > caret)
		return (posCharacter >= caret.Position()) && (posCharacter < anchor.Position());
	else
		return (posCharacter >= anchor.Position()) && (posCharacter < caret.Position());
}

SelectionSegment SelectionRange::Intersect(SelectionSegment check) const {
	SelectionSegment inOrder(caret, anchor);
	if ((inOrder.start <= check.end) || (inOrder.end >= check.start)) {
		SelectionSegment portion = check;
		if (portion.start < inOrder.start)
			portion.start = inOrder.start;
		if (portion.end > inOrder.end)
			portion.end = inOrder.end;
		if (portion.start > portion.end)
			return SelectionSegment();
		else
			return portion;
	} else {
		return SelectionSegment();
	}
}

bool SelectionRange::Trim(SelectionRange range) {
	SelectionPosition startRange = range.Start();
	SelectionPosition endRange = range.End();
	SelectionPosition start = Start();
	SelectionPosition end = End();
	PLATFORM_ASSERT(start <= end);
	PLATFORM_ASSERT(startRange <= endRange);
	if ((startRange <= end) && (endRange >= start)) {
		if ((start > startRange) && (end < endRange)) {
			// Completely covered by range -> empty at start
			end = start;
		} else if ((start < startRange) && (end > endRange)) {
			// Completely covers range -> empty at start
			end = start;
		} else if (start <= startRange) {
			// Trim end
			end = startRange;
		} else { //
			PLATFORM_ASSERT(end >= endRange);
			// Trim start
			start = endRange;
		}
		if (anchor > caret) {
			caret = start;
			anchor = end;
		} else {
			anchor = start;
			caret = end;
		}
		return Empty();
	} else {
		return false;
	}
}

// If range is all virtual collapse to start of virtual space
void SelectionRange::MinimizeVirtualSpace() {
	if (caret.Position() == anchor.Position()) {
		int virtualSpace = caret.VirtualSpace();
		if (virtualSpace > anchor.VirtualSpace())
			virtualSpace = anchor.VirtualSpace();
		caret.SetVirtualSpace(virtualSpace);
		anchor.SetVirtualSpace(virtualSpace);
	}
}

Selection::Selection() : mainRange(0), moveExtends(false), tentativeMain(false), selType(selStream) {
	AddSelection(SelectionPosition(0));
}

Selection::~Selection() {
}

bool Selection::IsRectangular() const {
	return (selType == selRectangle) || (selType == selThin);
}

int Selection::MainCaret() const {
	return ranges[mainRange].caret.Position();
}

int Selection::MainAnchor() const {
	return ranges[mainRange].anchor.Position();
}

SelectionRange &Selection::Rectangular() {
	return rangeRectangular;
}

SelectionSegment Selection::Limits() const {
	if (ranges.empty()) {
		return SelectionSegment();
	} else {
		SelectionSegment sr(ranges[0].anchor, ranges[0].caret);
		for (size_t i=1; i<ranges.size(); i++) {
			sr.Extend(ranges[i].anchor);
			sr.Extend(ranges[i].caret);
		}
		return sr;
	}
}

SelectionSegment Selection::LimitsForRectangularElseMain() const {
	if (IsRectangular()) {
		return Limits();
	} else {
		return SelectionSegment(ranges[mainRange].caret, ranges[mainRange].anchor);
	}
}

size_t Selection::Count() const {
	return ranges.size();
}

size_t Selection::Main() const {
	return mainRange;
}

void Selection::SetMain(size_t r) {
	PLATFORM_ASSERT(r < ranges.size());
	mainRange = r;
}

SelectionRange &Selection::Range(size_t r) {
	return ranges[r];
}

SelectionRange &Selection::RangeMain() {
	return ranges[mainRange];
}

bool Selection::MoveExtends() const {
	return moveExtends;
}

void Selection::SetMoveExtends(bool moveExtends_) {
	moveExtends = moveExtends_;
}

bool Selection::Empty() const {
	for (size_t i=0; i<ranges.size(); i++) {
		if (!ranges[i].Empty())
			return false;
	}
	return true;
}

SelectionPosition Selection::Last() const {
	SelectionPosition lastPosition;
	for (size_t i=0; i<ranges.size(); i++) {
		if (lastPosition < ranges[i].caret)
			lastPosition = ranges[i].caret;
		if (lastPosition < ranges[i].anchor)
			lastPosition = ranges[i].anchor;
	}
	return lastPosition;
}

int Selection::Length() const {
	int len = 0;
	for (size_t i=0; i<ranges.size(); i++) {
		len += ranges[i].Length();
	}
	return len;
}

void Selection::MovePositions(bool insertion, int startChange, int length) {
	for (size_t i=0; i<ranges.size(); i++) {
		ranges[i].caret.MoveForInsertDelete(insertion, startChange, length);
		ranges[i].anchor.MoveForInsertDelete(insertion, startChange, length);
	}
}

void Selection::TrimSelection(SelectionRange range) {
	for (size_t i=0; i<ranges.size();) {
		if ((i != mainRange) && (ranges[i].Trim(range))) {
			// Trimmed to empty so remove
			for (size_t j=i; j<ranges.size()-1; j++) {
				ranges[j] = ranges[j+1];
				if (j == mainRange-1)
					mainRange--;
			}
			ranges.pop_back();
		} else {
			i++;
		}
	}
}

void Selection::SetSelection(SelectionRange range) {
	ranges.clear();
	ranges.push_back(range);
	mainRange = ranges.size() - 1;
}

void Selection::AddSelection(SelectionRange range) {
	TrimSelection(range);
	ranges.push_back(range);
	mainRange = ranges.size() - 1;
}

void Selection::AddSelectionWithoutTrim(SelectionRange range) {
	ranges.push_back(range);
	mainRange = ranges.size() - 1;
}

void Selection::TentativeSelection(SelectionRange range) {
	if (!tentativeMain) {
		rangesSaved = ranges;
	}
	ranges = rangesSaved;
	AddSelection(range);
	TrimSelection(ranges[mainRange]);
	tentativeMain = true;
}

void Selection::CommitTentative() {
	rangesSaved.clear();
	tentativeMain = false;
}

int Selection::CharacterInSelection(int posCharacter) const {
	for (size_t i=0; i<ranges.size(); i++) {
		if (ranges[i].ContainsCharacter(posCharacter))
			return i == mainRange ? 1 : 2;
	}
	return 0;
}

int Selection::InSelectionForEOL(int pos) const {
	for (size_t i=0; i<ranges.size(); i++) {
		if (!ranges[i].Empty() && (pos > ranges[i].Start().Position()) && (pos <= ranges[i].End().Position()))
			return i == mainRange ? 1 : 2;
	}
	return 0;
}

int Selection::VirtualSpaceFor(int pos) const {
	int virtualSpace = 0;
	for (size_t i=0; i<ranges.size(); i++) {
		if ((ranges[i].caret.Position() == pos) && (virtualSpace < ranges[i].caret.VirtualSpace()))
			virtualSpace = ranges[i].caret.VirtualSpace();
		if ((ranges[i].anchor.Position() == pos) && (virtualSpace < ranges[i].anchor.VirtualSpace()))
			virtualSpace = ranges[i].anchor.VirtualSpace();
	}
	return virtualSpace;
}

void Selection::Clear() {
	ranges.clear();
	ranges.push_back(SelectionRange());
	mainRange = ranges.size() - 1;
	selType = selStream;
	moveExtends = false;
	ranges[mainRange].Reset();
	rangeRectangular.Reset();
}

void Selection::RemoveDuplicates() {
	for (size_t i=0; i<ranges.size()-1; i++) {
		if (ranges[i].Empty()) {
			size_t j=i+1;
			while (j<ranges.size()) {
				if (ranges[i] == ranges[j]) {
					ranges.erase(ranges.begin() + j);
					if (mainRange >= j)
						mainRange--;
				} else {
					j++;
				}
			}
		}
	}
}

void Selection::RotateMain() {
	mainRange = (mainRange + 1) % ranges.size();
}

<commit_msg>Bug: [#1492]. Need extra header for better standard compliance in Visual Studio 2013.<commit_after>// Scintilla source code edit control
/** @file Selection.cxx
 ** Classes maintaining the selection.
 **/
// Copyright 2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>

#include <vector>
#include <algorithm>

#include "Platform.h"

#include "Scintilla.h"

#include "Selection.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) {
	if (insertion) {
		if (position == startChange) {
			int virtualLengthRemove = std::min(length, virtualSpace);
			virtualSpace -= virtualLengthRemove;
			position += virtualLengthRemove;
		} else if (position > startChange) {
			position += length;
		}
	} else {
		if (position == startChange) {
			virtualSpace = 0;
		}
		if (position > startChange) {
			int endDeletion = startChange + length;
			if (position > endDeletion) {
				position -= length;
			} else {
				position = startChange;
				virtualSpace = 0;
			}
		}
	}
}

bool SelectionPosition::operator <(const SelectionPosition &other) const {
	if (position == other.position)
		return virtualSpace < other.virtualSpace;
	else
		return position < other.position;
}

bool SelectionPosition::operator >(const SelectionPosition &other) const {
	if (position == other.position)
		return virtualSpace > other.virtualSpace;
	else
		return position > other.position;
}

bool SelectionPosition::operator <=(const SelectionPosition &other) const {
	if (position == other.position && virtualSpace == other.virtualSpace)
		return true;
	else
		return other > *this;
}

bool SelectionPosition::operator >=(const SelectionPosition &other) const {
	if (position == other.position && virtualSpace == other.virtualSpace)
		return true;
	else
		return *this > other;
}

int SelectionRange::Length() const {
	if (anchor > caret) {
		return anchor.Position() - caret.Position();
	} else {
		return caret.Position() - anchor.Position();
	}
}

bool SelectionRange::Contains(int pos) const {
	if (anchor > caret)
		return (pos >= caret.Position()) && (pos <= anchor.Position());
	else
		return (pos >= anchor.Position()) && (pos <= caret.Position());
}

bool SelectionRange::Contains(SelectionPosition sp) const {
	if (anchor > caret)
		return (sp >= caret) && (sp <= anchor);
	else
		return (sp >= anchor) && (sp <= caret);
}

bool SelectionRange::ContainsCharacter(int posCharacter) const {
	if (anchor > caret)
		return (posCharacter >= caret.Position()) && (posCharacter < anchor.Position());
	else
		return (posCharacter >= anchor.Position()) && (posCharacter < caret.Position());
}

SelectionSegment SelectionRange::Intersect(SelectionSegment check) const {
	SelectionSegment inOrder(caret, anchor);
	if ((inOrder.start <= check.end) || (inOrder.end >= check.start)) {
		SelectionSegment portion = check;
		if (portion.start < inOrder.start)
			portion.start = inOrder.start;
		if (portion.end > inOrder.end)
			portion.end = inOrder.end;
		if (portion.start > portion.end)
			return SelectionSegment();
		else
			return portion;
	} else {
		return SelectionSegment();
	}
}

bool SelectionRange::Trim(SelectionRange range) {
	SelectionPosition startRange = range.Start();
	SelectionPosition endRange = range.End();
	SelectionPosition start = Start();
	SelectionPosition end = End();
	PLATFORM_ASSERT(start <= end);
	PLATFORM_ASSERT(startRange <= endRange);
	if ((startRange <= end) && (endRange >= start)) {
		if ((start > startRange) && (end < endRange)) {
			// Completely covered by range -> empty at start
			end = start;
		} else if ((start < startRange) && (end > endRange)) {
			// Completely covers range -> empty at start
			end = start;
		} else if (start <= startRange) {
			// Trim end
			end = startRange;
		} else { //
			PLATFORM_ASSERT(end >= endRange);
			// Trim start
			start = endRange;
		}
		if (anchor > caret) {
			caret = start;
			anchor = end;
		} else {
			anchor = start;
			caret = end;
		}
		return Empty();
	} else {
		return false;
	}
}

// If range is all virtual collapse to start of virtual space
void SelectionRange::MinimizeVirtualSpace() {
	if (caret.Position() == anchor.Position()) {
		int virtualSpace = caret.VirtualSpace();
		if (virtualSpace > anchor.VirtualSpace())
			virtualSpace = anchor.VirtualSpace();
		caret.SetVirtualSpace(virtualSpace);
		anchor.SetVirtualSpace(virtualSpace);
	}
}

Selection::Selection() : mainRange(0), moveExtends(false), tentativeMain(false), selType(selStream) {
	AddSelection(SelectionPosition(0));
}

Selection::~Selection() {
}

bool Selection::IsRectangular() const {
	return (selType == selRectangle) || (selType == selThin);
}

int Selection::MainCaret() const {
	return ranges[mainRange].caret.Position();
}

int Selection::MainAnchor() const {
	return ranges[mainRange].anchor.Position();
}

SelectionRange &Selection::Rectangular() {
	return rangeRectangular;
}

SelectionSegment Selection::Limits() const {
	if (ranges.empty()) {
		return SelectionSegment();
	} else {
		SelectionSegment sr(ranges[0].anchor, ranges[0].caret);
		for (size_t i=1; i<ranges.size(); i++) {
			sr.Extend(ranges[i].anchor);
			sr.Extend(ranges[i].caret);
		}
		return sr;
	}
}

SelectionSegment Selection::LimitsForRectangularElseMain() const {
	if (IsRectangular()) {
		return Limits();
	} else {
		return SelectionSegment(ranges[mainRange].caret, ranges[mainRange].anchor);
	}
}

size_t Selection::Count() const {
	return ranges.size();
}

size_t Selection::Main() const {
	return mainRange;
}

void Selection::SetMain(size_t r) {
	PLATFORM_ASSERT(r < ranges.size());
	mainRange = r;
}

SelectionRange &Selection::Range(size_t r) {
	return ranges[r];
}

SelectionRange &Selection::RangeMain() {
	return ranges[mainRange];
}

bool Selection::MoveExtends() const {
	return moveExtends;
}

void Selection::SetMoveExtends(bool moveExtends_) {
	moveExtends = moveExtends_;
}

bool Selection::Empty() const {
	for (size_t i=0; i<ranges.size(); i++) {
		if (!ranges[i].Empty())
			return false;
	}
	return true;
}

SelectionPosition Selection::Last() const {
	SelectionPosition lastPosition;
	for (size_t i=0; i<ranges.size(); i++) {
		if (lastPosition < ranges[i].caret)
			lastPosition = ranges[i].caret;
		if (lastPosition < ranges[i].anchor)
			lastPosition = ranges[i].anchor;
	}
	return lastPosition;
}

int Selection::Length() const {
	int len = 0;
	for (size_t i=0; i<ranges.size(); i++) {
		len += ranges[i].Length();
	}
	return len;
}

void Selection::MovePositions(bool insertion, int startChange, int length) {
	for (size_t i=0; i<ranges.size(); i++) {
		ranges[i].caret.MoveForInsertDelete(insertion, startChange, length);
		ranges[i].anchor.MoveForInsertDelete(insertion, startChange, length);
	}
}

void Selection::TrimSelection(SelectionRange range) {
	for (size_t i=0; i<ranges.size();) {
		if ((i != mainRange) && (ranges[i].Trim(range))) {
			// Trimmed to empty so remove
			for (size_t j=i; j<ranges.size()-1; j++) {
				ranges[j] = ranges[j+1];
				if (j == mainRange-1)
					mainRange--;
			}
			ranges.pop_back();
		} else {
			i++;
		}
	}
}

void Selection::SetSelection(SelectionRange range) {
	ranges.clear();
	ranges.push_back(range);
	mainRange = ranges.size() - 1;
}

void Selection::AddSelection(SelectionRange range) {
	TrimSelection(range);
	ranges.push_back(range);
	mainRange = ranges.size() - 1;
}

void Selection::AddSelectionWithoutTrim(SelectionRange range) {
	ranges.push_back(range);
	mainRange = ranges.size() - 1;
}

void Selection::TentativeSelection(SelectionRange range) {
	if (!tentativeMain) {
		rangesSaved = ranges;
	}
	ranges = rangesSaved;
	AddSelection(range);
	TrimSelection(ranges[mainRange]);
	tentativeMain = true;
}

void Selection::CommitTentative() {
	rangesSaved.clear();
	tentativeMain = false;
}

int Selection::CharacterInSelection(int posCharacter) const {
	for (size_t i=0; i<ranges.size(); i++) {
		if (ranges[i].ContainsCharacter(posCharacter))
			return i == mainRange ? 1 : 2;
	}
	return 0;
}

int Selection::InSelectionForEOL(int pos) const {
	for (size_t i=0; i<ranges.size(); i++) {
		if (!ranges[i].Empty() && (pos > ranges[i].Start().Position()) && (pos <= ranges[i].End().Position()))
			return i == mainRange ? 1 : 2;
	}
	return 0;
}

int Selection::VirtualSpaceFor(int pos) const {
	int virtualSpace = 0;
	for (size_t i=0; i<ranges.size(); i++) {
		if ((ranges[i].caret.Position() == pos) && (virtualSpace < ranges[i].caret.VirtualSpace()))
			virtualSpace = ranges[i].caret.VirtualSpace();
		if ((ranges[i].anchor.Position() == pos) && (virtualSpace < ranges[i].anchor.VirtualSpace()))
			virtualSpace = ranges[i].anchor.VirtualSpace();
	}
	return virtualSpace;
}

void Selection::Clear() {
	ranges.clear();
	ranges.push_back(SelectionRange());
	mainRange = ranges.size() - 1;
	selType = selStream;
	moveExtends = false;
	ranges[mainRange].Reset();
	rangeRectangular.Reset();
}

void Selection::RemoveDuplicates() {
	for (size_t i=0; i<ranges.size()-1; i++) {
		if (ranges[i].Empty()) {
			size_t j=i+1;
			while (j<ranges.size()) {
				if (ranges[i] == ranges[j]) {
					ranges.erase(ranges.begin() + j);
					if (mainRange >= j)
						mainRange--;
				} else {
					j++;
				}
			}
		}
	}
}

void Selection::RotateMain() {
	mainRange = (mainRange + 1) % ranges.size();
}

<|endoftext|>


<commit_before>// Sh: A GPU metaprogramming language.
//
// Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
// Project administrator: Michael D. McCool
// Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
//          Michael D. McCool
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must
// not claim that you wrote the original software. If you use this
// software in a product, an acknowledgment in the product documentation
// would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must
// not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//////////////////////////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifndef WIN32
#include <ltdl.h>
#else
#include <windows.h>
#endif

#include <algorithm>

#include "ShBackend.hpp"
#include "ShProgram.hpp"
#include "ShDebug.hpp"
#include "ShEnvironment.hpp"
#include "ShInternals.hpp"
#include "ShOptimizer.hpp"
#include "ShTransformer.hpp"

namespace SH {

ShBackend::ShBackendList* ShBackend::m_backends = 0;
bool ShBackend::m_doneInit = false;

ShBackendCode::~ShBackendCode()
{
}

ShBackend::ShBackend()
{
  init();
  m_backends->push_back(this);
}

ShBackend::~ShBackend()
{
  m_backends->erase(std::remove(begin(), end(), ShBackendPtr(this)), end());
}

ShBackend::ShBackendList::iterator ShBackend::begin()
{
  init();
  return m_backends->begin();
}

ShBackend::ShBackendList::iterator ShBackend::end()
{
  init();
  if (!m_backends) m_backends = new ShBackendList();
  return m_backends->end();
}

ShPointer<ShBackend> ShBackend::lookup(const std::string& name)
{
  init();

  for (ShBackendList::iterator I = begin(); I != end(); ++I) {
    if ((*I)->name() == name) return *I;
  }
#ifndef WIN32
  std::string libname(SH_INSTALL_PREFIX);
  libname += "/lib/sh/libsh" + name + ".so";

  lt_dlhandle handle = lt_dlopenext(libname.c_str());

  if (!handle) {
    SH_DEBUG_ERROR("Could not open " << libname << ": " << lt_dlerror());
    return 0;
  }

  for (ShBackendList::iterator I = begin(); I != end(); ++I) {
    if ((*I)->name() == name) {
      return *I;
    }
  }

  SH_DEBUG_ERROR("Could not find " << name << "backend");

  return 0;
#else

  SH_DEBUG_PRINT("Looking up " << name);

  HMODULE mod = NULL;
#define SH_WIN32_BACKENDS_DIR "\\DEV\\SH\\BACKENDS\\GL"

  std::string libname(SH_WIN32_BACKENDS_DIR);
  libname += "\\LIBSH";
  libname += name;
#ifdef SH_DEBUG
  libname += "D";
#endif
  libname += ".DLL";
  mod = LoadLibrary(libname.c_str());

  if (!mod) {
    SH_DEBUG_ERROR("Could not open " << libname);
    return 0;
  }

  for (ShBackendList::iterator I = begin(); I != end(); ++I) {
    if ((*I)->name() == name) {
      SH_DEBUG_PRINT("Found " << name << " at " << I->object());
      return *I;
    }
  }

  SH_DEBUG_ERROR("Could not find " << name << "backend");

  return 0;
#endif
}

void ShBackend::init()
{
  if (m_doneInit) return;
  SH_DEBUG_PRINT("Initializing backend system");

  m_backends = new ShBackendList();

#ifndef WIN32
  if (lt_dlinit()) {
    SH_DEBUG_ERROR("Error initializing ltdl: " << lt_dlerror());
  }

  std::string searchpath(SH_INSTALL_PREFIX);
  searchpath += "/lib/sh";

  if (lt_dladdsearchdir(searchpath.c_str())) {
    SH_DEBUG_ERROR("Could not add " + searchpath + " to search dir: " << lt_dlerror());
  }
#endif

  m_doneInit = true;
}

}
<commit_msg>Win32 backend loading changes...<commit_after>// Sh: A GPU metaprogramming language.
//
// Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
// Project administrator: Michael D. McCool
// Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
//          Michael D. McCool
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must
// not claim that you wrote the original software. If you use this
// software in a product, an acknowledgment in the product documentation
// would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must
// not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//////////////////////////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifndef WIN32
#include <ltdl.h>
#else
#include <windows.h>
#endif

#include <algorithm>

#include "ShBackend.hpp"
#include "ShProgram.hpp"
#include "ShDebug.hpp"
#include "ShEnvironment.hpp"
#include "ShInternals.hpp"
#include "ShOptimizer.hpp"
#include "ShTransformer.hpp"

namespace SH {

ShBackend::ShBackendList* ShBackend::m_backends = 0;
bool ShBackend::m_doneInit = false;

ShBackendCode::~ShBackendCode()
{
}

ShBackend::ShBackend()
{
  init();
  m_backends->push_back(this);
}

ShBackend::~ShBackend()
{
  m_backends->erase(std::remove(begin(), end(), ShBackendPtr(this)), end());
}

ShBackend::ShBackendList::iterator ShBackend::begin()
{
  init();
  return m_backends->begin();
}

ShBackend::ShBackendList::iterator ShBackend::end()
{
  init();
  if (!m_backends) m_backends = new ShBackendList();
  return m_backends->end();
}

ShPointer<ShBackend> ShBackend::lookup(const std::string& name)
{
  init();

  for (ShBackendList::iterator I = begin(); I != end(); ++I) {
    if ((*I)->name() == name) return *I;
  }
#ifndef WIN32
  std::string libname(SH_INSTALL_PREFIX);
  libname += "/lib/sh/libsh" + name + ".so";

  lt_dlhandle handle = lt_dlopenext(libname.c_str());

  if (!handle) {
    SH_DEBUG_ERROR("Could not open " << libname << ": " << lt_dlerror());
    return 0;
  }

  for (ShBackendList::iterator I = begin(); I != end(); ++I) {
    if ((*I)->name() == name) {
      return *I;
    }
  }

  SH_DEBUG_ERROR("Could not find " << name << "backend");

  return 0;
#else

  SH_DEBUG_PRINT("Looking up " << name);

  HMODULE mod = NULL;
  std::string libname("LIBSH");
  libname += name;
#ifdef SH_DEBUG
  libname += "D";
#endif
  libname += ".DLL";
  mod = LoadLibrary(libname.c_str());

  if (!mod) {
    SH_DEBUG_ERROR("Could not open " << libname);
    return 0;
  }

  for (ShBackendList::iterator I = begin(); I != end(); ++I) {
    if ((*I)->name() == name) {
      SH_DEBUG_PRINT("Found " << name << " at " << I->object());
      return *I;
    }
  }

  SH_DEBUG_ERROR("Could not find " << name << "backend");

  return 0;
#endif
}

void ShBackend::init()
{
  if (m_doneInit) return;
  SH_DEBUG_PRINT("Initializing backend system");

  m_backends = new ShBackendList();

#ifndef WIN32
  if (lt_dlinit()) {
    SH_DEBUG_ERROR("Error initializing ltdl: " << lt_dlerror());
  }

  std::string searchpath(SH_INSTALL_PREFIX);
  searchpath += "/lib/sh";

  if (lt_dladdsearchdir(searchpath.c_str())) {
    SH_DEBUG_ERROR("Could not add " + searchpath + " to search dir: " << lt_dlerror());
  }
#endif

  m_doneInit = true;
}

}
<|endoftext|>