<commit_before>/*
 * SimpleSphereRenderer.cpp
 *
 * Copyright (C) 2009 by VISUS (Universitaet Stuttgart)
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "vislib/graphics/gl/IncludeAllGL.h"
#include "mmcore/moldyn/SimpleSphereRenderer.h"
#include "mmcore/moldyn/MultiParticleDataCall.h"
#include "mmcore/CoreInstance.h"
#include "mmcore/view/CallClipPlane.h"
#include "mmcore/view/CallGetTransferFunction.h"
#include "mmcore/view/CallRender3D.h"
#include "vislib/assert.h"
#include "mmcore/param/FloatParam.h"

using namespace megamol::core;

/*
 * moldyn::SimpleSphereRenderer::SimpleSphereRenderer
 */
moldyn::SimpleSphereRenderer::SimpleSphereRenderer(void) : AbstractSimpleSphereRenderer(),
        sphereShader(),
        scalingParam("scaling", "scaling factor for particle radii") {
    // intentionally empty

    this->scalingParam << new core::param::FloatParam(1.0f);
    this->MakeSlotAvailable(&this->scalingParam);
}

/*
 * moldyn::SimpleSphereRenderer::~SimpleSphereRenderer
 */
moldyn::SimpleSphereRenderer::~SimpleSphereRenderer(void) {
    this->Release();
}

/*
 * moldyn::SimpleSphereRenderer::create
 */
bool moldyn::SimpleSphereRenderer::create(void) {
    ASSERT(IsAvailable());

    vislib::graphics::gl::ShaderSource vert, frag;

    if (!instance()->ShaderSourceFactory().MakeShaderSource("simplesphere::vertex", vert)) {
        return false;
    }
    if (!instance()->ShaderSourceFactory().MakeShaderSource("simplesphere::fragment", frag)) {
        return false;
    }

    //printf("\nVertex Shader:\n%s\n\nFragment Shader:\n%s\n",
    //    vert.WholeCode().PeekBuffer(),
    //    frag.WholeCode().PeekBuffer());

    try {
        if (!this->sphereShader.Create(vert.Code(), vert.Count(), frag.Code(), frag.Count())) {
            vislib::sys::Log::DefaultLog.WriteMsg(vislib::sys::Log::LEVEL_ERROR,
                "Unable to compile sphere shader: Unknown error\n");
            return false;
        }

    } catch(vislib::graphics::gl::AbstractOpenGLShader::CompileException ce) {
        vislib::sys::Log::DefaultLog.WriteMsg(vislib::sys::Log::LEVEL_ERROR,
            "Unable to compile sphere shader (@%s): %s\n",
            vislib::graphics::gl::AbstractOpenGLShader::CompileException::CompileActionName(
            ce.FailedAction()) ,ce.GetMsgA());
        return false;
    } catch(vislib::Exception e) {
        vislib::sys::Log::DefaultLog.WriteMsg(vislib::sys::Log::LEVEL_ERROR,
            "Unable to compile sphere shader: %s\n", e.GetMsgA());
        return false;
    } catch(...) {
        vislib::sys::Log::DefaultLog.WriteMsg(vislib::sys::Log::LEVEL_ERROR,
            "Unable to compile sphere shader: Unknown exception\n");
        return false;
    }

    return AbstractSimpleSphereRenderer::create();
}

/*
 * moldyn::SimpleSphereRenderer::release
 */
void moldyn::SimpleSphereRenderer::release(void) {
    this->sphereShader.Release();
    AbstractSimpleSphereRenderer::release();
}

/*
 * moldyn::SimpleSphereRenderer::Render
 */
bool moldyn::SimpleSphereRenderer::Render(Call& call) {
    view::CallRender3D *cr = dynamic_cast<view::CallRender3D*>(&call);
    if (cr == NULL) return false;

    float scaling = 1.0f;
    MultiParticleDataCall *c2 = this->getData(static_cast<unsigned int>(cr->Time()), scaling);
    if (c2 == NULL) return false;

    float clipDat[4];
    float clipCol[4];
    this->getClipData(clipDat, clipCol);

    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);

    float viewportStuff[4];
    ::glGetFloatv(GL_VIEWPORT, viewportStuff);
    glPointSize(vislib::math::Max(viewportStuff[2], viewportStuff[3]));
    if (viewportStuff[2] < 1.0f) viewportStuff[2] = 1.0f;
    if (viewportStuff[3] < 1.0f) viewportStuff[3] = 1.0f;
    viewportStuff[2] = 2.0f / viewportStuff[2];
    viewportStuff[3] = 2.0f / viewportStuff[3];

    this->sphereShader.Enable();
    glUniform4fv(this->sphereShader.ParameterLocation("viewAttr"), 1, viewportStuff);
    glUniform3fv(this->sphereShader.ParameterLocation("camIn"), 1, cr->GetCameraParameters()->Front().PeekComponents());
    glUniform3fv(this->sphereShader.ParameterLocation("camRight"), 1, cr->GetCameraParameters()->Right().PeekComponents());
    glUniform3fv(this->sphereShader.ParameterLocation("camUp"), 1, cr->GetCameraParameters()->Up().PeekComponents());
    glUniform1f(this->sphereShader.ParameterLocation("scaling"), this->scalingParam.Param<param::FloatParam>()->Value());

    glUniform4fv(this->sphereShader.ParameterLocation("clipDat"), 1, clipDat);
    glUniform4fv(this->sphereShader.ParameterLocation("clipCol"), 1, clipCol);

    glScalef(scaling, scaling, scaling);

    unsigned int cial = glGetAttribLocationARB(this->sphereShader, "colIdx");

    for (unsigned int i = 0; i < c2->GetParticleListCount(); i++) {
        MultiParticleDataCall::Particles &parts = c2->AccessParticles(i);
        float minC = 0.0f, maxC = 0.0f;
        unsigned int colTabSize = 0;

        // colour
        switch (parts.GetColourDataType()) {
            case MultiParticleDataCall::Particles::COLDATA_NONE:
                glColor3ubv(parts.GetGlobalColour());
                break;
            case MultiParticleDataCall::Particles::COLDATA_UINT8_RGB:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(3, GL_UNSIGNED_BYTE, parts.GetColourDataStride(), parts.GetColourData());
                break;
            case MultiParticleDataCall::Particles::COLDATA_UINT8_RGBA:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(4, GL_UNSIGNED_BYTE, parts.GetColourDataStride(), parts.GetColourData());
                break;
            case MultiParticleDataCall::Particles::COLDATA_FLOAT_RGB:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(3, GL_FLOAT, parts.GetColourDataStride(), parts.GetColourData());
                break;
            case MultiParticleDataCall::Particles::COLDATA_FLOAT_RGBA:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(4, GL_FLOAT, parts.GetColourDataStride(), parts.GetColourData());
                break;
            case MultiParticleDataCall::Particles::COLDATA_FLOAT_I:
            case MultiParticleDataCall::Particles::COLDATA_DOUBLE_I: {
                glEnableVertexAttribArrayARB(cial);
                if (parts.GetColourDataType() == SimpleSphericalParticles::COLDATA_FLOAT_I) {
                    glVertexAttribPointerARB(
                        cial, 1, GL_FLOAT, GL_FALSE, parts.GetColourDataStride(), parts.GetColourData());
                } else {
                    glVertexAttribPointerARB(
                        cial, 1, GL_DOUBLE, GL_FALSE, parts.GetColourDataStride(), parts.GetColourData());
                }
                glEnable(GL_TEXTURE_1D);

                view::CallGetTransferFunction *cgtf = this->getTFSlot.CallAs<view::CallGetTransferFunction>();
                if ((cgtf != NULL) && ((*cgtf)())) {
                    glBindTexture(GL_TEXTURE_1D, cgtf->OpenGLTexture());
                    colTabSize = cgtf->TextureSize();
                } else {
                    glBindTexture(GL_TEXTURE_1D, this->greyTF);
                    colTabSize = 2;
                }

                glUniform1i(this->sphereShader.ParameterLocation("colTab"), 0);
                minC = parts.GetMinColourIndexValue();
                maxC = parts.GetMaxColourIndexValue();
                glColor3ub(127, 127, 127);
            } break;
            case MultiParticleDataCall::Particles::COLDATA_USHORT_RGBA:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(4, GL_UNSIGNED_SHORT, parts.GetColourDataStride(), parts.GetColourData());
                break;
            default:
                glColor3ub(127, 127, 127);
                break;
        }

        // radius and position
        switch (parts.GetVertexDataType()) {
            case MultiParticleDataCall::Particles::VERTDATA_NONE:
                continue;
            case MultiParticleDataCall::Particles::VERTDATA_FLOAT_XYZ:
                glEnableClientState(GL_VERTEX_ARRAY);
                glUniform4f(this->sphereShader.ParameterLocation("inConsts1"), parts.GetGlobalRadius(), minC, maxC, float(colTabSize));
                glVertexPointer(3, GL_FLOAT, parts.GetVertexDataStride(), parts.GetVertexData());
                break;
            case MultiParticleDataCall::Particles::VERTDATA_FLOAT_XYZR:
                glEnableClientState(GL_VERTEX_ARRAY);
                glUniform4f(this->sphereShader.ParameterLocation("inConsts1"), -1.0f, minC, maxC, float(colTabSize));
                glVertexPointer(4, GL_FLOAT, parts.GetVertexDataStride(), parts.GetVertexData());
                break;
            case MultiParticleDataCall::Particles::VERTDATA_DOUBLE_XYZ:
                glEnableClientState(GL_VERTEX_ARRAY);
                glUniform4f(this->sphereShader.ParameterLocation("inConsts1"), parts.GetGlobalRadius(), minC, maxC, float(colTabSize));
                glVertexPointer(3, GL_DOUBLE, parts.GetVertexDataStride(), parts.GetVertexData());
                break;
            case MultiParticleDataCall::Particles::VERTDATA_SHORT_XYZ:
                glEnableClientState(GL_VERTEX_ARRAY);
                glUniform4f(this->sphereShader.ParameterLocation("inConsts1"), parts.GetGlobalRadius(), minC, maxC, float(colTabSize));
                glVertexPointer(3, GL_SHORT, parts.GetVertexDataStride(), parts.GetVertexData());
                break;
            default:
                continue;
        }

        glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(parts.GetCount()));

        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableVertexAttribArrayARB(cial);
        glDisable(GL_TEXTURE_1D);
    }

    c2->Unlock();

    this->sphereShader.Disable();

    glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);

    return true;
}
<commit_msg>Using L attrib pointer to avoid cast from double to float<commit_after>/*
 * SimpleSphereRenderer.cpp
 *
 * Copyright (C) 2009 by VISUS (Universitaet Stuttgart)
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "vislib/graphics/gl/IncludeAllGL.h"
#include "mmcore/moldyn/SimpleSphereRenderer.h"
#include "mmcore/moldyn/MultiParticleDataCall.h"
#include "mmcore/CoreInstance.h"
#include "mmcore/view/CallClipPlane.h"
#include "mmcore/view/CallGetTransferFunction.h"
#include "mmcore/view/CallRender3D.h"
#include "vislib/assert.h"
#include "mmcore/param/FloatParam.h"

using namespace megamol::core;

/*
 * moldyn::SimpleSphereRenderer::SimpleSphereRenderer
 */
moldyn::SimpleSphereRenderer::SimpleSphereRenderer(void) : AbstractSimpleSphereRenderer(),
        sphereShader(),
        scalingParam("scaling", "scaling factor for particle radii") {
    // intentionally empty

    this->scalingParam << new core::param::FloatParam(1.0f);
    this->MakeSlotAvailable(&this->scalingParam);
}

/*
 * moldyn::SimpleSphereRenderer::~SimpleSphereRenderer
 */
moldyn::SimpleSphereRenderer::~SimpleSphereRenderer(void) {
    this->Release();
}

/*
 * moldyn::SimpleSphereRenderer::create
 */
bool moldyn::SimpleSphereRenderer::create(void) {
    ASSERT(IsAvailable());

    vislib::graphics::gl::ShaderSource vert, frag;

    if (!instance()->ShaderSourceFactory().MakeShaderSource("simplesphere::vertex", vert)) {
        return false;
    }
    if (!instance()->ShaderSourceFactory().MakeShaderSource("simplesphere::fragment", frag)) {
        return false;
    }

    //printf("\nVertex Shader:\n%s\n\nFragment Shader:\n%s\n",
    //    vert.WholeCode().PeekBuffer(),
    //    frag.WholeCode().PeekBuffer());

    try {
        if (!this->sphereShader.Create(vert.Code(), vert.Count(), frag.Code(), frag.Count())) {
            vislib::sys::Log::DefaultLog.WriteMsg(vislib::sys::Log::LEVEL_ERROR,
                "Unable to compile sphere shader: Unknown error\n");
            return false;
        }

    } catch(vislib::graphics::gl::AbstractOpenGLShader::CompileException ce) {
        vislib::sys::Log::DefaultLog.WriteMsg(vislib::sys::Log::LEVEL_ERROR,
            "Unable to compile sphere shader (@%s): %s\n",
            vislib::graphics::gl::AbstractOpenGLShader::CompileException::CompileActionName(
            ce.FailedAction()) ,ce.GetMsgA());
        return false;
    } catch(vislib::Exception e) {
        vislib::sys::Log::DefaultLog.WriteMsg(vislib::sys::Log::LEVEL_ERROR,
            "Unable to compile sphere shader: %s\n", e.GetMsgA());
        return false;
    } catch(...) {
        vislib::sys::Log::DefaultLog.WriteMsg(vislib::sys::Log::LEVEL_ERROR,
            "Unable to compile sphere shader: Unknown exception\n");
        return false;
    }

    return AbstractSimpleSphereRenderer::create();
}

/*
 * moldyn::SimpleSphereRenderer::release
 */
void moldyn::SimpleSphereRenderer::release(void) {
    this->sphereShader.Release();
    AbstractSimpleSphereRenderer::release();
}

/*
 * moldyn::SimpleSphereRenderer::Render
 */
bool moldyn::SimpleSphereRenderer::Render(Call& call) {
    view::CallRender3D *cr = dynamic_cast<view::CallRender3D*>(&call);
    if (cr == NULL) return false;

    float scaling = 1.0f;
    MultiParticleDataCall *c2 = this->getData(static_cast<unsigned int>(cr->Time()), scaling);
    if (c2 == NULL) return false;

    float clipDat[4];
    float clipCol[4];
    this->getClipData(clipDat, clipCol);

    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);

    float viewportStuff[4];
    ::glGetFloatv(GL_VIEWPORT, viewportStuff);
    glPointSize(vislib::math::Max(viewportStuff[2], viewportStuff[3]));
    if (viewportStuff[2] < 1.0f) viewportStuff[2] = 1.0f;
    if (viewportStuff[3] < 1.0f) viewportStuff[3] = 1.0f;
    viewportStuff[2] = 2.0f / viewportStuff[2];
    viewportStuff[3] = 2.0f / viewportStuff[3];

    this->sphereShader.Enable();
    glUniform4fv(this->sphereShader.ParameterLocation("viewAttr"), 1, viewportStuff);
    glUniform3fv(this->sphereShader.ParameterLocation("camIn"), 1, cr->GetCameraParameters()->Front().PeekComponents());
    glUniform3fv(this->sphereShader.ParameterLocation("camRight"), 1, cr->GetCameraParameters()->Right().PeekComponents());
    glUniform3fv(this->sphereShader.ParameterLocation("camUp"), 1, cr->GetCameraParameters()->Up().PeekComponents());
    glUniform1f(this->sphereShader.ParameterLocation("scaling"), this->scalingParam.Param<param::FloatParam>()->Value());

    glUniform4fv(this->sphereShader.ParameterLocation("clipDat"), 1, clipDat);
    glUniform4fv(this->sphereShader.ParameterLocation("clipCol"), 1, clipCol);

    glScalef(scaling, scaling, scaling);

    unsigned int cial = glGetAttribLocationARB(this->sphereShader, "colIdx");

    for (unsigned int i = 0; i < c2->GetParticleListCount(); i++) {
        MultiParticleDataCall::Particles &parts = c2->AccessParticles(i);
        float minC = 0.0f, maxC = 0.0f;
        unsigned int colTabSize = 0;

        // colour
        switch (parts.GetColourDataType()) {
            case MultiParticleDataCall::Particles::COLDATA_NONE:
                glColor3ubv(parts.GetGlobalColour());
                break;
            case MultiParticleDataCall::Particles::COLDATA_UINT8_RGB:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(3, GL_UNSIGNED_BYTE, parts.GetColourDataStride(), parts.GetColourData());
                break;
            case MultiParticleDataCall::Particles::COLDATA_UINT8_RGBA:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(4, GL_UNSIGNED_BYTE, parts.GetColourDataStride(), parts.GetColourData());
                break;
            case MultiParticleDataCall::Particles::COLDATA_FLOAT_RGB:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(3, GL_FLOAT, parts.GetColourDataStride(), parts.GetColourData());
                break;
            case MultiParticleDataCall::Particles::COLDATA_FLOAT_RGBA:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(4, GL_FLOAT, parts.GetColourDataStride(), parts.GetColourData());
                break;
            case MultiParticleDataCall::Particles::COLDATA_FLOAT_I:
            case MultiParticleDataCall::Particles::COLDATA_DOUBLE_I: {
                glEnableVertexAttribArrayARB(cial);
                if (parts.GetColourDataType() == SimpleSphericalParticles::COLDATA_FLOAT_I) {
                    glVertexAttribPointerARB(
                        cial, 1, GL_FLOAT, GL_FALSE, parts.GetColourDataStride(), parts.GetColourData());
                } else {
                    glVertexAttribLPointer(cial, 1, GL_DOUBLE, parts.GetColourDataStride(), parts.GetColourData());
                }
                glEnable(GL_TEXTURE_1D);

                view::CallGetTransferFunction *cgtf = this->getTFSlot.CallAs<view::CallGetTransferFunction>();
                if ((cgtf != NULL) && ((*cgtf)())) {
                    glBindTexture(GL_TEXTURE_1D, cgtf->OpenGLTexture());
                    colTabSize = cgtf->TextureSize();
                } else {
                    glBindTexture(GL_TEXTURE_1D, this->greyTF);
                    colTabSize = 2;
                }

                glUniform1i(this->sphereShader.ParameterLocation("colTab"), 0);
                minC = parts.GetMinColourIndexValue();
                maxC = parts.GetMaxColourIndexValue();
                glColor3ub(127, 127, 127);
            } break;
            case MultiParticleDataCall::Particles::COLDATA_USHORT_RGBA:
                glEnableClientState(GL_COLOR_ARRAY);
                glColorPointer(4, GL_UNSIGNED_SHORT, parts.GetColourDataStride(), parts.GetColourData());
                break;
            default:
                glColor3ub(127, 127, 127);
                break;
        }

        // radius and position
        switch (parts.GetVertexDataType()) {
            case MultiParticleDataCall::Particles::VERTDATA_NONE:
                continue;
            case MultiParticleDataCall::Particles::VERTDATA_FLOAT_XYZ:
                glEnableClientState(GL_VERTEX_ARRAY);
                glUniform4f(this->sphereShader.ParameterLocation("inConsts1"), parts.GetGlobalRadius(), minC, maxC, float(colTabSize));
                glVertexPointer(3, GL_FLOAT, parts.GetVertexDataStride(), parts.GetVertexData());
                break;
            case MultiParticleDataCall::Particles::VERTDATA_FLOAT_XYZR:
                glEnableClientState(GL_VERTEX_ARRAY);
                glUniform4f(this->sphereShader.ParameterLocation("inConsts1"), -1.0f, minC, maxC, float(colTabSize));
                glVertexPointer(4, GL_FLOAT, parts.GetVertexDataStride(), parts.GetVertexData());
                break;
            case MultiParticleDataCall::Particles::VERTDATA_DOUBLE_XYZ:
                glEnableClientState(GL_VERTEX_ARRAY);
                glUniform4f(this->sphereShader.ParameterLocation("inConsts1"), parts.GetGlobalRadius(), minC, maxC, float(colTabSize));
                glVertexPointer(3, GL_DOUBLE, parts.GetVertexDataStride(), parts.GetVertexData());
                break;
            case MultiParticleDataCall::Particles::VERTDATA_SHORT_XYZ:
                glEnableClientState(GL_VERTEX_ARRAY);
                glUniform4f(this->sphereShader.ParameterLocation("inConsts1"), parts.GetGlobalRadius(), minC, maxC, float(colTabSize));
                glVertexPointer(3, GL_SHORT, parts.GetVertexDataStride(), parts.GetVertexData());
                break;
            default:
                continue;
        }

        glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(parts.GetCount()));

        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableVertexAttribArrayARB(cial);
        glDisable(GL_TEXTURE_1D);
    }

    c2->Unlock();

    this->sphereShader.Disable();

    glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);

    return true;
}
<|endoftext|>


<commit_before>//
//  Created by Asger Nyman Christiansen on 18/12/2016.
//  Copyright © 2016 Asger Nyman Christiansen. All rights reserved.
//

#include "GLCamera.h"
#include "MeshCreator.h"
#include "materials/GLFlatColorMaterial.h"
#include "materials/GLColorMaterial.h"

#define GLFW_INCLUDE_NONE
#include "glfw3.h"

using namespace std;
using namespace glm;
using namespace gle;
using namespace mesh;

GLFWwindow* gWindow = NULL;

shared_ptr<mat4> cube_rotation = make_shared<mat4>(1.);

void on_error(int errorCode, const char* msg)
{
    throw std::runtime_error(msg);
}

void print_fps(double elapsedTime)
{
    static int draws = 0;
    draws++;
    static float seconds = 0.;
    seconds += elapsedTime;
    if(seconds > 5)
    {
        std::cout << "FPS: " << ((float)draws)/seconds << std::endl;
        seconds = 0.;
        draws = 0;
    }
}

void update()
{
    static float last_time = glfwGetTime();
    float time = glfwGetTime();
    float elapsed_time = time - last_time;

    print_fps(elapsed_time);
    *cube_rotation = rotate(rotate(*cube_rotation, elapsed_time, vec3(0., 1., 0.)), elapsed_time, vec3(1., 0., 0.));

    last_time = time;
}

void create_cube(GLScene& root, const vec3& translation, std::shared_ptr<GLMaterial> material)
{
    auto geometry = MeshCreator::create_box(false);

    auto translation_node = std::make_shared<GLTransformationNode>(translate(translation));
    root.add_child(translation_node);
    auto rotation_node = std::make_shared<GLTransformationNode>(cube_rotation);
    translation_node->add_child(rotation_node);
    rotation_node->add_leaf(geometry, material);
}

void create_cubes(GLScene& root)
{
    auto flat_material = make_shared<GLFlatColorMaterial>(vec3(0.5, 0.1, 0.7));
    auto color_material = make_shared<GLColorMaterial>(vec3(0.5, 0.1, 0.7));

    create_cube(root, vec3(-2., 2., 0.), color_material);
    create_cube(root, vec3(-2., -2., 0.), flat_material);
    create_cube(root, vec3(2., 2., 0.), flat_material);
    create_cube(root, vec3(2., -2., 0.), color_material);
}

int main(int argc, const char * argv[])
{
    int WIN_SIZE_X = 1200;
    int WIN_SIZE_Y = 700;

    // initialise GLFW
    glfwSetErrorCallback(on_error);
    if(!glfwInit())
        throw std::runtime_error("glfwInit failed");

    // Open a window with GLFW
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    gWindow = glfwCreateWindow(WIN_SIZE_X, WIN_SIZE_Y, "GLEngine example 1", NULL, NULL);
    if(!gWindow)
        throw std::runtime_error("glfwCreateWindow failed. Can your hardware handle OpenGL 3.3?");

    // GLFW settings
    glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    glfwSetCursorPos(gWindow, 0, 0);
    glfwMakeContextCurrent(gWindow);
    glfwGetFramebufferSize(gWindow, &WIN_SIZE_X, &WIN_SIZE_Y);

    // Create camera
    auto camera = GLCamera(WIN_SIZE_X, WIN_SIZE_Y);
    camera.set_view(vec3(0., 0., 10.), vec3(0., 0., -1.));

    // Create scene
    auto scene = GLScene();
    scene.add_light(std::make_shared<GLDirectionalLight>(glm::vec3(1., -1., 0.)));
    create_cubes(scene);

    // run while the window is open
    while(!glfwWindowShouldClose(gWindow))
    {
        // process pending events
        glfwPollEvents();

        // update the scene based on the time elapsed since last update
        update();

        // draw one frame
        camera.draw(scene);

        glfwSwapBuffers(gWindow);

        //exit program if escape key is pressed
        if(glfwGetKey(gWindow, GLFW_KEY_ESCAPE))
            glfwSetWindowShouldClose(gWindow, GL_TRUE);
    }

    // clean up and exit
    glfwTerminate();
    return 0;
}
<commit_msg>Fixed hello world example.<commit_after>//
//  Created by Asger Nyman Christiansen on 18/12/2016.
//  Copyright © 2016 Asger Nyman Christiansen. All rights reserved.
//

#include "GLCamera.h"
#include "MeshCreator.h"
#include "materials/GLFlatColorMaterial.h"
#include "materials/GLColorMaterial.h"
#include "gtx/rotate_vector.hpp"

#define GLFW_INCLUDE_NONE
#include "glfw3.h"

using namespace std;
using namespace glm;
using namespace gle;
using namespace mesh;

GLFWwindow* gWindow = NULL;

shared_ptr<mat4> cube_rotation = make_shared<mat4>(1.);

void on_error(int errorCode, const char* msg)
{
    throw std::runtime_error(msg);
}

void print_fps(double elapsedTime)
{
    static int draws = 0;
    draws++;
    static float seconds = 0.;
    seconds += elapsedTime;
    if(seconds > 5)
    {
        std::cout << "FPS: " << ((float)draws)/seconds << std::endl;
        seconds = 0.;
        draws = 0;
    }
}

void update()
{
    static float last_time = glfwGetTime();
    float time = glfwGetTime();
    float elapsed_time = time - last_time;

    print_fps(elapsed_time);
    *cube_rotation = rotate(rotate(*cube_rotation, elapsed_time, vec3(0., 1., 0.)), elapsed_time, vec3(1., 0., 0.));

    last_time = time;
}

void create_cube(GLScene& root, const vec3& translation, std::shared_ptr<GLMaterial> material)
{
    auto geometry = MeshCreator::create_box(false);

    auto translation_node = std::make_shared<GLTransformationNode>(translate(translation));
    root.add_child(translation_node);
    auto rotation_node = std::make_shared<GLTransformationNode>(cube_rotation);
    translation_node->add_child(rotation_node);
    rotation_node->add_leaf(geometry, material);
}

void create_cubes(GLScene& root)
{
    auto flat_material = make_shared<GLFlatColorMaterial>(vec3(0.5, 0.1, 0.7));
    auto color_material = make_shared<GLColorMaterial>(vec3(0.5, 0.1, 0.7));

    create_cube(root, vec3(-2., 2., 0.), color_material);
    create_cube(root, vec3(-2., -2., 0.), flat_material);
    create_cube(root, vec3(2., 2., 0.), flat_material);
    create_cube(root, vec3(2., -2., 0.), color_material);
}

int main(int argc, const char * argv[])
{
    int WIN_SIZE_X = 1200;
    int WIN_SIZE_Y = 700;

    // initialise GLFW
    glfwSetErrorCallback(on_error);
    if(!glfwInit())
        throw std::runtime_error("glfwInit failed");

    // Open a window with GLFW
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    gWindow = glfwCreateWindow(WIN_SIZE_X, WIN_SIZE_Y, "GLEngine example 1", NULL, NULL);
    if(!gWindow)
        throw std::runtime_error("glfwCreateWindow failed. Can your hardware handle OpenGL 3.3?");

    // GLFW settings
    glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    glfwSetCursorPos(gWindow, 0, 0);
    glfwMakeContextCurrent(gWindow);
    glfwGetFramebufferSize(gWindow, &WIN_SIZE_X, &WIN_SIZE_Y);

    // Create camera
    auto camera = GLCamera(WIN_SIZE_X, WIN_SIZE_Y);
    camera.set_view(vec3(0., 0., 10.), vec3(0., 0., -1.));

    // Create scene
    auto scene = GLScene();
    scene.add_light(std::make_shared<GLDirectionalLight>(glm::vec3(1., -1., 0.)));
    create_cubes(scene);

    // run while the window is open
    while(!glfwWindowShouldClose(gWindow))
    {
        // process pending events
        glfwPollEvents();

        // update the scene based on the time elapsed since last update
        update();

        // draw one frame
        camera.draw(scene);

        glfwSwapBuffers(gWindow);

        //exit program if escape key is pressed
        if(glfwGetKey(gWindow, GLFW_KEY_ESCAPE))
            glfwSetWindowShouldClose(gWindow, GL_TRUE);
    }

    // clean up and exit
    glfwTerminate();
    return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include <future>
#include <utility>
#include <functional>
#include <type_traits>
#include <agency/execution_agent.hpp>
#include <functional>
#include <agency/executor_traits.hpp>
#include <agency/sequential_executor.hpp>
#include <agency/concurrent_executor.hpp>
#include <agency/parallel_executor.hpp>
#include <agency/vector_executor.hpp>
#include <agency/nested_executor.hpp>
#include <memory>
#include <tuple>
#include <initializer_list>
#include <agency/detail/tuple.hpp>
#include <agency/detail/shape_cast.hpp>
#include <agency/detail/index_cast.hpp>

namespace agency
{

// XXX add is_execution_policy_v
// XXX maybe this should simply check for the existence of the
//     nested type T::execution_category?
// XXX the problem is that execution agent as well as execution_agent_traits
//     also define this typedef
template<class T> struct is_execution_policy : std::false_type {};

// customization point -- allow users to specialize this
// to change the type of execution policy based on the type of an executor
template<class ExecutionPolicy, class Executor>
struct rebind_executor;

template<class ExecutionPolicy, class Executor>
using rebind_executor_t = typename rebind_executor<ExecutionPolicy,Executor>::type;

namespace detail
{

template<class T, class Result = void>
struct enable_if_execution_policy
  : std::enable_if<is_execution_policy<T>::value,Result>
{};

template<class T, class Result = void>
struct disable_if_execution_policy
  : std::enable_if<!is_execution_policy<T>::value,Result>
{};

template<class... Types>
struct last_type_impl
{
  typedef typename std::tuple_element<sizeof...(Types) - 1, std::tuple<Types...>>::type type;
};

template<>
struct last_type_impl<>
{
  typedef void type;
};

template<class... Types>
using last_type = typename last_type_impl<Types...>::type;

template<class Result, class... Args>
struct enable_if_nested_call
  : enable_if_execution_policy<last_type<Args...>, Result>
{};

template<class Result, class... Args>
struct disable_if_nested_call
  : disable_if_execution_policy<
      decay_t<last_type<Args...>>,
      Result
    >
{};

// declare nested_execution_policy for basic_execution_policy's use below
template<class ExecutionPolicy1, class ExecutionPolicy2>
class nested_execution_policy;

// XXX we should assert that ExecutionCategory is stronger than the category of ExecutionAgent
// XXX another way to order these parameters would be
// ExecutionCategory, BulkExecutor, ExecutionAgent = __default_execution_agent<ExecutionAgent>, DerivedExecutionPolicy
template<class ExecutionAgent,
         class BulkExecutor,
         class ExecutionCategory = typename execution_agent_traits<ExecutionAgent>::execution_category,
         class DerivedExecutionPolicy = void>
class basic_execution_policy
{
  public:
    using execution_agent_type = ExecutionAgent;
    using executor_type        = BulkExecutor;
    using execution_category   = ExecutionCategory;

  private:
    using derived_type         = typename std::conditional<
      std::is_same<DerivedExecutionPolicy,void>::value,
      basic_execution_policy,
      DerivedExecutionPolicy
    >::type;

    using agent_traits         = execution_agent_traits<execution_agent_type>;

  public:
    using param_type           = typename agent_traits::param_type;

    basic_execution_policy() = default;

    basic_execution_policy(const param_type& param, const executor_type& executor = executor_type{})
      : param_(param),
        executor_(executor)
    {}

    const param_type& param() const
    {
      return param_;
    }

    executor_type& executor() const
    {
      return executor_;
    }

    template<class OtherExecutor>
    rebind_executor_t<derived_type,OtherExecutor> on(const OtherExecutor& executor) const
    {
      return rebind_executor_t<derived_type,OtherExecutor>(param(), executor);
    }

    // this is the flat form of operator()
    template<class Arg1, class... Args>
    typename detail::disable_if_nested_call<derived_type, Arg1, Args...>::type
      operator()(Arg1&& arg1, Args&&... args) const
    {
      return derived_type{param_type{std::forward<Arg1>(arg1), std::forward<Args>(args)...}, executor()};
    }

    // this is the nested form of operator()
    template<class Arg1, class... Args>
    typename detail::enable_if_nested_call<
      detail::nested_execution_policy<
        derived_type,
        decay_t<last_type<Arg1,Args...>>
      >,
      Arg1, Args...
    >::type
      operator()(Arg1&& arg1, Args&&... args) const
    {
      // wrap the args in a tuple so we can manipulate them easier
      auto arg_tuple = detail::forward_as_tuple(std::forward<Arg1>(arg1), std::forward<Args>(args)...);

      // get the arguments to the outer execution policy
      auto outer_args = detail::tuple_drop_last(arg_tuple);

      // create the outer execution policy
      auto outer = detail::tuple_apply(*this, outer_args);

      // get the inner execution policy
      auto inner = __tu::tuple_last(arg_tuple);

      // return the nesting of the two policies
      return detail::nested_execution_policy<derived_type,decltype(inner)>(outer, inner);
    }

    template<class Arg1, class... Args>
    derived_type operator()(std::initializer_list<Arg1> arg1, std::initializer_list<Args>... args) const
    {
      return derived_type{param_type{std::move(arg1), std::move(args)...}, executor()};
    }

  protected:
    param_type param_;

    // executor_ needs to be mutable, because:
    // * the global execution policy objects are constexpr
    // * executor.bulk_add() is a non-const member function
    mutable executor_type executor_;
};

// ExecutionCategory1 corresponds to the category of the executor
// XXX ExecutionCategory2 corresponds to the category of the policy
// XXX this overload should only be selected if ExecutionCategory1 is stronger than ExecutionCategory2
template<class ExecutionCategory1, class ExecutionAgent, class BulkExecutor, class ExecutionCategory2, class DerivedExecutionPolicy, class Function>
void bulk_invoke(ExecutionCategory1,
                 const basic_execution_policy<ExecutionAgent,BulkExecutor,ExecutionCategory2,DerivedExecutionPolicy>& exec,
                 Function f)
{
  using traits = execution_agent_traits<ExecutionAgent>;

  auto param = exec.param();
  auto agent_shape = traits::domain(param).shape();
  auto shared_init = traits::make_shared_initializer(param);

  using executor_index_type = typename executor_traits<BulkExecutor>::index_type;
  using shared_param_type = typename executor_traits<BulkExecutor>::template shared_param_type<decltype(shared_init)>;

  // convert the shape of the agent into the type of the executor's shape
  using executor_shape_type = typename executor_traits<BulkExecutor>::shape_type;
  executor_shape_type executor_shape = detail::shape_cast<executor_shape_type>(agent_shape);

  return executor_traits<BulkExecutor>::bulk_invoke(exec.executor(), [=](executor_index_type executor_idx, shared_param_type shared_params)
  {
    // convert the index of the executor into the type of the agent's index
    using agent_index_type = typename traits::index_type;
    auto agent_idx = detail::index_cast<agent_index_type>(executor_idx, executor_shape, agent_shape);

    traits::execute(f, agent_idx, param, shared_params);
  },
  executor_shape,
  shared_init);
}

// ExecutionCategory1 corresponds to the category of the executor
// XXX ExecutionCategory2 corresponds to the category of the policy
// XXX this overload should only be selected if ExecutionCategory1 is stronger than ExecutionCategory2
template<class ExecutionCategory1, class ExecutionAgent, class BulkExecutor, class ExecutionCategory2, class DerivedExecutionPolicy, class Function>
std::future<void> bulk_async(ExecutionCategory1,
                             const basic_execution_policy<ExecutionAgent,BulkExecutor,ExecutionCategory2,DerivedExecutionPolicy>& exec,
                             Function f)
{
  using traits = execution_agent_traits<ExecutionAgent>;

  auto param = exec.param();
  auto agent_shape = traits::domain(param).shape();
  auto shared_init = traits::make_shared_initializer(param);

  using executor_index_type = typename executor_traits<BulkExecutor>::index_type;
  using shared_param_type = typename executor_traits<BulkExecutor>::template shared_param_type<decltype(shared_init)>;

  // convert the shape of the agent into the type of the executor's shape
  using executor_shape_type = typename executor_traits<BulkExecutor>::shape_type;
  executor_shape_type executor_shape = detail::shape_cast<executor_shape_type>(agent_shape);

  return executor_traits<BulkExecutor>::bulk_async(exec.executor(), [=](executor_index_type executor_idx, shared_param_type shared_params)
  {
    // convert the index of the executor into the type of the agent's index
    using agent_index_type = typename traits::index_type;
    auto agent_idx = detail::index_cast<agent_index_type>(executor_idx, executor_shape, agent_shape);

    traits::execute(f, agent_idx, param, shared_params);
  },
  executor_shape,
  shared_init);
}

template<class ExecutionPolicy1, class ExecutionPolicy2>
class nested_execution_policy
  : public basic_execution_policy<
      execution_group<
        typename ExecutionPolicy1::execution_agent_type,
        typename ExecutionPolicy2::execution_agent_type
      >,
      nested_executor<
        typename ExecutionPolicy1::executor_type,
        typename ExecutionPolicy2::executor_type
      >,
      nested_execution_tag<
        typename ExecutionPolicy1::execution_category,
        typename ExecutionPolicy2::execution_category
      >,
      nested_execution_policy<ExecutionPolicy1,ExecutionPolicy2>
    >
{
  private:
    using super_t = basic_execution_policy<
      execution_group<
        typename ExecutionPolicy1::execution_agent_type,
        typename ExecutionPolicy2::execution_agent_type
      >,
      nested_executor<
        typename ExecutionPolicy1::executor_type,
        typename ExecutionPolicy2::executor_type
      >,
      nested_execution_tag<
        typename ExecutionPolicy1::execution_category,
        typename ExecutionPolicy2::execution_category
      >,
      nested_execution_policy<ExecutionPolicy1,ExecutionPolicy2>
    >;

  public:
    using outer_execution_policy_type = ExecutionPolicy1;
    using inner_execution_policy_type = ExecutionPolicy2;
    using typename super_t::execution_agent_type;
    using typename super_t::executor_type;

    nested_execution_policy(const outer_execution_policy_type& outer_exec,
                            const inner_execution_policy_type& inner_exec)
      : super_t(typename execution_agent_type::param_type(outer_exec.param(), inner_exec.param()),
                executor_type(outer_exec.executor(), inner_exec.executor()))
    {}
};

} // end detail

template<class ExecutionAgent, class BulkExecutor, class ExecutionCategory, class DerivedExecutionPolicy>
struct is_execution_policy<detail::basic_execution_policy<ExecutionAgent,BulkExecutor,ExecutionCategory,DerivedExecutionPolicy>> : std::true_type {};

template<class T1, class T2>
struct is_execution_policy<detail::nested_execution_policy<T1,T2>>
  : std::integral_constant<
      bool,
      is_execution_policy<T1>::value && is_execution_policy<T2>::value
    >
{};

template<class ExecutionPolicy, class Executor>
struct rebind_executor
{
  using type = detail::basic_execution_policy<
    typename ExecutionPolicy::execution_agent_type,
    Executor
  >;
};

class sequential_execution_policy : public detail::basic_execution_policy<sequential_agent, sequential_executor, sequential_execution_tag, sequential_execution_policy>
{
  private:
    using super_t = detail::basic_execution_policy<sequential_agent, sequential_executor, sequential_execution_tag, sequential_execution_policy>;

  public:
    using super_t::basic_execution_policy;
};

template<> struct is_execution_policy<sequential_execution_policy> : std::true_type {};

const sequential_execution_policy seq{};

class concurrent_execution_policy : public detail::basic_execution_policy<concurrent_agent, concurrent_executor, concurrent_execution_tag, concurrent_execution_policy>
{
  private:
    using super_t = detail::basic_execution_policy<concurrent_agent, concurrent_executor, concurrent_execution_tag, concurrent_execution_policy>;

  public:
    using super_t::basic_execution_policy;
};

template<> struct is_execution_policy<concurrent_execution_policy> : std::true_type {};

const concurrent_execution_policy con{};

class parallel_execution_policy : public detail::basic_execution_policy<parallel_agent, parallel_executor, parallel_execution_tag, parallel_execution_policy>
{
  private:
    using super_t = detail::basic_execution_policy<parallel_agent, parallel_executor, parallel_execution_tag, parallel_execution_policy>;

  public:
    using super_t::basic_execution_policy;
};

template<> struct is_execution_policy<parallel_execution_policy> : std::true_type {};

const parallel_execution_policy par{};

class vector_execution_policy : public detail::basic_execution_policy<vector_agent, vector_executor, vector_execution_tag, vector_execution_policy>
{
  private:
    using super_t = detail::basic_execution_policy<vector_agent, vector_executor, vector_execution_tag, vector_execution_policy>;

  public:
    using super_t::basic_execution_policy;
};

template<> struct is_execution_policy<vector_execution_policy> : std::true_type {};

const vector_execution_policy vec{};

template<class ExecutionPolicy, class Function, class... Args>
typename detail::enable_if_execution_policy<detail::decay_t<ExecutionPolicy>>::type
bulk_invoke(ExecutionPolicy&& exec, Function&& f, Args&&... args)
{
  // XXX the execution_category we dispatch on should be the category of the policy's executor
  using execution_category = typename detail::decay_t<ExecutionPolicy>::execution_category;
  return detail::bulk_invoke(execution_category(), exec, std::bind(f, std::placeholders::_1, args...));
}

template<class ExecutionPolicy, class Function, class... Args>
typename detail::enable_if_execution_policy<detail::decay_t<ExecutionPolicy>,std::future<void>>::type
bulk_async(ExecutionPolicy&& exec, Function&& f, Args&&... args)
{
  // XXX the execution_category we dispatch on should be the category of the policy's executor
  using execution_category = typename detail::decay_t<ExecutionPolicy>::execution_category;
  return detail::bulk_async(execution_category(), exec, std::bind(f, std::placeholders::_1, args...));
}

} // end agency

<commit_msg>Rename detail::bulk_invoke & detail::bulk_async to detail::bulk_invoke_impl & detail::bulk_async_impl<commit_after>#pragma once

#include <future>
#include <utility>
#include <functional>
#include <type_traits>
#include <agency/execution_agent.hpp>
#include <functional>
#include <agency/executor_traits.hpp>
#include <agency/sequential_executor.hpp>
#include <agency/concurrent_executor.hpp>
#include <agency/parallel_executor.hpp>
#include <agency/vector_executor.hpp>
#include <agency/nested_executor.hpp>
#include <memory>
#include <tuple>
#include <initializer_list>
#include <agency/detail/tuple.hpp>
#include <agency/detail/shape_cast.hpp>
#include <agency/detail/index_cast.hpp>

namespace agency
{

// XXX add is_execution_policy_v
// XXX maybe this should simply check for the existence of the
//     nested type T::execution_category?
// XXX the problem is that execution agent as well as execution_agent_traits
//     also define this typedef
template<class T> struct is_execution_policy : std::false_type {};

// customization point -- allow users to specialize this
// to change the type of execution policy based on the type of an executor
template<class ExecutionPolicy, class Executor>
struct rebind_executor;

template<class ExecutionPolicy, class Executor>
using rebind_executor_t = typename rebind_executor<ExecutionPolicy,Executor>::type;

namespace detail
{

template<class T, class Result = void>
struct enable_if_execution_policy
  : std::enable_if<is_execution_policy<T>::value,Result>
{};

template<class T, class Result = void>
struct disable_if_execution_policy
  : std::enable_if<!is_execution_policy<T>::value,Result>
{};

template<class... Types>
struct last_type_impl
{
  typedef typename std::tuple_element<sizeof...(Types) - 1, std::tuple<Types...>>::type type;
};

template<>
struct last_type_impl<>
{
  typedef void type;
};

template<class... Types>
using last_type = typename last_type_impl<Types...>::type;

template<class Result, class... Args>
struct enable_if_nested_call
  : enable_if_execution_policy<last_type<Args...>, Result>
{};

template<class Result, class... Args>
struct disable_if_nested_call
  : disable_if_execution_policy<
      decay_t<last_type<Args...>>,
      Result
    >
{};

// declare nested_execution_policy for basic_execution_policy's use below
template<class ExecutionPolicy1, class ExecutionPolicy2>
class nested_execution_policy;

// XXX we should assert that ExecutionCategory is stronger than the category of ExecutionAgent
// XXX another way to order these parameters would be
// ExecutionCategory, BulkExecutor, ExecutionAgent = __default_execution_agent<ExecutionAgent>, DerivedExecutionPolicy
template<class ExecutionAgent,
         class BulkExecutor,
         class ExecutionCategory = typename execution_agent_traits<ExecutionAgent>::execution_category,
         class DerivedExecutionPolicy = void>
class basic_execution_policy
{
  public:
    using execution_agent_type = ExecutionAgent;
    using executor_type        = BulkExecutor;
    using execution_category   = ExecutionCategory;

  private:
    using derived_type         = typename std::conditional<
      std::is_same<DerivedExecutionPolicy,void>::value,
      basic_execution_policy,
      DerivedExecutionPolicy
    >::type;

    using agent_traits         = execution_agent_traits<execution_agent_type>;

  public:
    using param_type           = typename agent_traits::param_type;

    basic_execution_policy() = default;

    basic_execution_policy(const param_type& param, const executor_type& executor = executor_type{})
      : param_(param),
        executor_(executor)
    {}

    const param_type& param() const
    {
      return param_;
    }

    executor_type& executor() const
    {
      return executor_;
    }

    template<class OtherExecutor>
    rebind_executor_t<derived_type,OtherExecutor> on(const OtherExecutor& executor) const
    {
      return rebind_executor_t<derived_type,OtherExecutor>(param(), executor);
    }

    // this is the flat form of operator()
    template<class Arg1, class... Args>
    typename detail::disable_if_nested_call<derived_type, Arg1, Args...>::type
      operator()(Arg1&& arg1, Args&&... args) const
    {
      return derived_type{param_type{std::forward<Arg1>(arg1), std::forward<Args>(args)...}, executor()};
    }

    // this is the nested form of operator()
    template<class Arg1, class... Args>
    typename detail::enable_if_nested_call<
      detail::nested_execution_policy<
        derived_type,
        decay_t<last_type<Arg1,Args...>>
      >,
      Arg1, Args...
    >::type
      operator()(Arg1&& arg1, Args&&... args) const
    {
      // wrap the args in a tuple so we can manipulate them easier
      auto arg_tuple = detail::forward_as_tuple(std::forward<Arg1>(arg1), std::forward<Args>(args)...);

      // get the arguments to the outer execution policy
      auto outer_args = detail::tuple_drop_last(arg_tuple);

      // create the outer execution policy
      auto outer = detail::tuple_apply(*this, outer_args);

      // get the inner execution policy
      auto inner = __tu::tuple_last(arg_tuple);

      // return the nesting of the two policies
      return detail::nested_execution_policy<derived_type,decltype(inner)>(outer, inner);
    }

    template<class Arg1, class... Args>
    derived_type operator()(std::initializer_list<Arg1> arg1, std::initializer_list<Args>... args) const
    {
      return derived_type{param_type{std::move(arg1), std::move(args)...}, executor()};
    }

  protected:
    param_type param_;

    // executor_ needs to be mutable, because:
    // * the global execution policy objects are constexpr
    // * executor.bulk_add() is a non-const member function
    mutable executor_type executor_;
};

// ExecutionCategory1 corresponds to the category of the executor
// XXX ExecutionCategory2 corresponds to the category of the policy
// XXX this overload should only be selected if ExecutionCategory1 is stronger than ExecutionCategory2
template<class ExecutionCategory1, class ExecutionAgent, class BulkExecutor, class ExecutionCategory2, class DerivedExecutionPolicy, class Function>
void bulk_invoke_impl(ExecutionCategory1,
                      const basic_execution_policy<ExecutionAgent,BulkExecutor,ExecutionCategory2,DerivedExecutionPolicy>& exec,
                      Function f)
{
  using traits = execution_agent_traits<ExecutionAgent>;

  auto param = exec.param();
  auto agent_shape = traits::domain(param).shape();
  auto shared_init = traits::make_shared_initializer(param);

  using executor_index_type = typename executor_traits<BulkExecutor>::index_type;
  using shared_param_type = typename executor_traits<BulkExecutor>::template shared_param_type<decltype(shared_init)>;

  // convert the shape of the agent into the type of the executor's shape
  using executor_shape_type = typename executor_traits<BulkExecutor>::shape_type;
  executor_shape_type executor_shape = detail::shape_cast<executor_shape_type>(agent_shape);

  return executor_traits<BulkExecutor>::bulk_invoke(exec.executor(), [=](executor_index_type executor_idx, shared_param_type shared_params)
  {
    // convert the index of the executor into the type of the agent's index
    using agent_index_type = typename traits::index_type;
    auto agent_idx = detail::index_cast<agent_index_type>(executor_idx, executor_shape, agent_shape);

    traits::execute(f, agent_idx, param, shared_params);
  },
  executor_shape,
  shared_init);
}

// ExecutionCategory1 corresponds to the category of the executor
// XXX ExecutionCategory2 corresponds to the category of the policy
// XXX this overload should only be selected if ExecutionCategory1 is stronger than ExecutionCategory2
template<class ExecutionCategory1, class ExecutionAgent, class BulkExecutor, class ExecutionCategory2, class DerivedExecutionPolicy, class Function>
std::future<void> bulk_async_impl(ExecutionCategory1,
                                  const basic_execution_policy<ExecutionAgent,BulkExecutor,ExecutionCategory2,DerivedExecutionPolicy>& exec,
                                  Function f)
{
  using traits = execution_agent_traits<ExecutionAgent>;

  auto param = exec.param();
  auto agent_shape = traits::domain(param).shape();
  auto shared_init = traits::make_shared_initializer(param);

  using executor_index_type = typename executor_traits<BulkExecutor>::index_type;
  using shared_param_type = typename executor_traits<BulkExecutor>::template shared_param_type<decltype(shared_init)>;

  // convert the shape of the agent into the type of the executor's shape
  using executor_shape_type = typename executor_traits<BulkExecutor>::shape_type;
  executor_shape_type executor_shape = detail::shape_cast<executor_shape_type>(agent_shape);

  return executor_traits<BulkExecutor>::bulk_async(exec.executor(), [=](executor_index_type executor_idx, shared_param_type shared_params)
  {
    // convert the index of the executor into the type of the agent's index
    using agent_index_type = typename traits::index_type;
    auto agent_idx = detail::index_cast<agent_index_type>(executor_idx, executor_shape, agent_shape);

    traits::execute(f, agent_idx, param, shared_params);
  },
  executor_shape,
  shared_init);
}

template<class ExecutionPolicy1, class ExecutionPolicy2>
class nested_execution_policy
  : public basic_execution_policy<
      execution_group<
        typename ExecutionPolicy1::execution_agent_type,
        typename ExecutionPolicy2::execution_agent_type
      >,
      nested_executor<
        typename ExecutionPolicy1::executor_type,
        typename ExecutionPolicy2::executor_type
      >,
      nested_execution_tag<
        typename ExecutionPolicy1::execution_category,
        typename ExecutionPolicy2::execution_category
      >,
      nested_execution_policy<ExecutionPolicy1,ExecutionPolicy2>
    >
{
  private:
    using super_t = basic_execution_policy<
      execution_group<
        typename ExecutionPolicy1::execution_agent_type,
        typename ExecutionPolicy2::execution_agent_type
      >,
      nested_executor<
        typename ExecutionPolicy1::executor_type,
        typename ExecutionPolicy2::executor_type
      >,
      nested_execution_tag<
        typename ExecutionPolicy1::execution_category,
        typename ExecutionPolicy2::execution_category
      >,
      nested_execution_policy<ExecutionPolicy1,ExecutionPolicy2>
    >;

  public:
    using outer_execution_policy_type = ExecutionPolicy1;
    using inner_execution_policy_type = ExecutionPolicy2;
    using typename super_t::execution_agent_type;
    using typename super_t::executor_type;

    nested_execution_policy(const outer_execution_policy_type& outer_exec,
                            const inner_execution_policy_type& inner_exec)
      : super_t(typename execution_agent_type::param_type(outer_exec.param(), inner_exec.param()),
                executor_type(outer_exec.executor(), inner_exec.executor()))
    {}
};

} // end detail

template<class ExecutionAgent, class BulkExecutor, class ExecutionCategory, class DerivedExecutionPolicy>
struct is_execution_policy<detail::basic_execution_policy<ExecutionAgent,BulkExecutor,ExecutionCategory,DerivedExecutionPolicy>> : std::true_type {};

template<class T1, class T2>
struct is_execution_policy<detail::nested_execution_policy<T1,T2>>
  : std::integral_constant<
      bool,
      is_execution_policy<T1>::value && is_execution_policy<T2>::value
    >
{};

template<class ExecutionPolicy, class Executor>
struct rebind_executor
{
  using type = detail::basic_execution_policy<
    typename ExecutionPolicy::execution_agent_type,
    Executor
  >;
};

class sequential_execution_policy : public detail::basic_execution_policy<sequential_agent, sequential_executor, sequential_execution_tag, sequential_execution_policy>
{
  private:
    using super_t = detail::basic_execution_policy<sequential_agent, sequential_executor, sequential_execution_tag, sequential_execution_policy>;

  public:
    using super_t::basic_execution_policy;
};

template<> struct is_execution_policy<sequential_execution_policy> : std::true_type {};

const sequential_execution_policy seq{};

class concurrent_execution_policy : public detail::basic_execution_policy<concurrent_agent, concurrent_executor, concurrent_execution_tag, concurrent_execution_policy>
{
  private:
    using super_t = detail::basic_execution_policy<concurrent_agent, concurrent_executor, concurrent_execution_tag, concurrent_execution_policy>;

  public:
    using super_t::basic_execution_policy;
};

template<> struct is_execution_policy<concurrent_execution_policy> : std::true_type {};

const concurrent_execution_policy con{};

class parallel_execution_policy : public detail::basic_execution_policy<parallel_agent, parallel_executor, parallel_execution_tag, parallel_execution_policy>
{
  private:
    using super_t = detail::basic_execution_policy<parallel_agent, parallel_executor, parallel_execution_tag, parallel_execution_policy>;

  public:
    using super_t::basic_execution_policy;
};

template<> struct is_execution_policy<parallel_execution_policy> : std::true_type {};

const parallel_execution_policy par{};

class vector_execution_policy : public detail::basic_execution_policy<vector_agent, vector_executor, vector_execution_tag, vector_execution_policy>
{
  private:
    using super_t = detail::basic_execution_policy<vector_agent, vector_executor, vector_execution_tag, vector_execution_policy>;

  public:
    using super_t::basic_execution_policy;
};

template<> struct is_execution_policy<vector_execution_policy> : std::true_type {};

const vector_execution_policy vec{};

template<class ExecutionPolicy, class Function, class... Args>
typename detail::enable_if_execution_policy<detail::decay_t<ExecutionPolicy>>::type
bulk_invoke(ExecutionPolicy&& exec, Function&& f, Args&&... args)
{
  // XXX the execution_category we dispatch on should be the category of the policy's executor
  using execution_category = typename detail::decay_t<ExecutionPolicy>::execution_category;
  return detail::bulk_invoke_impl(execution_category(), exec, std::bind(f, std::placeholders::_1, args...));
}

template<class ExecutionPolicy, class Function, class... Args>
typename detail::enable_if_execution_policy<detail::decay_t<ExecutionPolicy>,std::future<void>>::type
bulk_async(ExecutionPolicy&& exec, Function&& f, Args&&... args)
{
  // XXX the execution_category we dispatch on should be the category of the policy's executor
  using execution_category = typename detail::decay_t<ExecutionPolicy>::execution_category;
  return detail::bulk_async_impl(execution_category(), exec, std::bind(f, std::placeholders::_1, args...));
}

} // end agency

<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "testpropertyeditor.h"
#include "../testview.h"

#include <memory>
#include <cstdio>

#include <metainfo.h>
#include <model.h>
#include <modelnode.h>
#include <variantproperty.h>
#include <bytearraymodifier.h>
#include <invalididexception.h>
#include <invalidmodelnodeexception.h>
#include <propertyeditor.h>
#include <QDebug>
#include <QDir>
#include <QSpinBox>
#include <QLineEdit>
#include <QStackedWidget>
#include <QmlView>
#include <QVariant>

using namespace QmlDesigner;

#include "../common/statichelpers.cpp"

static void inspectPropertyEditor(ModelNode node, QWidget* propWidget)
{
    if (!propWidget)
        return;

    QStackedWidget * stackedWidget = qobject_cast<QStackedWidget *> (propWidget);
    QVERIFY(stackedWidget);
    QmlView *view = qobject_cast<QmlView*>(stackedWidget->currentWidget());
    QVERIFY(view);

    QLineEdit * idLineEdit = view->findChild<QLineEdit* >("IdLineEdit");

    if (!idLineEdit)
        return ;

    QCOMPARE(idLineEdit->text(), node.id());

    if (node.hasProperty("width")) {
         QSpinBox * widthSpinBox = view->findChild<QSpinBox* >("WidthSpinBox");
         QVERIFY(widthSpinBox);
         QCOMPARE(widthSpinBox->value(), node.variantProperty("width").value().toInt());
    }

    if (node.hasProperty("height")) {
        QSpinBox * heightSpinBox = view->findChild<QSpinBox* >("HeightSpinBox");
        QVERIFY(heightSpinBox);
        QCOMPARE(heightSpinBox->value(), node.variantProperty("height").value().toInt());// this can be dangerous
    }

    if (node.hasProperty("x")) {
        QSpinBox * xSpinBox = view->findChild<QSpinBox* >("XSpinBox");
        QVERIFY(xSpinBox);
        QCOMPARE(xSpinBox->value(), node.variantProperty("x").value().toInt()); // this can be dangerous
    }

    if (node.hasProperty("y")) {
        QSpinBox * ySpinBox = view->findChild<QSpinBox* >("YSpinBox");
        QVERIFY(ySpinBox);
        QCOMPARE(ySpinBox->value(), node.variantProperty("y").value().toInt());
    }
}
static void selectThrough(ModelNode node, QWidget* propWidget = 0)
{
    QVERIFY(node.isValid());
    int numberOfProperties = node.propertyNames().count();
    QList<AbstractProperty> properties = node.properties();
    node.view()->clearSelectedModelNodes();
    node.view()->selectModelNode(node);
    QString name = node.id();
    qApp->processEvents();
    QTest::qSleep(100);
    qApp->processEvents();
    QTest::qSleep(100);
    qApp->processEvents();
    inspectPropertyEditor(node, propWidget);
    //selecting should not effect any properties at all!
    QCOMPARE(node.propertyNames().count(), numberOfProperties);
    foreach (const AbstractProperty &property, properties)
        if (property.isVariantProperty()) {
            QCOMPARE(property.toVariantProperty().value(), node.variantProperty(property.name()).value());
        }
    QList<ModelNode> childNodes = node.allDirectSubModelNodes();
    foreach (const ModelNode &childNode, childNodes)
        selectThrough(childNode, propWidget);
}

static QWidget * setupPropertyEditor(QWidget *widget, Model *model)
{
    PropertyEditor *properties = new PropertyEditor(widget);

    QString qmlDir = QDir::cleanPath(qApp->applicationDirPath() + QString("/../shared/propertyeditor/"));
    qDebug() << qmlDir;
    properties->setQmlDir(qmlDir);
    model->attachView(properties);
    QWidget *pane = properties->createPropertiesPage();
    pane->setParent(widget);
    widget->show();
    widget->resize(300, 800);
    qApp->processEvents();
    pane->resize(300, 800);
    pane->move(0,0);
    qApp->processEvents();
    QTest::qSleep(100);

    return pane;
}

static void loadFileAndTest(const QString &fileName)
{
    QFile file(fileName);
    QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));

    QList<QmlError> errors;
    //std::auto_ptr<ByteArrayModifier> modifier1(ByteArrayModifier::create(QString(file.readAll())));
    //std::auto_ptr<Model> model1(Model::create(modifier1.get(), QUrl::fromLocalFile(file.fileName()), &errors));

    QScopedPointer<Model> model1(Model::create("Item"));
    QVERIFY(model1.data());

    QScopedPointer<TestView> view(new TestView);
    QVERIFY(view.data());
    model1->attachView(view.data());

    QVERIFY(model1.data());

    std::auto_ptr<QWidget> widget(new QWidget());
    QWidget *propWidget = setupPropertyEditor(widget.get(), model1.data());

    selectThrough(view->rootModelNode(), propWidget);
}

TestPropertyEditor::TestPropertyEditor()
    : QObject()
{
}

void TestPropertyEditor::initTestCase()
{
    qInstallMsgHandler(testMessageOutput);
    MetaInfo::setPluginPaths(pluginPaths());
    Exception::setShouldAssert(false);
}

void TestPropertyEditor::createCoreModel()
{
    try {
        std::auto_ptr<QWidget> widget(new QWidget());

        QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
        QVERIFY(model.data());

        QScopedPointer<TestView> view(new TestView);
        QVERIFY(view.data());
        model->attachView(view.data());

        QVERIFY(model.data());
        setupPropertyEditor(widget.get(), model.data());

        QVERIFY(view->rootModelNode().isValid());
        int numberOfProperties = view->rootModelNode().propertyNames().count();
        selectThrough(view->rootModelNode());
        QCOMPARE(view->rootModelNode().propertyNames().count(), numberOfProperties);
    } catch (Exception &exception) {
        QFAIL("Exception thrown");
    }
}

void TestPropertyEditor::loadEmptyCoreModel()
{
   /* QList<QmlError> errors;
    QFile file(":/fx/empty.qml");
    QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));

    std::auto_ptr<QWidget> widget(new QWidget());
    std::auto_ptr<ByteArrayModifier> modifier1(ByteArrayModifier::create(QString(file.readAll())));
    std::auto_ptr<Model> model1(Model::create(modifier1.get(), QUrl(), &errors));
    foreach (const QmlError &error, errors)
        QFAIL(error.toString().toLatin1());
    QVERIFY(model1.get());
    setupPropertyEditor(widget.get(), model1.get());

    selectThrough(model1->rootNode());

    std::auto_ptr<ByteArrayModifier> modifier2(ByteArrayModifier::create("import Qt 4.6\n Item{}"));
    std::auto_ptr<Model> model2(Model::create(modifier2.get(), QUrl(), &errors));
    foreach (const QmlError &error, errors)
        QFAIL(error.toString().toLatin1());
    QVERIFY(model2.get());

    QVERIFY(compareTree(model1->rootNode(), model2->rootNode()));*/
}

void TestPropertyEditor::createSubNode()
{
    std::auto_ptr<QWidget> widget(new QWidget());

    QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
    QVERIFY(model.data());

    QScopedPointer<TestView> view(new TestView);
    QVERIFY(view.data());
    model->attachView(view.data());

    setupPropertyEditor(widget.get(), model.data());
    QVERIFY(view->rootModelNode().isValid());
    selectThrough(view->rootModelNode());
    ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
    QVERIFY(childNode.isValid());
    QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
    QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
    QCOMPARE(childNode.type(), QString("Qt/Rectangle"));

    selectThrough(childNode);

    QVERIFY(childNode.id().isEmpty());

    childNode.setId("Blah");
    QCOMPARE(childNode.id(), QString("Blah"));

    QCOMPARE(childNode.id(), QString("Blah"));
}

void TestPropertyEditor::createRect()
{
    try {

        std::auto_ptr<QWidget> widget(new QWidget());

        QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
        QVERIFY(model.data());

        QScopedPointer<TestView> view(new TestView);
        QVERIFY(view.data());
        model->attachView(view.data());

        setupPropertyEditor(widget.get(), model.data());

        QVERIFY(view->rootModelNode().isValid());

        //selectThrough(view->rootModelNode());

        ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
        QVERIFY(childNode.isValid());
        QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
        QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
        QCOMPARE(childNode.type(), QString("Qt/Rectangle"));

        QVERIFY(childNode.id().isEmpty());

        childNode.setId("Rect01");
        QCOMPARE(childNode.id(), QString("Rect01"));

        childNode.variantProperty("x") = 100;
        QCOMPARE(QmlObjectNode(childNode).instanceValue("x").toInt(), 100);
        childNode.variantProperty("y") = 100;
        QCOMPARE(QmlObjectNode(childNode).instanceValue("y").toInt(), 100);
        childNode.variantProperty("width") = 100;
        QCOMPARE(QmlObjectNode(childNode).instanceValue("width").toInt(), 100);
        childNode.variantProperty("height") = 100;
        QCOMPARE(QmlObjectNode(childNode).instanceValue("height").toInt(), 100);

        selectThrough(childNode);

        QCOMPARE(childNode.propertyNames().count(), 4);
        QCOMPARE(childNode.variantProperty("scale").value(), QVariant());

    } catch (Exception &exception) {
        QFAIL("Exception thrown");
    }
}

void TestPropertyEditor::removeNode()
{
    std::auto_ptr<QWidget> widget(new QWidget());

    QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
    QVERIFY(model.data());

    QScopedPointer<TestView> view(new TestView);
    QVERIFY(view.data());
    model->attachView(view.data());

    setupPropertyEditor(widget.get(), model.data());

    QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0);

    selectThrough(view->rootModelNode());

    ModelNode childNode = view->rootModelNode().addChildNode("Qt/Rectangle", 4, 6, "data");
    QVERIFY(childNode.isValid());
    QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 1);
    QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
    QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());

    selectThrough(childNode);

    ModelNode subChildNode = childNode.addChildNode("Qt/Rectangle", 4, 6, "data");
    QVERIFY(subChildNode.isValid());
    QCOMPARE(childNode.allDirectSubModelNodes().count(), 1);
    QVERIFY(childNode.allDirectSubModelNodes().contains(subChildNode));
    QVERIFY(subChildNode.parentProperty().parentModelNode() == childNode);

    selectThrough(subChildNode);

    childNode.destroy();

    QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0);
    QVERIFY(!view->rootModelNode().allDirectSubModelNodes().contains(childNode));
    QVERIFY(!childNode.isValid());
    QVERIFY(!subChildNode.isValid());
}

void TestPropertyEditor::loadWelcomeScreen()
{
    loadFileAndTest(QCoreApplication::applicationDirPath() + "/../shared/welcomescreen.qml");
}

void TestPropertyEditor::loadHelloWorld()
{
    loadFileAndTest(":/fx/helloworld.qml");
}

void TestPropertyEditor::cleanupTestCase()
{
    MetaInfo::clearGlobal();
}

QTEST_MAIN(TestPropertyEditor);
<commit_msg>Fix compilation of QmlDesigner PropertyEditor autotests<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "testpropertyeditor.h"
#include "../testview.h"

#include <memory>
#include <cstdio>

#include <metainfo.h>
#include <model.h>
#include <modelnode.h>
#include <variantproperty.h>
#include <bytearraymodifier.h>
#include <invalididexception.h>
#include <invalidmodelnodeexception.h>
#include <propertyeditor.h>
#include <QDebug>
#include <QDir>
#include <QSpinBox>
#include <QLineEdit>
#include <QStackedWidget>
#include <QmlView>
#include <QVariant>

using namespace QmlDesigner;

#include "../common/statichelpers.cpp"

static void inspectPropertyEditor(ModelNode node, QWidget* propWidget)
{
    if (!propWidget)
        return;

    QStackedWidget * stackedWidget = qobject_cast<QStackedWidget *> (propWidget);
    QVERIFY(stackedWidget);
    QmlView *view = qobject_cast<QmlView*>(stackedWidget->currentWidget());
    QVERIFY(view);

    QLineEdit * idLineEdit = view->findChild<QLineEdit* >("IdLineEdit");

    if (!idLineEdit)
        return ;

    QCOMPARE(idLineEdit->text(), node.id());

    if (node.hasProperty("width")) {
         QSpinBox * widthSpinBox = view->findChild<QSpinBox* >("WidthSpinBox");
         QVERIFY(widthSpinBox);
         QCOMPARE(widthSpinBox->value(), node.variantProperty("width").value().toInt());
    }

    if (node.hasProperty("height")) {
        QSpinBox * heightSpinBox = view->findChild<QSpinBox* >("HeightSpinBox");
        QVERIFY(heightSpinBox);
        QCOMPARE(heightSpinBox->value(), node.variantProperty("height").value().toInt());// this can be dangerous
    }

    if (node.hasProperty("x")) {
        QSpinBox * xSpinBox = view->findChild<QSpinBox* >("XSpinBox");
        QVERIFY(xSpinBox);
        QCOMPARE(xSpinBox->value(), node.variantProperty("x").value().toInt()); // this can be dangerous
    }

    if (node.hasProperty("y")) {
        QSpinBox * ySpinBox = view->findChild<QSpinBox* >("YSpinBox");
        QVERIFY(ySpinBox);
        QCOMPARE(ySpinBox->value(), node.variantProperty("y").value().toInt());
    }
}
static void selectThrough(ModelNode node, QWidget* propWidget = 0)
{
    QVERIFY(node.isValid());
    int numberOfProperties = node.propertyNames().count();
    QList<AbstractProperty> properties = node.properties();
    node.view()->clearSelectedModelNodes();
    node.view()->selectModelNode(node);
    QString name = node.id();
    qApp->processEvents();
    QTest::qSleep(100);
    qApp->processEvents();
    QTest::qSleep(100);
    qApp->processEvents();
    inspectPropertyEditor(node, propWidget);
    //selecting should not effect any properties at all!
    QCOMPARE(node.propertyNames().count(), numberOfProperties);
    foreach (const AbstractProperty &property, properties)
        if (property.isVariantProperty()) {
            QCOMPARE(property.toVariantProperty().value(), node.variantProperty(property.name()).value());
        }
    QList<ModelNode> childNodes = node.allDirectSubModelNodes();
    foreach (const ModelNode &childNode, childNodes)
        selectThrough(childNode, propWidget);
}

static QWidget * setupPropertyEditor(QWidget *widget, Model *model)
{
    PropertyEditor *properties = new PropertyEditor(widget);

    QString qmlDir = QDir::cleanPath(qApp->applicationDirPath() + QString("/../shared/propertyeditor/"));
    qDebug() << qmlDir;
    properties->setQmlDir(qmlDir);
    model->attachView(properties);
    QWidget *pane = properties->createPropertiesPage();
    pane->setParent(widget);
    widget->show();
    widget->resize(300, 800);
    qApp->processEvents();
    pane->resize(300, 800);
    pane->move(0,0);
    qApp->processEvents();
    QTest::qSleep(100);

    return pane;
}

static void loadFileAndTest(const QString &fileName)
{
    QFile file(fileName);
    QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));

    QList<QmlError> errors;
    //std::auto_ptr<ByteArrayModifier> modifier1(ByteArrayModifier::create(QString(file.readAll())));
    //std::auto_ptr<Model> model1(Model::create(modifier1.get(), QUrl::fromLocalFile(file.fileName()), &errors));

    QScopedPointer<Model> model1(Model::create("Item"));
    QVERIFY(model1.data());

    QScopedPointer<TestView> view(new TestView);
    QVERIFY(view.data());
    model1->attachView(view.data());

    QVERIFY(model1.data());

    std::auto_ptr<QWidget> widget(new QWidget());
    QWidget *propWidget = setupPropertyEditor(widget.get(), model1.data());

    selectThrough(view->rootModelNode(), propWidget);
}

TestPropertyEditor::TestPropertyEditor()
    : QObject()
{
}

void TestPropertyEditor::initTestCase()
{
    qInstallMsgHandler(testMessageOutput);
    Exception::setShouldAssert(false);
}

void TestPropertyEditor::createCoreModel()
{
    try {
        std::auto_ptr<QWidget> widget(new QWidget());

        QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
        QVERIFY(model.data());

        QScopedPointer<TestView> view(new TestView);
        QVERIFY(view.data());
        model->attachView(view.data());

        QVERIFY(model.data());
        setupPropertyEditor(widget.get(), model.data());

        QVERIFY(view->rootModelNode().isValid());
        int numberOfProperties = view->rootModelNode().propertyNames().count();
        selectThrough(view->rootModelNode());
        QCOMPARE(view->rootModelNode().propertyNames().count(), numberOfProperties);
    } catch (Exception &exception) {
        QFAIL("Exception thrown");
    }
}

void TestPropertyEditor::loadEmptyCoreModel()
{
   /* QList<QmlError> errors;
    QFile file(":/fx/empty.qml");
    QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));

    std::auto_ptr<QWidget> widget(new QWidget());
    std::auto_ptr<ByteArrayModifier> modifier1(ByteArrayModifier::create(QString(file.readAll())));
    std::auto_ptr<Model> model1(Model::create(modifier1.get(), QUrl(), &errors));
    foreach (const QmlError &error, errors)
        QFAIL(error.toString().toLatin1());
    QVERIFY(model1.get());
    setupPropertyEditor(widget.get(), model1.get());

    selectThrough(model1->rootNode());

    std::auto_ptr<ByteArrayModifier> modifier2(ByteArrayModifier::create("import Qt 4.6\n Item{}"));
    std::auto_ptr<Model> model2(Model::create(modifier2.get(), QUrl(), &errors));
    foreach (const QmlError &error, errors)
        QFAIL(error.toString().toLatin1());
    QVERIFY(model2.get());

    QVERIFY(compareTree(model1->rootNode(), model2->rootNode()));*/
}

void TestPropertyEditor::createSubNode()
{
    std::auto_ptr<QWidget> widget(new QWidget());

    QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
    QVERIFY(model.data());

    QScopedPointer<TestView> view(new TestView);
    QVERIFY(view.data());
    model->attachView(view.data());

    setupPropertyEditor(widget.get(), model.data());
    QVERIFY(view->rootModelNode().isValid());
    selectThrough(view->rootModelNode());

    ModelNode childNode = view->createModelNode("Qt/Rectangle", 4, 6);
    view->rootModelNode().nodeListProperty("data").reparentHere(childNode);

    QVERIFY(childNode.isValid());
    QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
    QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
    QCOMPARE(childNode.type(), QString("Qt/Rectangle"));

    selectThrough(childNode);

    QVERIFY(childNode.id().isEmpty());

    childNode.setId("Blah");
    QCOMPARE(childNode.id(), QString("Blah"));

    QCOMPARE(childNode.id(), QString("Blah"));
}

void TestPropertyEditor::createRect()
{
    try {

        std::auto_ptr<QWidget> widget(new QWidget());

        QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
        QVERIFY(model.data());

        QScopedPointer<TestView> view(new TestView);
        QVERIFY(view.data());
        model->attachView(view.data());

        setupPropertyEditor(widget.get(), model.data());

        QVERIFY(view->rootModelNode().isValid());

        //selectThrough(view->rootModelNode());

        ModelNode childNode = view->createModelNode("Qt/Rectangle", 4, 6);
        view->rootModelNode().nodeListProperty("data").reparentHere(childNode);

        QVERIFY(childNode.isValid());
        QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
        QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());
        QCOMPARE(childNode.type(), QString("Qt/Rectangle"));

        QVERIFY(childNode.id().isEmpty());

        childNode.setId("Rect01");
        QCOMPARE(childNode.id(), QString("Rect01"));

        childNode.variantProperty("x") = 100;
        QCOMPARE(QmlObjectNode(childNode).instanceValue("x").toInt(), 100);
        childNode.variantProperty("y") = 100;
        QCOMPARE(QmlObjectNode(childNode).instanceValue("y").toInt(), 100);
        childNode.variantProperty("width") = 100;
        QCOMPARE(QmlObjectNode(childNode).instanceValue("width").toInt(), 100);
        childNode.variantProperty("height") = 100;
        QCOMPARE(QmlObjectNode(childNode).instanceValue("height").toInt(), 100);

        selectThrough(childNode);

        QCOMPARE(childNode.propertyNames().count(), 4);
        QCOMPARE(childNode.variantProperty("scale").value(), QVariant());

    } catch (Exception &exception) {
        QFAIL("Exception thrown");
    }
}

void TestPropertyEditor::removeNode()
{
    std::auto_ptr<QWidget> widget(new QWidget());

    QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}"));
    QVERIFY(model.data());

    QScopedPointer<TestView> view(new TestView);
    QVERIFY(view.data());
    model->attachView(view.data());

    setupPropertyEditor(widget.get(), model.data());

    QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0);

    selectThrough(view->rootModelNode());

    ModelNode childNode = view->createModelNode("Qt/Rectangle", 4, 6);
    view->rootModelNode().nodeListProperty("data").reparentHere(childNode);
    QVERIFY(childNode.isValid());
    QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 1);
    QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode));
    QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode());

    selectThrough(childNode);

    ModelNode subChildNode = view->createModelNode("Qt/Rectangle", 4, 6);
    childNode.nodeListProperty("data").reparentHere(subChildNode);
    QVERIFY(subChildNode.isValid());
    QCOMPARE(childNode.allDirectSubModelNodes().count(), 1);
    QVERIFY(childNode.allDirectSubModelNodes().contains(subChildNode));
    QVERIFY(subChildNode.parentProperty().parentModelNode() == childNode);

    selectThrough(subChildNode);

    childNode.destroy();

    QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0);
    QVERIFY(!view->rootModelNode().allDirectSubModelNodes().contains(childNode));
    QVERIFY(!childNode.isValid());
    QVERIFY(!subChildNode.isValid());
}

void TestPropertyEditor::loadWelcomeScreen()
{
    loadFileAndTest(QCoreApplication::applicationDirPath() + "/../shared/welcomescreen.qml");
}

void TestPropertyEditor::loadHelloWorld()
{
    loadFileAndTest(":/fx/helloworld.qml");
}

void TestPropertyEditor::cleanupTestCase()
{
    MetaInfo::clearGlobal();
}

QTEST_MAIN(TestPropertyEditor);
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the demonstration applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtGui/QApplication>
#include <QtDeclarative/QDeclarativeView>
#include <QtDeclarative/QDeclarativeEngine>

#if !defined(QT_NO_OPENGL)
#include <QtOpenGL/QGLWidget>
#endif

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    const QString mainQmlApp = QLatin1String("qrc:/declarative-camera.qml");
    QDeclarativeView view;
#if !defined(QT_NO_OPENGL)
    view.setViewport(new QGLWidget);
#endif
    view.setSource(QUrl(mainQmlApp));
    view.setResizeMode(QDeclarativeView::SizeRootObjectToView);
    // Qt.quit() called in embedded .qml by default only emits
    // quit() signal, so do this (optionally use Qt.exit()).
    QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit()));
#if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
    view.showFullScreen();
#else
    view.setGeometry(QRect(100, 100, 800, 480));
    view.show();
#endif
    return application.exec();
}

<commit_msg>QML camera example: don't use GL viewport on maemo<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the demonstration applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtGui/QApplication>
#include <QtDeclarative/QDeclarativeView>
#include <QtDeclarative/QDeclarativeEngine>

#if !defined(QT_NO_OPENGL)
#include <QtOpenGL/QGLWidget>
#endif

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    const QString mainQmlApp = QLatin1String("qrc:/declarative-camera.qml");
    QDeclarativeView view;
#if !defined(QT_NO_OPENGL) && !defined(Q_WS_MAEMO_5) && !defined(Q_WS_MAEMO_6)
    view.setViewport(new QGLWidget);
#endif
    view.setSource(QUrl(mainQmlApp));
    view.setResizeMode(QDeclarativeView::SizeRootObjectToView);
    // Qt.quit() called in embedded .qml by default only emits
    // quit() signal, so do this (optionally use Qt.exit()).
    QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit()));
#if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
    view.showFullScreen();
#else
    view.setGeometry(QRect(100, 100, 800, 480));
    view.show();
#endif
    return application.exec();
}

<|endoftext|>


<commit_before>/**
 * elf_parser.cpp - Implementation of ELF binary perser
 * @author Alexander Titov <alexander.igorevich.titov@gmail.com>
 * Copyright 2012 uArchSim iLab project
 */

// Genereic C
#include <libelf.h>
#include <cstdio>
#include <unistd.h>
#include <cstring>
#include <fcntl.h>
#include <gelf.h>
#include <cstdlib>
#include <cerrno>
#include <cassert>

// Generic C++
#include <iostream>
#include <string>
#include <sstream>

// uArchSim modules
#include <elf_parser.h>

using namespace std;

ElfSection::ElfSection( const char* elf_file_name, const char* section_name)
{
    // open the binary file, we have to use C-style open,
    // because it is required by elf_begin function
    int file_descr = open( elf_file_name, O_RDONLY);
    if ( file_descr < 0)
    {
        cerr << "ERROR: Could not open file " << elf_file_name << ": "
             << strerror( errno) << endl;
        exit( EXIT_FAILURE);
    }

    // set ELF library operating version
    if ( elf_version( EV_CURRENT) == EV_NONE)
    {
        cerr << "ERROR: Could not set ELF library operating version:"
             <<  elf_errmsg( elf_errno()) << endl;
        exit( EXIT_FAILURE);
    }

    // open the file in ELF format
    Elf* elf = elf_begin( file_descr, ELF_C_READ, NULL);
    if ( !elf)
    {
        cerr << "ERROR: Could not open file " << elf_file_name
             << " as ELF file: "
             <<  elf_errmsg( elf_errno()) << endl;
        exit( EXIT_FAILURE);
    }

    // set the name of the sections
    this->name = new char[ strlen( section_name) + 1];
    strcpy( this->name, section_name);

    // set the size, start address and offset
    uint64 offset = NO_VAL64;
    this->extractSectionParams( elf, section_name,
        offset, this->size, this->start_addr);

    // allocate place for the content
    this->content = new uint8[ this->size + 1];

    lseek( file_descr, offset, SEEK_SET);
    FILE *file = fdopen( file_descr, "r");
    if ( !file )
    {
        cerr << "ERROR: Could not open file " << elf_file_name << ": "
             << strerror(errno) << endl;
        exit( EXIT_FAILURE);
    }

    // fill the content by the section data
    fread( this->content, sizeof( uint8), this->size, file);

    // close all used files
    fclose( file);
    elf_end( elf);
    close( file_descr);
}

ElfSection::~ElfSection()
{
    delete [] this->name;
    delete [] this->content;
}

void ElfSection::extractSectionParams( Elf* elf, const char* section_name,
                                       uint64& offset, uint64& size,
                                       uint64& start_addr)
{
    size_t shstrndx;
    elf_getshdrstrndx( elf, &shstrndx);

    // look through all sections and try to find the desired one
    Elf_Scn *section = NULL;
    while ( ( section = elf_nextscn( elf, section)) != NULL)
    {
        GElf_Shdr shdr;
        gelf_getshdr( section, &shdr);
        char* name = elf_strptr( elf, shstrndx, shdr.sh_name);

        // if a section with the decired name
        // then set its start address, size and offset
        // and return back from the function.
        if ( !strcmp( name, section_name))
        {
            offset = ( uint64)shdr.sh_offset;
            size = ( uint64)shdr.sh_size;
            start_addr = ( uint64)shdr.sh_addr;

            return;
        }
    }

    cerr << "ERROR: Could not find section " << section_name
         << " in ELF file!" << endl;
    exit( EXIT_FAILURE);
}

uint64 ElfSection::read( uint64 addr, short num_of_bytes) const
{
    // insert here your implementation
    assert(0);
    return NO_VAL64;
}

bool ElfSection::isInside( uint64 addr, short num_of_bytes) const
{
    // insert here your implementation
    assert(0);
    return false;
}

uint64 ElfSection::startAddr() const
{
    // insert here your implementation
    assert(0);
    return NO_VAL64;
}

string ElfSection::dump( string indent) const
{
    ostringstream oss;

    oss << indent << "Dump ELF section \"" << this->name << "\"" << endl
        << indent << "  size = " << this->size << " Bytes" << endl
        << indent << "  start_addr = 0x" << hex << this->start_addr << dec << endl
        << indent << "  Content:" << endl;

    string str = this->strByBytes();

    // split the contents into words of 4 bytes
    for ( size_t offset = 0; offset < this->size; offset += sizeof( uint32))
    {
        oss << indent << "    0x" << hex << ( this->start_addr + offset)
            << indent << ":    " << str.substr( 2 * offset, // 2 hex digits is need per byte
                                                sizeof( uint64))
	        << endl;
    }

    return oss.str();
}

string ElfSection::strByBytes() const
{
    // temp stream is used to convert numbers into the output string
    ostringstream oss;
    oss << hex;

    // convert each byte into 2 hex digits
    for( size_t i = 0; i < this->size; ++i)
    {
        oss.width( 2); // because we need two hex symbols to print a byte (e.g. "ff")
        oss.fill( '0'); // thus, number 8 will be printed as "08"

        // print a value of
        oss << (uint16) *( this->content + i); // need converting to uint16
                                               // to be not preinted as an alphabet symbol
    }

    return oss.str();
}

string ElfSection::strByWords() const
{
    // temp stream is used to convert numbers into the output string
    ostringstream oss;
    oss << hex;

    // convert each words of 4 bytes into 8 hex digits
    for( size_t i = 0; i < this->size/sizeof( uint32); ++i)
    {
        oss.width( 8); // because we need 8 hex symbols to print a word (e.g. "ffffffff")
        oss.fill( '0'); // thus, number a44f will be printed as "0000a44f"

        oss << *( ( uint32*)this->content + i);
    }

    return oss.str();
}

<commit_msg>[branch] elf_parser has been completed<commit_after>/**
 * elf_parser.cpp - Implementation of ELF binary perser
 * @author Alexander Titov <alexander.igorevich.titov@gmail.com>
 * Copyright 2012 uArchSim iLab project
 */

// Genereic C
#include <libelf.h>
#include <cstdio>
#include <unistd.h>
#include <cstring>
#include <fcntl.h>
#include <gelf.h>
#include <cstdlib>
#include <cerrno>
#include <cassert>

// Generic C++
#include <iostream>
#include <string>
#include <sstream>

// uArchSim modules
#include <elf_parser.h>

using namespace std;

ElfSection::ElfSection( const char* elf_file_name, const char* section_name)
{
    // open the binary file, we have to use C-style open,
    // because it is required by elf_begin function
    int file_descr = open( elf_file_name, O_RDONLY);
    if ( file_descr < 0)
    {
        cerr << "ERROR: Could not open file " << elf_file_name << ": "
             << strerror( errno) << endl;
        exit( EXIT_FAILURE);
    }

    // set ELF library operating version
    if ( elf_version( EV_CURRENT) == EV_NONE)
    {
        cerr << "ERROR: Could not set ELF library operating version:"
             <<  elf_errmsg( elf_errno()) << endl;
        exit( EXIT_FAILURE);
    }

    // open the file in ELF format
    Elf* elf = elf_begin( file_descr, ELF_C_READ, NULL);
    if ( !elf)
    {
        cerr << "ERROR: Could not open file " << elf_file_name
             << " as ELF file: "
             <<  elf_errmsg( elf_errno()) << endl;
        exit( EXIT_FAILURE);
    }

    // set the name of the sections
    this->name = new char[ strlen( section_name) + 1];
    strcpy( this->name, section_name);

    // set the size, start address and offset
    uint64 offset = NO_VAL64;
    this->extractSectionParams( elf, section_name,
        offset, this->size, this->start_addr);

    // allocate place for the content
    this->content = new uint8[ this->size + 1];

    lseek( file_descr, offset, SEEK_SET);
    FILE *file = fdopen( file_descr, "r");
    if ( !file )
    {
        cerr << "ERROR: Could not open file " << elf_file_name << ": "
             << strerror(errno) << endl;
        exit( EXIT_FAILURE);
    }

    // fill the content by the section data
    fread( this->content, sizeof( uint8), this->size, file);

    // close all used files
    fclose( file);
    elf_end( elf);
    close( file_descr);
}

ElfSection::~ElfSection()
{
    delete [] this->name;
    delete [] this->content;
}

void ElfSection::extractSectionParams( Elf* elf, const char* section_name,
                                       uint64& offset, uint64& size,
                                       uint64& start_addr)
{
    size_t shstrndx;
    elf_getshdrstrndx( elf, &shstrndx);

    // look through all sections and try to find the desired one
    Elf_Scn *section = NULL;
    while ( ( section = elf_nextscn( elf, section)) != NULL)
    {
        GElf_Shdr shdr;
        gelf_getshdr( section, &shdr);
        char* name = elf_strptr( elf, shstrndx, shdr.sh_name);

        // if a section with the decired name
        // then set its start address, size and offset
        // and return back from the function.
        if ( !strcmp( name, section_name))
        {
            offset = ( uint64)shdr.sh_offset;
            size = ( uint64)shdr.sh_size;
            start_addr = ( uint64)shdr.sh_addr;

            return;
        }
    }

    cerr << "ERROR: Could not find section " << section_name
         << " in ELF file!" << endl;
    exit( EXIT_FAILURE);
}

uint64 ElfSection::read( uint64 addr, short num_of_bytes) const
{
    assert( num_of_bytes < sizeof( uint64));
    assert( isInside( addr, num_of_bytes));
    uint64 data = 0;
    for ( short i = num_of_bytes; i > 0; --i)
    {
        short the_num_of_byte = addr - this->start_addr + i - 1;
        data <<= 8;
        data |= this->content[the_num_of_byte];
    }
    cout << "\n\nit my debug print!\ndata=" << hex << data << endl;
    return data;
}

bool ElfSection::isInside( uint64 addr, short num_of_bytes) const
{
    cout << "\nstart_addr = " << start_addr << "\naddr = "
         << addr << endl;
    assert( num_of_bytes);
    if (this->start_addr > addr)
    {
        return false;
    }
    if ( this->start_addr + this->size >= addr + num_of_bytes)
    {
        return true;
    }
    return false;
}

uint64 ElfSection::startAddr() const
{
    assert(start_addr);
    return start_addr;
}

string ElfSection::dump( string indent) const
{
    ostringstream oss;

    oss << indent << "Dump ELF section \"" << this->name << "\"" << endl
        << indent << "  size = " << this->size << " Bytes" << endl
        << indent << "  start_addr = 0x" << hex << this->start_addr << dec << endl
        << indent << "  Content:" << endl;

    string str = this->strByBytes();

    // split the contents into words of 4 bytes
    for ( size_t offset = 0; offset < this->size; offset += sizeof( uint32))
    {
        oss << indent << "    0x" << hex << ( this->start_addr + offset)
            << indent << ":    " << str.substr( 2 * offset, // 2 hex digits is need per byte
                                                sizeof( uint64))
	        << endl;
    }

    return oss.str();
}

string ElfSection::strByBytes() const
{
    // temp stream is used to convert numbers into the output string
    ostringstream oss;
    oss << hex;

    // convert each byte into 2 hex digits
    for( size_t i = 0; i < this->size; ++i)
    {
        oss.width( 2); // because we need two hex symbols to print a byte (e.g. "ff")
        oss.fill( '0'); // thus, number 8 will be printed as "08"

        // print a value of
        oss << (uint16) *( this->content + i); // need converting to uint16
                                               // to be not preinted as an alphabet symbol
    }

    return oss.str();
}

string ElfSection::strByWords() const
{
    // temp stream is used to convert numbers into the output string
    ostringstream oss;
    oss << hex;

    // convert each words of 4 bytes into 8 hex digits
    for( size_t i = 0; i < this->size/sizeof( uint32); ++i)
    {
        oss.width( 8); // because we need 8 hex symbols to print a word (e.g. "ffffffff")
        oss.fill( '0'); // thus, number a44f will be printed as "0000a44f"

        oss << *( ( uint32*)this->content + i);
    }

    return oss.str();
}

<|endoftext|>