<commit_before>#include "stdsneezy.h"
#include "obj_vehicle.h"

TVehicle *findVehicle(TBeing *ch)
{
  TObj *o;
  TVehicle *v;

  for(o=object_list;o;o=o->next){
    if((v=dynamic_cast<TVehicle *>(o)) && v->getTarget() == ch->in_room)
      return v;
  }

  return NULL;
}

// drive speed <fast|medium|slow|stop>
// drive <north|south|etc>
// drive exit
// drive look
void TBeing::doDrive(string arg)
{
  string buf;
  TVehicle *vehicle;

  if(!(vehicle=findVehicle(this))){
    sendTo("You aren't inside of a vehicle.\n\r");
    return;
  }

  arg=lower(arg);
  arg=one_argument(arg, buf);

  // drive <direction>
  // this is a little wacky, let me explain:
  // we loop through all of the directions and check for a match
  // if we have a match, THEN we check for keys and return
  // we do this so that directions can be parsed first BUT if no
  // direction is entered we can fall through to non-keys commands
  for(dirTypeT dir=DIR_NORTH;dir<MAX_DIR;dir++){
    if(is_abbrev(buf, dirs[dir])){
      if(!has_key(this, vehicle->getPortalKey())){
	sendTo("You need the keys to drive this vehicle!\n\r");
	return;
      }

      vehicle->driveDir(this, dir);
      return;
    }
  }

  // any passenger can use these commands
  if(is_abbrev(buf, "exit")){
    vehicle->driveExit(this);
    return;
  }

  if(is_abbrev(buf, "look")){
    vehicle->driveLook(this);
    return;
  }

  if(is_abbrev(buf, "status")){
    vehicle->driveStatus(this);
    return;
  }

  if(is_abbrev(buf, "close")){
    vehicle->closeMe(this);
    return;
  }

  if(is_abbrev(buf, "lock")){
    vehicle->lockMe(this);
    return;
  }

  // authenticated commands
  if(is_abbrev(buf, "fast") || is_abbrev(buf, "medium") ||
     is_abbrev(buf, "slow") || is_abbrev(buf, "stop")){
    if(!has_key(this, vehicle->getPortalKey())){
      sendTo("You need the keys to drive this vehicle!\n\r");
      return;
    }

    vehicle->driveSpeed(this, buf);
    return;
  }

  sendTo("Syntax: drive <direction>\n\r");
  sendTo("        drive <fast|medium|slow|stop>\n\r");
  sendTo("        drive <exit|look|close|lock>\n\r");
}

<commit_msg>added abbrevs for diag directions added safety check for !vehicle->roomp<commit_after>#include "stdsneezy.h"
#include "obj_vehicle.h"

TVehicle *findVehicle(TBeing *ch)
{
  TObj *o;
  TVehicle *v;

  for(o=object_list;o;o=o->next){
    if((v=dynamic_cast<TVehicle *>(o)) && v->getTarget() == ch->in_room)
      return v;
  }

  return NULL;
}

// drive speed <fast|medium|slow|stop>
// drive <north|south|etc>
// drive exit
// drive look
void TBeing::doDrive(string arg)
{
  string buf;
  TVehicle *vehicle;

  if(!(vehicle=findVehicle(this))){
    sendTo("You aren't inside of a vehicle.\n\r");
    return;
  }

  if(!vehicle->roomp){
    sendTo("This vehicle is located in the void!  You can't drive it now!\n\r");
    return;
  }

  arg=lower(arg);
  arg=one_argument(arg, buf);

  // drive <direction>
  // this is a little wacky, let me explain:
  // we loop through all of the directions and check for a match
  // if we have a match, THEN we check for keys and return
  // we do this so that directions can be parsed first BUT if no
  // direction is entered we can fall through to non-keys commands
  for(dirTypeT dir=DIR_NORTH;dir<MAX_DIR;dir++){
    if(is_abbrev(buf, dirs[dir]) ||
       (dirs[dir]=="northwest" && buf=="nw") ||
       (dirs[dir]=="southwest" && buf=="sw") ||
       (dirs[dir]=="northeast" && buf=="ne") ||
       (dirs[dir]=="southeast" && buf=="se")){
      if(!has_key(this, vehicle->getPortalKey())){
	sendTo("You need the keys to drive this vehicle!\n\r");
	return;
      }

      vehicle->driveDir(this, dir);
      return;
    }
  }

  // any passenger can use these commands
  if(is_abbrev(buf, "exit")){
    vehicle->driveExit(this);
    return;
  }

  if(is_abbrev(buf, "look")){
    vehicle->driveLook(this);
    return;
  }

  if(is_abbrev(buf, "status")){
    vehicle->driveStatus(this);
    return;
  }

  if(is_abbrev(buf, "close")){
    vehicle->closeMe(this);
    return;
  }

  if(is_abbrev(buf, "lock")){
    vehicle->lockMe(this);
    return;
  }

  // authenticated commands
  if(is_abbrev(buf, "fast") || is_abbrev(buf, "medium") ||
     is_abbrev(buf, "slow") || is_abbrev(buf, "stop")){
    if(!has_key(this, vehicle->getPortalKey())){
      sendTo("You need the keys to drive this vehicle!\n\r");
      return;
    }

    vehicle->driveSpeed(this, buf);
    return;
  }

  sendTo("Syntax: drive <direction>\n\r");
  sendTo("        drive <fast|medium|slow|stop>\n\r");
  sendTo("        drive <exit|look|close|lock>\n\r");
}

<|endoftext|>


<commit_before>#include "DebugDrawingManager.hpp"

#include "../Entity/World.hpp"
#include "../Entity/Entity.hpp"
#include "../Component/Lens.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include "../MainWindow.hpp"
#include "Managers.hpp"
#include "ResourceManager.hpp"
#include "../Shader/Shader.hpp"
#include "../Shader/ShaderProgram.hpp"
#include "DebugDrawing.vert.hpp"
#include "DebugDrawing.frag.hpp"

#define BUFFER_OFFSET(i) ((char *)nullptr + (i))

DebugDrawingManager::DebugDrawingManager() {
    vertexShader = Managers().resourceManager->CreateShader(DEBUGDRAWING_VERT, DEBUGDRAWING_VERT_LENGTH, GL_VERTEX_SHADER);
    fragmentShader = Managers().resourceManager->CreateShader(DEBUGDRAWING_FRAG, DEBUGDRAWING_FRAG_LENGTH, GL_FRAGMENT_SHADER);
    shaderProgram = Managers().resourceManager->CreateShaderProgram({ vertexShader, fragmentShader });

    // Create point vertex array.
    glBindVertexArray(0);

    glGenBuffers(1, &pointVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pointVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, 1 * sizeof(glm::vec3), &glm::vec3(0.f, 0.f, 0.f)[0], GL_STATIC_DRAW);

    glGenVertexArrays(1, &pointVertexArray);
    glBindVertexArray(pointVertexArray);

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

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0));

    glBindVertexArray(0);

    // Create line vertex array.
    glm::vec3 line[2];
    line[0] = glm::vec3(0.f, 0.f, 0.f);
    line[1] = glm::vec3(1.f, 1.f, 1.f);

    glGenBuffers(1, &lineVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, lineVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, 2 * sizeof(glm::vec3), line, GL_STATIC_DRAW);

    glGenVertexArrays(1, &lineVertexArray);
    glBindVertexArray(lineVertexArray);

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

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0));

    glBindVertexArray(0);
}

DebugDrawingManager::~DebugDrawingManager() {
    glDeleteBuffers(1, &pointVertexBuffer);
    glDeleteVertexArrays(1, &pointVertexArray);

    glDeleteBuffers(1, &lineVertexBuffer);
    glDeleteVertexArrays(1, &lineVertexArray);

    Managers().resourceManager->FreeShader(vertexShader);
    Managers().resourceManager->FreeShader(fragmentShader);
    Managers().resourceManager->FreeShaderProgram(shaderProgram);
}

void DebugDrawingManager::AddPoint(const glm::vec3& position, const glm::vec3& color, float size, float duration, bool depthTesting) {
    Point point;
    point.position = position;
    point.color = color;
    point.size = size;
    point.duration = duration;
    point.depthTesting = depthTesting;
    points.push_back(point);
}

void DebugDrawingManager::AddLine(const glm::vec3& startPosition, const glm::vec3& endPosition, const glm::vec3& color, float width, float duration, bool depthTesting) {
    Line line;
    line.startPosition = startPosition;
    line.endPosition = endPosition;
    line.color = color;
    line.width = width;
    line.duration = duration;
    line.depthTesting = depthTesting;
    lines.push_back(line);
}

void DebugDrawingManager::Update(float deltaTime) {
    // Points.
    for (std::size_t i=0; i<points.size(); ++i) {
        if (points[i].duration < 0.f) {
            points[i] = points[points.size() - 1];
            points.pop_back();
            --i;
        } else {
            points[i].duration -= deltaTime;
        }
    }

    // Lines.
    for (std::size_t i=0; i < lines.size(); ++i) {
        if (lines[i].duration < 0.f) {
            lines[i] = lines[lines.size() - 1];
            lines.pop_back();
            --i;
        } else {
            lines[i].duration -= deltaTime;
        }
    }
}

void DebugDrawingManager::Render(World& world) {
    // Find camera entity.
    Entity* camera = nullptr;
    std::vector<Component::Lens*> lenses = world.GetComponents<Component::Lens>();
    for (Component::Lens* lens : lenses) {
        camera = lens->entity;
    };

    if (camera != nullptr) {
        glm::mat4 viewMat(camera->GetCameraOrientation() * glm::translate(glm::mat4(), -camera->position));
        glm::mat4 projectionMat(camera->GetComponent<Component::Lens>()->GetProjection(MainWindow::GetInstance()->GetSize()));
        glm::mat4 viewProjectionMat(projectionMat * viewMat);

        shaderProgram->Use();
        glUniformMatrix4fv(shaderProgram->GetUniformLocation("viewProjection"), 1, GL_FALSE, &viewProjectionMat[0][0]);

        // Points.
        glBindVertexArray(pointVertexArray);
        for (const Point& point : points) {
            glm::mat4 model(glm::translate(glm::mat4(), point.position));

            glUniformMatrix4fv(shaderProgram->GetUniformLocation("model"), 1, GL_FALSE, &model[0][0]);
            point.depthTesting ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
            glUniform3fv(shaderProgram->GetUniformLocation("color"), 1, &point.color[0]);
            glUniform1f(shaderProgram->GetUniformLocation("size"), point.size);
            glDrawArrays(GL_POINTS, 0, 1);
        }

        glEnable(GL_DEPTH_TEST);
        glBindVertexArray(0);
    }
}
<commit_msg>Draw debug lines<commit_after>#include "DebugDrawingManager.hpp"

#include "../Entity/World.hpp"
#include "../Entity/Entity.hpp"
#include "../Component/Lens.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include "../MainWindow.hpp"
#include "Managers.hpp"
#include "ResourceManager.hpp"
#include "../Shader/Shader.hpp"
#include "../Shader/ShaderProgram.hpp"
#include "DebugDrawing.vert.hpp"
#include "DebugDrawing.frag.hpp"

#define BUFFER_OFFSET(i) ((char *)nullptr + (i))

DebugDrawingManager::DebugDrawingManager() {
    vertexShader = Managers().resourceManager->CreateShader(DEBUGDRAWING_VERT, DEBUGDRAWING_VERT_LENGTH, GL_VERTEX_SHADER);
    fragmentShader = Managers().resourceManager->CreateShader(DEBUGDRAWING_FRAG, DEBUGDRAWING_FRAG_LENGTH, GL_FRAGMENT_SHADER);
    shaderProgram = Managers().resourceManager->CreateShaderProgram({ vertexShader, fragmentShader });

    // Create point vertex array.
    glBindVertexArray(0);

    glGenBuffers(1, &pointVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pointVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, 1 * sizeof(glm::vec3), &glm::vec3(0.f, 0.f, 0.f)[0], GL_STATIC_DRAW);

    glGenVertexArrays(1, &pointVertexArray);
    glBindVertexArray(pointVertexArray);

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

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0));

    glBindVertexArray(0);

    // Create line vertex array.
    glm::vec3 line[2];
    line[0] = glm::vec3(0.f, 0.f, 0.f);
    line[1] = glm::vec3(1.f, 1.f, 1.f);

    glGenBuffers(1, &lineVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, lineVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, 2 * sizeof(glm::vec3), line, GL_STATIC_DRAW);

    glGenVertexArrays(1, &lineVertexArray);
    glBindVertexArray(lineVertexArray);

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

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0));

    glBindVertexArray(0);
}

DebugDrawingManager::~DebugDrawingManager() {
    glDeleteBuffers(1, &pointVertexBuffer);
    glDeleteVertexArrays(1, &pointVertexArray);

    glDeleteBuffers(1, &lineVertexBuffer);
    glDeleteVertexArrays(1, &lineVertexArray);

    Managers().resourceManager->FreeShader(vertexShader);
    Managers().resourceManager->FreeShader(fragmentShader);
    Managers().resourceManager->FreeShaderProgram(shaderProgram);
}

void DebugDrawingManager::AddPoint(const glm::vec3& position, const glm::vec3& color, float size, float duration, bool depthTesting) {
    Point point;
    point.position = position;
    point.color = color;
    point.size = size;
    point.duration = duration;
    point.depthTesting = depthTesting;
    points.push_back(point);
}

void DebugDrawingManager::AddLine(const glm::vec3& startPosition, const glm::vec3& endPosition, const glm::vec3& color, float width, float duration, bool depthTesting) {
    Line line;
    line.startPosition = startPosition;
    line.endPosition = endPosition;
    line.color = color;
    line.width = width;
    line.duration = duration;
    line.depthTesting = depthTesting;
    lines.push_back(line);
}

void DebugDrawingManager::Update(float deltaTime) {
    // Points.
    for (std::size_t i=0; i<points.size(); ++i) {
        if (points[i].duration < 0.f) {
            points[i] = points[points.size() - 1];
            points.pop_back();
            --i;
        } else {
            points[i].duration -= deltaTime;
        }
    }

    // Lines.
    for (std::size_t i=0; i < lines.size(); ++i) {
        if (lines[i].duration < 0.f) {
            lines[i] = lines[lines.size() - 1];
            lines.pop_back();
            --i;
        } else {
            lines[i].duration -= deltaTime;
        }
    }
}

void DebugDrawingManager::Render(World& world) {
    // Find camera entity.
    Entity* camera = nullptr;
    std::vector<Component::Lens*> lenses = world.GetComponents<Component::Lens>();
    for (Component::Lens* lens : lenses) {
        camera = lens->entity;
    };

    if (camera != nullptr) {
        glm::mat4 viewMat(camera->GetCameraOrientation() * glm::translate(glm::mat4(), -camera->position));
        glm::mat4 projectionMat(camera->GetComponent<Component::Lens>()->GetProjection(MainWindow::GetInstance()->GetSize()));
        glm::mat4 viewProjectionMat(projectionMat * viewMat);

        shaderProgram->Use();
        glUniformMatrix4fv(shaderProgram->GetUniformLocation("viewProjection"), 1, GL_FALSE, &viewProjectionMat[0][0]);

        // Points.
        glBindVertexArray(pointVertexArray);
        for (const Point& point : points) {
            glm::mat4 model(glm::translate(glm::mat4(), point.position));

            glUniformMatrix4fv(shaderProgram->GetUniformLocation("model"), 1, GL_FALSE, &model[0][0]);
            point.depthTesting ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
            glUniform3fv(shaderProgram->GetUniformLocation("color"), 1, &point.color[0]);
            glUniform1f(shaderProgram->GetUniformLocation("size"), point.size);
            glDrawArrays(GL_POINTS, 0, 1);
        }

        // Lines.
        glBindVertexArray(lineVertexArray);
        for (const Line& line : lines) {
            glm::mat4 model(glm::translate(glm::mat4(), line.startPosition) * glm::scale(glm::mat4(), line.endPosition - line.startPosition));

            glUniformMatrix4fv(shaderProgram->GetUniformLocation("model"), 1, GL_FALSE, &model[0][0]);
            line.depthTesting ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
            glUniform3fv(shaderProgram->GetUniformLocation("color"), 1, &line.color[0]);
            glLineWidth(line.width);
            glDrawArrays(GL_LINES, 0, 2);
        }

        glEnable(GL_DEPTH_TEST);
        glBindVertexArray(0);
    }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module 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 either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** 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.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qfxpainteditem.h"
#include "qfxpainteditem_p.h"

#include <QDebug>
#include <QPen>
#include <QFile>
#include <QEvent>
#include <QApplication>
#include <QGraphicsSceneMouseEvent>

#if defined(QFX_RENDER_OPENGL2)
#include <QtOpenGL/qglframebufferobject.h>
#include <glsave.h>
#endif

QT_BEGIN_NAMESPACE

/*!
    \class QFxPaintedItem
    \brief The QFxPaintedItem class is an abstract base class for QFxView items that want cached painting.
    \ingroup group_coreitems

    This is a convenience class for implementing items that paint their contents
    using a QPainter.  The contents of the item are are cached behind the scenes.
    The dirtyCache() function should be called if the contents change to
    ensure the cache is refreshed the next time painting occurs.

    To subclass QFxPaintedItem, you must reimplement drawContents() to draw
    the contents of the item.
*/

/*!
    \fn void QFxPaintedItem::drawContents(QPainter *painter, const QRect &rect)

    This function is called when the cache needs to be refreshed. When
    sub-classing QFxPaintedItem this function should be implemented so as to
    paint the contents of the item using the given \a painter for the
    area of the contents specified by \a rect.
*/

/*!
    \property QFxPaintedItem::contentsSize
    \brief The size of the contents

    The contents size is the size of the item in regards to how it is painted
    using the drawContents() function.  This is distinct from the size of the
    item in regards to height() and width().
*/

/*!
    \property QFxPaintedItem::smooth
    \brief Setting for whether smooth scaling is enabled.
*/

/*!
    Marks areas of the cache that intersect with the given \a rect as dirty and
    in need of being refreshed.

    \sa clearCache()
*/
void QFxPaintedItem::dirtyCache(const QRect& rect)
{
    Q_D(QFxPaintedItem);
    for (int i=0; i < d->imagecache.count(); ) {
        if (d->imagecache[i]->area.intersects(rect)) {
            d->imagecache.removeAt(i);
        } else {
            ++i;
        }
    }
}

/*!
    Marks the entirety of the contents cache as dirty.

    \sa dirtyCache()
*/
void QFxPaintedItem::clearCache()
{
    Q_D(QFxPaintedItem);
    qDeleteAll(d->imagecache);
    d->imagecache.clear();
}

/*!
    Returns if smooth scaling of the cache contents is enabled.

    \sa setSmooth()
*/
bool QFxPaintedItem::isSmooth() const
{
    Q_D(const QFxPaintedItem);
    return d->smooth;
}

/*!
    Returns the size of the contents.

    \sa setContentsSize()
*/
QSize QFxPaintedItem::contentsSize() const
{
    Q_D(const QFxPaintedItem);
    return d->contentsSize;
}

/*!
    If \a smooth is true sets the image item to enable smooth scaling of
    the cache contents.

    \sa isSmooth()
*/
void QFxPaintedItem::setSmooth(bool smooth)
{
    Q_D(QFxPaintedItem);
    if (d->smooth == smooth) return;
    d->smooth = smooth;
    update();
}

/*!
    Sets the size of the contents to the given \a size.

    \sa contentsSize()
*/
void QFxPaintedItem::setContentsSize(const QSize &size)
{
    Q_D(QFxPaintedItem);
    if (d->contentsSize == size) return;
    d->contentsSize = size;
    clearCache();
    update();
}

/*!
    Constructs a new QFxPaintedItem with the given \a parent.
*/
QFxPaintedItem::QFxPaintedItem(QFxItem *parent)
  : QFxItem(*(new QFxPaintedItemPrivate), parent)
{
    init();
}

/*!
    \internal
    Constructs a new QFxPaintedItem with the given \a parent and
    initialized private data member \a dd.
*/
QFxPaintedItem::QFxPaintedItem(QFxPaintedItemPrivate &dd, QFxItem *parent)
  : QFxItem(dd, parent)
{
    init();
}

/*!
    Destroys the image item.
*/
QFxPaintedItem::~QFxPaintedItem()
{
}

/*!
    \internal
*/
void QFxPaintedItem::init()
{
    connect(this,SIGNAL(widthChanged()),this,SLOT(clearCache()));
    connect(this,SIGNAL(heightChanged()),this,SLOT(clearCache()));
    connect(this,SIGNAL(visibleChanged()),this,SLOT(clearCache()));
}

#if defined(QFX_RENDER_QPAINTER)
/*!
    \reimp
*/
void QFxPaintedItem::paintContents(QPainter &p)
#elif defined(QFX_RENDER_OPENGL)
/*!
    \reimp
*/
void QFxPaintedItem::paintGLContents(GLPainter &p)
#else
#error "What render?"
#endif
{
    Q_D(QFxPaintedItem);
    const QRect content(QPoint(0,0),d->contentsSize);
    if (content.width() <= 0 || content.height() <= 0)
        return;

#if defined(QFX_RENDER_QPAINTER)
    bool oldAntiAliasing = p.testRenderHint(QPainter::Antialiasing);
    bool oldSmoothPixmap = p.testRenderHint(QPainter::SmoothPixmapTransform);
    if (d->smooth) {
        p.setRenderHints(QPainter::Antialiasing, true);
        p.setRenderHints(QPainter::SmoothPixmapTransform, true);
    }
    QRectF clipf = p.clipRegion().boundingRect();
    if (clipf.isEmpty())
        clipf = mapToScene(content); // ### Inefficient: Maps toScene and then fromScene
    else
        clipf = mapToScene(clipf);

#elif defined(QFX_RENDER_OPENGL2)
    p.useTextureShader();
    const QRectF clipf = p.sceneClipRect;

#elif defined(QFX_RENDER_OPENGL1)
    p.useTextureShader();
    const QRectF clipf = p.sceneClipRect;
#endif

    const QRect clip = mapFromScene(clipf).toRect();

    QRegion topaint(clip);
    topaint &= content;
    QRegion uncached(content);

#if defined(QFX_RENDER_OPENGL2)
    glEnableVertexAttribArray(SingleTextureShader::Vertices);
    glEnableVertexAttribArray(SingleTextureShader::TextureCoords);
#elif defined(QFX_RENDER_OPENGL1)
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
#endif

    int cachesize=0;
    for (int i=0; i<d->imagecache.count(); ++i) {
        QRect area = d->imagecache[i]->area;
        if (topaint.contains(area)) {
            QRectF target(area.x(), area.y(), area.width(), area.height());
            p.drawPixmap(target.toRect(), d->imagecache[i]->image);
            topaint -= area;
            d->imagecache[i]->age=0;
        } else {
            d->imagecache[i]->age++;
        }
        cachesize += area.width()*area.height();
        uncached -= area;
    }

    if (!topaint.isEmpty()) {
        // Find a sensible larger area, otherwise will paint lots of tiny images.
        QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128);
        cachesize += biggerrect.width() * biggerrect.height();
        while (d->imagecache.count() && cachesize > d->max_imagecache_size) {
            int oldest=-1;
            int age=-1;
            for (int i=0; i<d->imagecache.count(); ++i) {
                int a = d->imagecache[i]->age;
                if (a > age) {
                    oldest = i;
                    age = a;
                }
            }
            cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
            uncached += d->imagecache[oldest]->area;
            d->imagecache.removeAt(oldest);
        }
        const QRegion bigger = QRegion(biggerrect) & uncached;
        const QVector<QRect> rects = bigger.rects();
        for (int i = 0; i < rects.count(); ++i) {
            const QRect &r = rects.at(i);
            QPixmap img(r.size());
            if (d->fillColor.isValid())
                img.fill(d->fillColor);
            {
                QPainter qp(&img);
                qp.translate(-r.x(),-r.y());
                drawContents(&qp, r);
            }
            QFxPaintedItemPrivate::ImageCacheItem *newitem = new QFxPaintedItemPrivate::ImageCacheItem;
            newitem->area = r;
#if defined(QFX_RENDER_QPAINTER)
            newitem->image = img;
#else
            newitem->image.setImage(img.toImage());
#endif
            d->imagecache.append(newitem);
            QRectF target(r.x(), r.y(), r.width(), r.height());
            p.drawPixmap(target.toRect(), newitem->image);
        }
    }
#if defined(QFX_RENDER_OPENGL2)
    glDisableVertexAttribArray(SingleTextureShader::Vertices);
    glDisableVertexAttribArray(SingleTextureShader::TextureCoords);
#elif defined(QFX_RENDER_OPENGL1)
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
#endif
#if defined(QFX_RENDER_QPAINTER)
    if (d->smooth) {
        p.setRenderHints(QPainter::Antialiasing, oldAntiAliasing);
        p.setRenderHints(QPainter::SmoothPixmapTransform, oldSmoothPixmap);
    }
#endif
}

/*!
  \qmlproperty int PaintedItem::cacheSize

  This property holds the maximum number of pixels of image cache to
  allow. The default is 0.1 megapixels. The cache will not be larger
  than the (unscaled) size of the item.
*/

/*!
  \property QFxPaintedItem::cacheSize

  The maximum number of pixels of image cache to allow. The default
  is 0.1 megapixels. The cache will not be larger than the (unscaled)
  size of the QFxPaintedItem.
*/
int QFxPaintedItem::cacheSize() const
{
    Q_D(const QFxPaintedItem);
    return d->max_imagecache_size;
}

void QFxPaintedItem::setCacheSize(int pixels)
{
    Q_D(QFxPaintedItem);
    if (pixels < d->max_imagecache_size) {
        int cachesize=0;
        for (int i=0; i<d->imagecache.count(); ++i) {
            QRect area = d->imagecache[i]->area;
            cachesize += area.width()*area.height();
        }
        while (d->imagecache.count() && cachesize > pixels) {
            int oldest=-1;
            int age=-1;
            for (int i=0; i<d->imagecache.count(); ++i) {
                int a = d->imagecache[i]->age;
                if (a > age) {
                    oldest = i;
                    age = a;
                }
            }
            cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
            d->imagecache.removeAt(oldest);
        }
    }
    d->max_imagecache_size = pixels;
}

/*!
    \property QFxPaintedItem::fillColor

    The color to be used to fill the item prior to calling drawContents().
    By default, this is Qt::transparent.

    Performance improvements can be achieved if subclasses call this with either an
    invalid color (QColor()), or an appropriate solid color.
*/
void QFxPaintedItem::setFillColor(const QColor& c)
{
    Q_D(QFxPaintedItem);
    if (d->fillColor == c)
        return;
    d->fillColor = c;
    emit fillColorChanged();
    update();
}

QColor QFxPaintedItem::fillColor() const
{
    Q_D(const QFxPaintedItem);
    return d->fillColor;
}

QT_END_NAMESPACE
<commit_msg>Smooth, but never anti-alias the edges of pixmaps that need to stitch.. Bug 256967 still stops it working correctly.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module 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 either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** 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.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qfxpainteditem.h"
#include "qfxpainteditem_p.h"

#include <QDebug>
#include <QPen>
#include <QFile>
#include <QEvent>
#include <QApplication>
#include <QGraphicsSceneMouseEvent>

#if defined(QFX_RENDER_OPENGL2)
#include <QtOpenGL/qglframebufferobject.h>
#include <glsave.h>
#endif

QT_BEGIN_NAMESPACE

/*!
    \class QFxPaintedItem
    \brief The QFxPaintedItem class is an abstract base class for QFxView items that want cached painting.
    \ingroup group_coreitems

    This is a convenience class for implementing items that paint their contents
    using a QPainter.  The contents of the item are are cached behind the scenes.
    The dirtyCache() function should be called if the contents change to
    ensure the cache is refreshed the next time painting occurs.

    To subclass QFxPaintedItem, you must reimplement drawContents() to draw
    the contents of the item.
*/

/*!
    \fn void QFxPaintedItem::drawContents(QPainter *painter, const QRect &rect)

    This function is called when the cache needs to be refreshed. When
    sub-classing QFxPaintedItem this function should be implemented so as to
    paint the contents of the item using the given \a painter for the
    area of the contents specified by \a rect.
*/

/*!
    \property QFxPaintedItem::contentsSize
    \brief The size of the contents

    The contents size is the size of the item in regards to how it is painted
    using the drawContents() function.  This is distinct from the size of the
    item in regards to height() and width().
*/

/*!
    \property QFxPaintedItem::smooth
    \brief Setting for whether smooth scaling is enabled.
*/

/*!
    Marks areas of the cache that intersect with the given \a rect as dirty and
    in need of being refreshed.

    \sa clearCache()
*/
void QFxPaintedItem::dirtyCache(const QRect& rect)
{
    Q_D(QFxPaintedItem);
    for (int i=0; i < d->imagecache.count(); ) {
        if (d->imagecache[i]->area.intersects(rect)) {
            d->imagecache.removeAt(i);
        } else {
            ++i;
        }
    }
}

/*!
    Marks the entirety of the contents cache as dirty.

    \sa dirtyCache()
*/
void QFxPaintedItem::clearCache()
{
    Q_D(QFxPaintedItem);
    qDeleteAll(d->imagecache);
    d->imagecache.clear();
}

/*!
    Returns if smooth scaling of the cache contents is enabled.

    \sa setSmooth()
*/
bool QFxPaintedItem::isSmooth() const
{
    Q_D(const QFxPaintedItem);
    return d->smooth;
}

/*!
    Returns the size of the contents.

    \sa setContentsSize()
*/
QSize QFxPaintedItem::contentsSize() const
{
    Q_D(const QFxPaintedItem);
    return d->contentsSize;
}

/*!
    If \a smooth is true sets the image item to enable smooth scaling of
    the cache contents.

    \sa isSmooth()
*/
void QFxPaintedItem::setSmooth(bool smooth)
{
    Q_D(QFxPaintedItem);
    if (d->smooth == smooth) return;
    d->smooth = smooth;
    update();
}

/*!
    Sets the size of the contents to the given \a size.

    \sa contentsSize()
*/
void QFxPaintedItem::setContentsSize(const QSize &size)
{
    Q_D(QFxPaintedItem);
    if (d->contentsSize == size) return;
    d->contentsSize = size;
    clearCache();
    update();
}

/*!
    Constructs a new QFxPaintedItem with the given \a parent.
*/
QFxPaintedItem::QFxPaintedItem(QFxItem *parent)
  : QFxItem(*(new QFxPaintedItemPrivate), parent)
{
    init();
}

/*!
    \internal
    Constructs a new QFxPaintedItem with the given \a parent and
    initialized private data member \a dd.
*/
QFxPaintedItem::QFxPaintedItem(QFxPaintedItemPrivate &dd, QFxItem *parent)
  : QFxItem(dd, parent)
{
    init();
}

/*!
    Destroys the image item.
*/
QFxPaintedItem::~QFxPaintedItem()
{
}

/*!
    \internal
*/
void QFxPaintedItem::init()
{
    connect(this,SIGNAL(widthChanged()),this,SLOT(clearCache()));
    connect(this,SIGNAL(heightChanged()),this,SLOT(clearCache()));
    connect(this,SIGNAL(visibleChanged()),this,SLOT(clearCache()));
}

#if defined(QFX_RENDER_QPAINTER)
/*!
    \reimp
*/
void QFxPaintedItem::paintContents(QPainter &p)
#elif defined(QFX_RENDER_OPENGL)
/*!
    \reimp
*/
void QFxPaintedItem::paintGLContents(GLPainter &p)
#else
#error "What render?"
#endif
{
    Q_D(QFxPaintedItem);
    const QRect content(QPoint(0,0),d->contentsSize);
    if (content.width() <= 0 || content.height() <= 0)
        return;

#if defined(QFX_RENDER_QPAINTER)
    bool oldAntiAliasing = p.testRenderHint(QPainter::Antialiasing);
    bool oldSmoothPixmap = p.testRenderHint(QPainter::SmoothPixmapTransform);
    if (oldAntiAliasing)
        p.setRenderHints(QPainter::Antialiasing, false); // cannot stitch properly otherwise
    if (d->smooth)
        p.setRenderHints(QPainter::SmoothPixmapTransform, true);
    QRectF clipf = p.clipRegion().boundingRect();
    if (clipf.isEmpty())
        clipf = mapToScene(content); // ### Inefficient: Maps toScene and then fromScene
    else
        clipf = mapToScene(clipf);

#elif defined(QFX_RENDER_OPENGL2)
    p.useTextureShader();
    const QRectF clipf = p.sceneClipRect;

#elif defined(QFX_RENDER_OPENGL1)
    p.useTextureShader();
    const QRectF clipf = p.sceneClipRect;
#endif

    const QRect clip = mapFromScene(clipf).toRect();

    QRegion topaint(clip);
    topaint &= content;
    QRegion uncached(content);

#if defined(QFX_RENDER_OPENGL2)
    glEnableVertexAttribArray(SingleTextureShader::Vertices);
    glEnableVertexAttribArray(SingleTextureShader::TextureCoords);
#elif defined(QFX_RENDER_OPENGL1)
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
#endif

    int cachesize=0;
    for (int i=0; i<d->imagecache.count(); ++i) {
        QRect area = d->imagecache[i]->area;
        if (topaint.contains(area)) {
            QRectF target(area.x(), area.y(), area.width(), area.height());
            p.drawPixmap(target.toRect(), d->imagecache[i]->image);
            topaint -= area;
            d->imagecache[i]->age=0;
        } else {
            d->imagecache[i]->age++;
        }
        cachesize += area.width()*area.height();
        uncached -= area;
    }

    if (!topaint.isEmpty()) {
        // Find a sensible larger area, otherwise will paint lots of tiny images.
        QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128);
        cachesize += biggerrect.width() * biggerrect.height();
        while (d->imagecache.count() && cachesize > d->max_imagecache_size) {
            int oldest=-1;
            int age=-1;
            for (int i=0; i<d->imagecache.count(); ++i) {
                int a = d->imagecache[i]->age;
                if (a > age) {
                    oldest = i;
                    age = a;
                }
            }
            cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
            uncached += d->imagecache[oldest]->area;
            d->imagecache.removeAt(oldest);
        }
        const QRegion bigger = QRegion(biggerrect) & uncached;
        const QVector<QRect> rects = bigger.rects();
        for (int i = 0; i < rects.count(); ++i) {
            const QRect &r = rects.at(i);
            QPixmap img(r.size());
            if (d->fillColor.isValid())
                img.fill(d->fillColor);
            {
                QPainter qp(&img);
                qp.translate(-r.x(),-r.y());
                drawContents(&qp, r);
            }
            QFxPaintedItemPrivate::ImageCacheItem *newitem = new QFxPaintedItemPrivate::ImageCacheItem;
            newitem->area = r;
#if defined(QFX_RENDER_QPAINTER)
            newitem->image = img;
#else
            newitem->image.setImage(img.toImage());
#endif
            d->imagecache.append(newitem);
            QRectF target(r.x(), r.y(), r.width(), r.height());
            p.drawPixmap(target.toRect(), newitem->image);
        }
    }
#if defined(QFX_RENDER_OPENGL2)
    glDisableVertexAttribArray(SingleTextureShader::Vertices);
    glDisableVertexAttribArray(SingleTextureShader::TextureCoords);
#elif defined(QFX_RENDER_OPENGL1)
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
#endif
#if defined(QFX_RENDER_QPAINTER)
    if (oldAntiAliasing)
        p.setRenderHints(QPainter::Antialiasing, oldAntiAliasing);
    if (d->smooth)
        p.setRenderHints(QPainter::SmoothPixmapTransform, oldSmoothPixmap);
#endif
}

/*!
  \qmlproperty int PaintedItem::cacheSize

  This property holds the maximum number of pixels of image cache to
  allow. The default is 0.1 megapixels. The cache will not be larger
  than the (unscaled) size of the item.
*/

/*!
  \property QFxPaintedItem::cacheSize

  The maximum number of pixels of image cache to allow. The default
  is 0.1 megapixels. The cache will not be larger than the (unscaled)
  size of the QFxPaintedItem.
*/
int QFxPaintedItem::cacheSize() const
{
    Q_D(const QFxPaintedItem);
    return d->max_imagecache_size;
}

void QFxPaintedItem::setCacheSize(int pixels)
{
    Q_D(QFxPaintedItem);
    if (pixels < d->max_imagecache_size) {
        int cachesize=0;
        for (int i=0; i<d->imagecache.count(); ++i) {
            QRect area = d->imagecache[i]->area;
            cachesize += area.width()*area.height();
        }
        while (d->imagecache.count() && cachesize > pixels) {
            int oldest=-1;
            int age=-1;
            for (int i=0; i<d->imagecache.count(); ++i) {
                int a = d->imagecache[i]->age;
                if (a > age) {
                    oldest = i;
                    age = a;
                }
            }
            cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
            d->imagecache.removeAt(oldest);
        }
    }
    d->max_imagecache_size = pixels;
}

/*!
    \property QFxPaintedItem::fillColor

    The color to be used to fill the item prior to calling drawContents().
    By default, this is Qt::transparent.

    Performance improvements can be achieved if subclasses call this with either an
    invalid color (QColor()), or an appropriate solid color.
*/
void QFxPaintedItem::setFillColor(const QColor& c)
{
    Q_D(QFxPaintedItem);
    if (d->fillColor == c)
        return;
    d->fillColor = c;
    emit fillColorChanged();
    update();
}

QColor QFxPaintedItem::fillColor() const
{
    Q_D(const QFxPaintedItem);
    return d->fillColor;
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>#include <examples/zurg/common/ProtobufLog.h>
#include <muduo/base/Logging.h>

namespace zurg
{

muduo::Logger::LogLevel toMuduoLogLevel(google::protobuf::LogLevel level)
{
  switch(level)
  {
    case google::protobuf::LOGLEVEL_WARNING:
      return muduo::Logger::WARN;
    case google::protobuf::LOGLEVEL_ERROR:
      return muduo::Logger::ERROR;
    case google::protobuf::LOGLEVEL_FATAL:
      return muduo::Logger::FATAL;
    case google::protobuf::LOGLEVEL_INFO:
      return muduo::Logger::INFO;
    default:
      return muduo::Logger::INFO;
  }
}

void zurgLogHandler(google::protobuf::LogLevel level,
                    const char* filename,
                    int line,
                    const std::string& message)
{
  muduo::Logger::LogLevel logLevel = toMuduoLogLevel(level);
  if (muduo::Logger::logLevel() <= logLevel)
  {
    muduo::Logger(filename, line, logLevel).stream() << "Protobuf - " << message;
  }
}

}
<commit_msg>explicit use Logger::SourceFile<commit_after>#include <examples/zurg/common/ProtobufLog.h>
#include <muduo/base/Logging.h>

namespace zurg
{

muduo::Logger::LogLevel toMuduoLogLevel(google::protobuf::LogLevel level)
{
  switch(level)
  {
    case google::protobuf::LOGLEVEL_WARNING:
      return muduo::Logger::WARN;
    case google::protobuf::LOGLEVEL_ERROR:
      return muduo::Logger::ERROR;
    case google::protobuf::LOGLEVEL_FATAL:
      return muduo::Logger::FATAL;
    case google::protobuf::LOGLEVEL_INFO:
      return muduo::Logger::INFO;
    default:
      return muduo::Logger::INFO;
  }
}

void zurgLogHandler(google::protobuf::LogLevel level,
                    const char* filename,
                    int line,
                    const std::string& message)
{
  muduo::Logger::LogLevel logLevel = toMuduoLogLevel(level);
  if (muduo::Logger::logLevel() <= logLevel)
  {
    muduo::Logger(muduo::Logger::SourceFile(filename),
                  line,
                  logLevel).stream() << "Protobuf - " << message;
  }
}

}
<|endoftext|>


<commit_before>/*
* Core Engine
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/internal/core_engine.h>
#include <botan/parsing.h>
#include <botan/filters.h>
#include <botan/algo_factory.h>
#include <botan/mode_pad.h>
#include <memory>

#if defined(BOTAN_HAS_ECB)
  #include <botan/ecb.h>
#endif

#if defined(BOTAN_HAS_CBC)
  #include <botan/cbc.h>
#endif

#if defined(BOTAN_HAS_CTS)
  #include <botan/cts.h>
#endif

#if defined(BOTAN_HAS_CFB)
  #include <botan/cfb.h>
#endif

#if defined(BOTAN_HAS_OFB)
  #include <botan/ofb.h>
#endif

#if defined(BOTAN_HAS_CTR_BE)
  #include <botan/ctr.h>
#endif

#if defined(BOTAN_HAS_EAX)
  #include <botan/eax.h>
#endif

#if defined(BOTAN_HAS_XTS)
  #include <botan/xts.h>
#endif

namespace Botan {

namespace {

/**
* Get a block cipher padding method by name
*/
BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec,
                                         const std::string& def_if_empty)
   {
#if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
   if(algo_spec == "NoPadding" || (algo_spec == "" && def_if_empty == "NoPadding"))
      return new Null_Padding;

   if(algo_spec == "PKCS7" || (algo_spec == "" && def_if_empty == "PKCS7"))
      return new PKCS7_Padding;

   if(algo_spec == "OneAndZeros")
      return new OneAndZeros_Padding;

   if(algo_spec == "X9.23")
      return new ANSI_X923_Padding;

#endif

   throw Algorithm_Not_Found(algo_spec);
   }

}

Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
                              Cipher_Dir direction,
                              const std::string& mode,
                              const std::string& padding)
   {
#if defined(BOTAN_HAS_OFB)
   if(mode == "OFB")
      return new StreamCipher_Filter(new OFB(block_cipher->clone()));
#endif

#if defined(BOTAN_HAS_CTR_BE)
   if(mode == "CTR-BE")
      return new StreamCipher_Filter(new CTR_BE(block_cipher->clone()));
#endif

#if defined(BOTAN_HAS_ECB)
   if(mode == "ECB" || mode == "")
      {
      if(direction == ENCRYPTION)
         return new ECB_Encryption(block_cipher->clone(),
                                   get_bc_pad(padding, "NoPadding"));
      else
         return new ECB_Decryption(block_cipher->clone(),
                                   get_bc_pad(padding, "NoPadding"));
      }
#endif

   if(mode == "CBC")
      {
      if(padding == "CTS")
         {
#if defined(BOTAN_HAS_CTS)
         if(direction == ENCRYPTION)
            return new CTS_Encryption(block_cipher->clone());
         else
            return new CTS_Decryption(block_cipher->clone());
#else
         return 0;
#endif
         }

#if defined(BOTAN_HAS_CBC)
      if(direction == ENCRYPTION)
         return new CBC_Encryption(block_cipher->clone(),
                                   get_bc_pad(padding, "PKCS7"));
      else
         return new CBC_Decryption(block_cipher->clone(),
                                   get_bc_pad(padding, "PKCS7"));
#else
      return 0;
#endif
      }

#if defined(BOTAN_HAS_XTS)
   if(mode == "XTS")
      {
      if(direction == ENCRYPTION)
         return new XTS_Encryption(block_cipher->clone());
      else
         return new XTS_Decryption(block_cipher->clone());
      }
#endif

   if(mode.find("CFB") != std::string::npos ||
      mode.find("EAX") != std::string::npos)
      {
      size_t bits = 0;

      std::vector<std::string> algo_info = parse_algorithm_name(mode);
      std::string mode_name = algo_info[0];
      if(algo_info.size() == 1)
         bits = 8 * block_cipher->block_size();
      else if(algo_info.size() == 2)
         bits = to_u32bit(algo_info[1]);
      else
         return 0;

#if defined(BOTAN_HAS_CFB)
      if(mode_name == "CFB")
         {
         if(direction == ENCRYPTION)
            return new CFB_Encryption(block_cipher->clone(), bits);
         else
            return new CFB_Decryption(block_cipher->clone(), bits);
         }
#endif

#if defined(BOTAN_HAS_EAX)
      if(mode_name == "EAX")
         {
         if(direction == ENCRYPTION)
            return new EAX_Encryption(block_cipher->clone(), bits);
         else
            return new EAX_Decryption(block_cipher->clone(), bits);
         }
#endif
      }

   return 0;
   }

/*
* Get a cipher object
*/
Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec,
                                         Cipher_Dir direction,
                                         Algorithm_Factory& af)
   {
   std::vector<std::string> algo_parts = split_on(algo_spec, '/');
   if(algo_parts.empty())
      throw Invalid_Algorithm_Name(algo_spec);

   const std::string cipher_name = algo_parts[0];

   // check if it is a stream cipher first (easy case)
   const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name);
   if(stream_cipher)
      return new StreamCipher_Filter(stream_cipher->clone());

   const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name);
   if(!block_cipher)
      return 0;

   if(algo_parts.size() != 2 && algo_parts.size() != 3)
      return 0;

   std::string mode = algo_parts[1];

   std::string padding;
   if(algo_parts.size() == 3)
      padding = algo_parts[2];
   else
      padding = (mode == "CBC") ? "PKCS7" : "NoPadding";

   if(mode == "ECB" && padding == "CTS")
      return 0;
   else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding")
      throw Invalid_Algorithm_Name(algo_spec);

   Keyed_Filter* filt = get_cipher_mode(block_cipher, direction, mode, padding);
   if(filt)
      return filt;

   throw Algorithm_Not_Found(cipher_name + "/" + mode + "/" + padding);
   }

}
<commit_msg>Fix PR 166<commit_after>/*
* Core Engine
* (C) 1999-2007,2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/internal/core_engine.h>
#include <botan/parsing.h>
#include <botan/filters.h>
#include <botan/algo_factory.h>
#include <botan/mode_pad.h>
#include <memory>

#if defined(BOTAN_HAS_ECB)
  #include <botan/ecb.h>
#endif

#if defined(BOTAN_HAS_CBC)
  #include <botan/cbc.h>
#endif

#if defined(BOTAN_HAS_CTS)
  #include <botan/cts.h>
#endif

#if defined(BOTAN_HAS_CFB)
  #include <botan/cfb.h>
#endif

#if defined(BOTAN_HAS_OFB)
  #include <botan/ofb.h>
#endif

#if defined(BOTAN_HAS_CTR_BE)
  #include <botan/ctr.h>
#endif

#if defined(BOTAN_HAS_EAX)
  #include <botan/eax.h>
#endif

#if defined(BOTAN_HAS_XTS)
  #include <botan/xts.h>
#endif

namespace Botan {

namespace {

/**
* Get a block cipher padding method by name
*/
BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec,
                                         const std::string& def_if_empty)
   {
#if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
   if(algo_spec == "NoPadding" || (algo_spec == "" && def_if_empty == "NoPadding"))
      return new Null_Padding;

   if(algo_spec == "PKCS7" || (algo_spec == "" && def_if_empty == "PKCS7"))
      return new PKCS7_Padding;

   if(algo_spec == "OneAndZeros")
      return new OneAndZeros_Padding;

   if(algo_spec == "X9.23")
      return new ANSI_X923_Padding;

#endif

   throw Algorithm_Not_Found(algo_spec);
   }

}

Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
                              Cipher_Dir direction,
                              const std::string& mode,
                              const std::string& padding)
   {
#if defined(BOTAN_HAS_OFB)
   if(mode == "OFB")
      return new StreamCipher_Filter(new OFB(block_cipher->clone()));
#endif

#if defined(BOTAN_HAS_CTR_BE)
   if(mode == "CTR-BE")
      return new StreamCipher_Filter(new CTR_BE(block_cipher->clone()));
#endif

#if defined(BOTAN_HAS_ECB)
   if(mode == "ECB" || mode == "")
      {
      if(direction == ENCRYPTION)
         return new ECB_Encryption(block_cipher->clone(),
                                   get_bc_pad(padding, "NoPadding"));
      else
         return new ECB_Decryption(block_cipher->clone(),
                                   get_bc_pad(padding, "NoPadding"));
      }
#endif

   if(mode == "CBC")
      {
      if(padding == "CTS")
         {
#if defined(BOTAN_HAS_CTS)
         if(direction == ENCRYPTION)
            return new CTS_Encryption(block_cipher->clone());
         else
            return new CTS_Decryption(block_cipher->clone());
#else
         return 0;
#endif
         }

#if defined(BOTAN_HAS_CBC)
      if(direction == ENCRYPTION)
         return new CBC_Encryption(block_cipher->clone(),
                                   get_bc_pad(padding, "PKCS7"));
      else
         return new CBC_Decryption(block_cipher->clone(),
                                   get_bc_pad(padding, "PKCS7"));
#else
      return 0;
#endif
      }

#if defined(BOTAN_HAS_XTS)
   if(mode == "XTS")
      {
      if(direction == ENCRYPTION)
         return new XTS_Encryption(block_cipher->clone());
      else
         return new XTS_Decryption(block_cipher->clone());
      }
#endif

   if(mode.find("CFB") != std::string::npos ||
      mode.find("EAX") != std::string::npos)
      {
      size_t bits = 0;

      std::vector<std::string> algo_info = parse_algorithm_name(mode);
      std::string mode_name = algo_info[0];
      if(algo_info.size() == 1)
         bits = 8 * block_cipher->block_size();
      else if(algo_info.size() == 2)
         bits = to_u32bit(algo_info[1]);
      else
         return 0;

#if defined(BOTAN_HAS_CFB)
      if(mode_name == "CFB")
         {
         if(direction == ENCRYPTION)
            return new CFB_Encryption(block_cipher->clone(), bits);
         else
            return new CFB_Decryption(block_cipher->clone(), bits);
         }
#endif

#if defined(BOTAN_HAS_EAX)
      if(mode_name == "EAX")
         {
         if(direction == ENCRYPTION)
            return new EAX_Encryption(block_cipher->clone(), bits);
         else
            return new EAX_Decryption(block_cipher->clone(), bits);
         }
#endif
      }

   return 0;
   }

/*
* Get a cipher object
*/
Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec,
                                      Cipher_Dir direction,
                                      Algorithm_Factory& af)
   {
   std::vector<std::string> algo_parts = split_on(algo_spec, '/');
   if(algo_parts.empty())
      throw Invalid_Algorithm_Name(algo_spec);

   const std::string cipher_name = algo_parts[0];

   // check if it is a stream cipher first (easy case)
   const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name);
   if(stream_cipher)
      return new StreamCipher_Filter(stream_cipher->clone());

   const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name);
   if(!block_cipher)
      return 0;

   if(algo_parts.size() >= 4)
      return 0; // 4 part mode, not something we know about

   if(algo_parts.size() < 2)
      throw Lookup_Error("Cipher specification '" + algo_spec +
                         "' is missing mode identifier");

   std::string mode = algo_parts[1];

   std::string padding;
   if(algo_parts.size() == 3)
      padding = algo_parts[2];
   else
      padding = (mode == "CBC") ? "PKCS7" : "NoPadding";

   if(mode == "ECB" && padding == "CTS")
      return 0;
   else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding")
      throw Invalid_Algorithm_Name(algo_spec);

   Keyed_Filter* filt = get_cipher_mode(block_cipher, direction, mode, padding);
   if(filt)
      return filt;

   throw Algorithm_Not_Found(cipher_name + "/" + mode + "/" + padding);
   }

}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// hybrid_scan_executor.cpp
//
// Identification: src/executor/hybrid_scan_executor.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>
#include <utility>
#include <vector>
#include <string>
#include <unordered_map>
#include <chrono>
#include <iostream>
#include <ctime>
#include <cassert>
#include <thread>

#include "common/timer.h"
#include "common/types.h"
#include "executor/logical_tile.h"
#include "executor/logical_tile_factory.h"
#include "executor/executor_context.h"
#include "expression/abstract_expression.h"
#include "expression/container_tuple.h"
#include "planner/hybrid_scan_plan.h"
#include "executor/hybrid_scan_executor.h"
#include "storage/data_table.h"
#include "storage/tile_group_header.h"
#include "storage/tile.h"
#include "concurrency/transaction_manager_factory.h"
#include "common/logger.h"

namespace peloton {
namespace executor {

HybridScanExecutor::HybridScanExecutor(const planner::AbstractPlan *node,
                                       ExecutorContext *executor_context)
    : AbstractScanExecutor(node, executor_context),
      indexed_tile_offset_(START_OID) {}

bool HybridScanExecutor::DInit() {
  auto status = AbstractScanExecutor::DInit();

  if (!status) return false;

  const planner::HybridScanPlan &node = GetPlanNode<planner::HybridScanPlan>();

  table_ = node.GetTable();
  index_ = node.GetDataIndex();
  type_ = node.GetHybridType();

  if (type_ == planner::SEQ) {
    current_tile_group_offset_ = START_OID;
    if (table_ != nullptr) {
      table_tile_group_count_ = table_->GetTileGroupCount();
      if (column_ids_.empty()) {
        column_ids_.resize(table_->GetSchema()->GetColumnCount());
        std::iota(column_ids_.begin(), column_ids_.end(), 0);
      }
    }

  } else if (type_ == planner::INDEX) {
    result_itr_ = START_OID;
    index_done_ = false;

    column_ids_ = node.GetColumnIds();
    std::vector<oid_t> key_column_ids_ = node.GetKeyColumnIds();
    std::vector<ExpressionType> expr_types_ = node.GetExprTypes();
    values_ = node.GetValues();
    std::vector<expression::AbstractExpression *> runtime_keys_ = node.GetRunTimeKeys();
    predicate_ = node.GetPredicate();

    if (runtime_keys_.size() != 0) {
      assert(runtime_keys_.size() == values_.size());

      if (!key_ready_) {
        values_.clear();

        for (auto expr : runtime_keys_) {
          auto value = expr->Evaluate(nullptr, nullptr, executor_context_);
          LOG_INFO("Evaluated runtime scan key: %s", value.GetInfo().c_str());
          values_.push_back(value);
        }

        key_ready_ = true;
      }
    }

    if (table_ != nullptr) {
      full_column_ids_.resize(table_->GetSchema()->GetColumnCount());
      std::iota(full_column_ids_.begin(), full_column_ids_.end(), 0);
    }
  } else {  // Hybrid type.
    table_tile_group_count_ = table_->GetTileGroupCount();
    int offset = index_->GetIndexedTileGroupOff();
    indexed_tile_offset_ = (offset == -1) ? INVALID_OID : (oid_t)offset;

    if (indexed_tile_offset_ == INVALID_OID) {
      current_tile_group_offset_ = START_OID;
    } else {
      current_tile_group_offset_ = indexed_tile_offset_ + 1;
      std::shared_ptr<storage::TileGroup> tile_group;
      if (current_tile_group_offset_ < table_tile_group_count_) {
        tile_group = table_->GetTileGroup(current_tile_group_offset_);
      } else {
        tile_group = table_->GetTileGroup(table_tile_group_count_ - 1);
      }

      oid_t tuple_id = 0;
      ItemPointer location(tile_group->GetTileGroupId(), tuple_id);
      block_threshold = location.block;
    }

    result_itr_ = START_OID;
    index_done_ = false;

    column_ids_ = node.GetColumnIds();
    std::vector<oid_t> key_column_ids_ = node.GetKeyColumnIds();
    std::vector<ExpressionType> expr_types_ = node.GetExprTypes();
    values_ = node.GetValues();
    std::vector<expression::AbstractExpression>runtime_keys_ = node.GetRunTimeKeys();
    predicate_ = node.GetPredicate();

    if (runtime_keys_.size() != 0) {
      assert(runtime_keys_.size() == values_.size());

      if (!key_ready_) {
        values_.clear();

        for (auto expr : runtime_keys_) {
          auto value = expr->Evaluate(nullptr, nullptr, executor_context_);
          LOG_INFO("Evaluated runtime scan key: %s", value.GetInfo().c_str());
          values_.push_back(value);
        }

        key_ready_ = true;
      }
    }

    if (table_ != nullptr) {
      full_column_ids_.resize(table_->GetSchema()->GetColumnCount());
      std::iota(full_column_ids_.begin(), full_column_ids_.end(), 0);
    }
  }

  return true;
}

bool HybridScanExecutor::SeqScanUtil() {
  assert(children_.size() == 0);
  // LOG_INFO("Hybrid executor, Seq Scan :: 0 child");

  assert(table_ != nullptr);
  assert(column_ids_.size() > 0);

  auto &transaction_manager =
      concurrency::TransactionManagerFactory::GetInstance();

  // Retrieve next tile group.
  while (current_tile_group_offset_ < table_tile_group_count_) {
    auto tile_group = table_->GetTileGroup(current_tile_group_offset_++);
    auto tile_group_header = tile_group->GetHeader();

    oid_t active_tuple_count = tile_group->GetNextTupleSlot();

    // Construct position list by looping through tile group
    // and applying the predicate.
    oid_t upper_bound_block = 0;
    if (item_pointers_.size() > 0) {
      auto reverse_iter = item_pointers_.rbegin();
      upper_bound_block = reverse_iter->block;
    }

    std::vector<oid_t> position_list;
    for (oid_t tuple_id = 0; tuple_id < active_tuple_count; tuple_id++) {
      ItemPointer location(tile_group->GetTileGroupId(), tuple_id);
      if (type_ == planner::HYBRID && item_pointers_.size() > 0 &&
          location.block <= upper_bound_block) {
        if (item_pointers_.find(location) != item_pointers_.end()) {
          continue;
        }
      }

      // check transaction visibility
      if (transaction_manager.IsVisible(tile_group_header, tuple_id)) {
        // if the tuple is visible, then perform predicate evaluation.
        if (predicate_ == nullptr) {
          position_list.push_back(tuple_id);
        } else {
          expression::ContainerTuple<storage::TileGroup> tuple(tile_group.get(),
                                                               tuple_id);
          auto eval =
              predicate_->Evaluate(&tuple, nullptr, executor_context_).IsTrue();
          if (eval == true) {
            position_list.push_back(tuple_id);
          }
        }
      } else {
        expression::ContainerTuple<storage::TileGroup> tuple(tile_group.get(),
                                                             tuple_id);
        auto eval =
            predicate_->Evaluate(&tuple, nullptr, executor_context_).IsTrue();
        if (eval == true) {
          position_list.push_back(tuple_id);
          auto res = transaction_manager.PerformRead(location);
          if (!res) {
            transaction_manager.SetTransactionResult(RESULT_FAILURE);
            return res;
          }
        }
      }
    }
    // Don't return empty tiles
    if (position_list.size() == 0) {
      continue;
    }

    // Construct logical tile.
    std::unique_ptr<LogicalTile> logical_tile(LogicalTileFactory::GetTile());
    logical_tile->AddColumns(tile_group, column_ids_);
    logical_tile->AddPositionList(std::move(position_list));
    LOG_INFO("Hybrid executor, Seq Scan :: Got a logical tile");
    SetOutput(logical_tile.release());
    return true;
  }

  return false;
}

bool HybridScanExecutor::IndexScanUtil() {
  // Already performed the index lookup
  assert(index_done_);

  while (result_itr_ < result_.size()) {  // Avoid returning empty tiles
    if (result_[result_itr_]->GetTupleCount() == 0) {
      result_itr_++;
      continue;
    } else {
      SetOutput(result_[result_itr_]);
      result_itr_++;
      return true;
    }
  }  // end while
  return false;
}

bool HybridScanExecutor::DExecute() {
  if (type_ == planner::SEQ) {
    return SeqScanUtil();
  } else if (type_ == planner::INDEX) {
    //  LOG_INFO("Hybrrd Scan executor, Index Scan :: 0 child");
    assert(children_.size() == 0);
    if (!index_done_) {
      if (index_->GetIndexType() == INDEX_CONSTRAINT_TYPE_PRIMARY_KEY) {
        auto status = ExecPrimaryIndexLookup();
        if (status == false) return false;
      } else {
        return false;
      }
    }

    return IndexScanUtil();
  } else {
    // do two part search
    if (index_done_ == false) {
      // Timer<> timer;
      // timer.Start();

      if (indexed_tile_offset_ == INVALID_OID) {
        index_done_ = true;
      } else {
        ExecPrimaryIndexLookup();
      }
    }

    if (IndexScanUtil() == true) {
      return true;
    }
    // Scan seq
    return SeqScanUtil();
  }
}

bool HybridScanExecutor::ExecPrimaryIndexLookup() {
  assert(!index_done_);

  const planner::HybridScanPlan &node = GetPlanNode<planner::HybridScanPlan>();

  std::vector<oid_t> key_column_ids_ = node.GetKeyColumnIds();
  std::vector<ExpressionType> expr_type_ = node.GetExprTypes();

  std::vector<ItemPointer *> tuple_location_ptrs;

  assert(index_->GetIndexType() == INDEX_CONSTRAINT_TYPE_PRIMARY_KEY);

  if (0 == key_column_ids_.size()) {
    index_->ScanAllKeys(tuple_location_ptrs);
  } else {
    index_->Scan(values_, key_column_ids_, expr_type_,
                 SCAN_DIRECTION_TYPE_FORWARD, tuple_location_ptrs);
  }

  LOG_INFO("Tuple_locations.size(): %lu", tuple_location_ptrs.size());

  auto &transaction_manager =
      concurrency::TransactionManagerFactory::GetInstance();

  if (tuple_location_ptrs.size() == 0) {
    index_done_ = true;
    return false;
  }

  // std::set<oid_t> oid_ts;

  std::map<oid_t, std::vector<oid_t>> visible_tuples;
  // for every tuple that is found in the index.
  for (auto tuple_location_ptr : tuple_location_ptrs) {
    ItemPointer tuple_location = *tuple_location_ptr;

    if (type_ == planner::HYBRID && tuple_location.block >= (block_threshold)) {
      item_pointers_.insert(tuple_location);
      //  oid_ts.insert(tuple_location.block);
    }

    auto &manager = catalog::Manager::GetInstance();
    auto tile_group = manager.GetTileGroup(tuple_location.block);
    auto tile_group_header = tile_group.get()->GetHeader();

    // perform transaction read
    size_t chain_length = 0;
    while (true) {
      ++chain_length;

      if (transaction_manager.IsVisible(tile_group_header,
                                        tuple_location.offset)) {
        visible_tuples[tuple_location.block].push_back(tuple_location.offset);
        auto res = transaction_manager.PerformRead(tuple_location);
        if (!res) {
          transaction_manager.SetTransactionResult(RESULT_FAILURE);
          return res;
        }
        break;
      } else {
        ItemPointer old_item = tuple_location;
        cid_t old_end_cid = tile_group_header->GetEndCommitId(old_item.offset);

        tuple_location = tile_group_header->GetNextItemPointer(old_item.offset);
        // there must exist a visible version.
        assert(tuple_location.IsNull() == false);

        cid_t max_committed_cid = transaction_manager.GetMaxCommittedCid();

        // check whether older version is garbage.
        if (old_end_cid < max_committed_cid) {
          assert(tile_group_header->GetTransactionId(old_item.offset) ==
                     INITIAL_TXN_ID ||
                 tile_group_header->GetTransactionId(old_item.offset) ==
                     INVALID_TXN_ID);

          if (tile_group_header->SetAtomicTransactionId(
                  old_item.offset, INVALID_TXN_ID) == true) {
            // atomically swap item pointer held in the index bucket.
            AtomicUpdateItemPointer(tuple_location_ptr, tuple_location);

            // currently, let's assume only primary index exists.
            // gc::GCManagerFactory::GetInstance().RecycleTupleSlot(
            //  table_->GetOid(), old_item.block, old_item.offset,
            //  max_committed_cid);
          }
        }

        tile_group = manager.GetTileGroup(tuple_location.block);
        tile_group_header = tile_group.get()->GetHeader();
      }
    }
  }

  // Construct a logical tile for each block
  for (auto tuples : visible_tuples) {
    auto &manager = catalog::Manager::GetInstance();
    auto tile_group = manager.GetTileGroup(tuples.first);

    std::unique_ptr<LogicalTile> logical_tile(LogicalTileFactory::GetTile());
    // Add relevant columns to logical tile
    logical_tile->AddColumns(tile_group, full_column_ids_);
    logical_tile->AddPositionList(std::move(tuples.second));
    if (column_ids_.size() != 0) {
      logical_tile->ProjectColumns(full_column_ids_, column_ids_);
    }

    result_.push_back(logical_tile.release());
  }

  index_done_ = true;

  LOG_TRACE("Result tiles : %lu", result_.size());

  return true;
}

}  // namespace executor
}  // namespace peloton
<commit_msg>Fixed mistake<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// hybrid_scan_executor.cpp
//
// Identification: src/executor/hybrid_scan_executor.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>
#include <utility>
#include <vector>
#include <string>
#include <unordered_map>
#include <chrono>
#include <iostream>
#include <ctime>
#include <cassert>
#include <thread>

#include "common/timer.h"
#include "common/types.h"
#include "executor/logical_tile.h"
#include "executor/logical_tile_factory.h"
#include "executor/executor_context.h"
#include "expression/abstract_expression.h"
#include "expression/container_tuple.h"
#include "planner/hybrid_scan_plan.h"
#include "executor/hybrid_scan_executor.h"
#include "storage/data_table.h"
#include "storage/tile_group_header.h"
#include "storage/tile.h"
#include "concurrency/transaction_manager_factory.h"
#include "common/logger.h"

namespace peloton {
namespace executor {

HybridScanExecutor::HybridScanExecutor(const planner::AbstractPlan *node,
                                       ExecutorContext *executor_context)
    : AbstractScanExecutor(node, executor_context),
      indexed_tile_offset_(START_OID) {}

bool HybridScanExecutor::DInit() {
  auto status = AbstractScanExecutor::DInit();

  if (!status) return false;

  const planner::HybridScanPlan &node = GetPlanNode<planner::HybridScanPlan>();

  table_ = node.GetTable();
  index_ = node.GetDataIndex();
  type_ = node.GetHybridType();

  if (type_ == planner::SEQ) {
    current_tile_group_offset_ = START_OID;
    if (table_ != nullptr) {
      table_tile_group_count_ = table_->GetTileGroupCount();
      if (column_ids_.empty()) {
        column_ids_.resize(table_->GetSchema()->GetColumnCount());
        std::iota(column_ids_.begin(), column_ids_.end(), 0);
      }
    }

  } else if (type_ == planner::INDEX) {
    result_itr_ = START_OID;
    index_done_ = false;

    column_ids_ = node.GetColumnIds();
    std::vector<oid_t> key_column_ids_ = node.GetKeyColumnIds();
    std::vector<ExpressionType> expr_types_ = node.GetExprTypes();
    values_ = node.GetValues();
    std::vector<expression::AbstractExpression *> runtime_keys_ = node.GetRunTimeKeys();
    predicate_ = node.GetPredicate();

    if (runtime_keys_.size() != 0) {
      assert(runtime_keys_.size() == values_.size());

      if (!key_ready_) {
        values_.clear();

        for (auto expr : runtime_keys_) {
          auto value = expr->Evaluate(nullptr, nullptr, executor_context_);
          LOG_INFO("Evaluated runtime scan key: %s", value.GetInfo().c_str());
          values_.push_back(value);
        }

        key_ready_ = true;
      }
    }

    if (table_ != nullptr) {
      full_column_ids_.resize(table_->GetSchema()->GetColumnCount());
      std::iota(full_column_ids_.begin(), full_column_ids_.end(), 0);
    }
  } else {  // Hybrid type.
    table_tile_group_count_ = table_->GetTileGroupCount();
    int offset = index_->GetIndexedTileGroupOff();
    indexed_tile_offset_ = (offset == -1) ? INVALID_OID : (oid_t)offset;

    if (indexed_tile_offset_ == INVALID_OID) {
      current_tile_group_offset_ = START_OID;
    } else {
      current_tile_group_offset_ = indexed_tile_offset_ + 1;
      std::shared_ptr<storage::TileGroup> tile_group;
      if (current_tile_group_offset_ < table_tile_group_count_) {
        tile_group = table_->GetTileGroup(current_tile_group_offset_);
      } else {
        tile_group = table_->GetTileGroup(table_tile_group_count_ - 1);
      }

      oid_t tuple_id = 0;
      ItemPointer location(tile_group->GetTileGroupId(), tuple_id);
      block_threshold = location.block;
    }

    result_itr_ = START_OID;
    index_done_ = false;

    column_ids_ = node.GetColumnIds();
    std::vector<oid_t> key_column_ids_ = node.GetKeyColumnIds();
    std::vector<ExpressionType> expr_types_ = node.GetExprTypes();
    values_ = node.GetValues();
    std::vector<expression::AbstractExpression *> runtime_keys_ = node.GetRunTimeKeys();
    predicate_ = node.GetPredicate();

    if (runtime_keys_.size() != 0) {
      assert(runtime_keys_.size() == values_.size());

      if (!key_ready_) {
        values_.clear();

        for (auto expr : runtime_keys_) {
          auto value = expr->Evaluate(nullptr, nullptr, executor_context_);
          LOG_INFO("Evaluated runtime scan key: %s", value.GetInfo().c_str());
          values_.push_back(value);
        }

        key_ready_ = true;
      }
    }

    if (table_ != nullptr) {
      full_column_ids_.resize(table_->GetSchema()->GetColumnCount());
      std::iota(full_column_ids_.begin(), full_column_ids_.end(), 0);
    }
  }

  return true;
}

bool HybridScanExecutor::SeqScanUtil() {
  assert(children_.size() == 0);
  // LOG_INFO("Hybrid executor, Seq Scan :: 0 child");

  assert(table_ != nullptr);
  assert(column_ids_.size() > 0);

  auto &transaction_manager =
      concurrency::TransactionManagerFactory::GetInstance();

  // Retrieve next tile group.
  while (current_tile_group_offset_ < table_tile_group_count_) {
    auto tile_group = table_->GetTileGroup(current_tile_group_offset_++);
    auto tile_group_header = tile_group->GetHeader();

    oid_t active_tuple_count = tile_group->GetNextTupleSlot();

    // Construct position list by looping through tile group
    // and applying the predicate.
    oid_t upper_bound_block = 0;
    if (item_pointers_.size() > 0) {
      auto reverse_iter = item_pointers_.rbegin();
      upper_bound_block = reverse_iter->block;
    }

    std::vector<oid_t> position_list;
    for (oid_t tuple_id = 0; tuple_id < active_tuple_count; tuple_id++) {
      ItemPointer location(tile_group->GetTileGroupId(), tuple_id);
      if (type_ == planner::HYBRID && item_pointers_.size() > 0 &&
          location.block <= upper_bound_block) {
        if (item_pointers_.find(location) != item_pointers_.end()) {
          continue;
        }
      }

      // check transaction visibility
      if (transaction_manager.IsVisible(tile_group_header, tuple_id)) {
        // if the tuple is visible, then perform predicate evaluation.
        if (predicate_ == nullptr) {
          position_list.push_back(tuple_id);
        } else {
          expression::ContainerTuple<storage::TileGroup> tuple(tile_group.get(),
                                                               tuple_id);
          auto eval =
              predicate_->Evaluate(&tuple, nullptr, executor_context_).IsTrue();
          if (eval == true) {
            position_list.push_back(tuple_id);
          }
        }
      } else {
        expression::ContainerTuple<storage::TileGroup> tuple(tile_group.get(),
                                                             tuple_id);
        auto eval =
            predicate_->Evaluate(&tuple, nullptr, executor_context_).IsTrue();
        if (eval == true) {
          position_list.push_back(tuple_id);
          auto res = transaction_manager.PerformRead(location);
          if (!res) {
            transaction_manager.SetTransactionResult(RESULT_FAILURE);
            return res;
          }
        }
      }
    }
    // Don't return empty tiles
    if (position_list.size() == 0) {
      continue;
    }

    // Construct logical tile.
    std::unique_ptr<LogicalTile> logical_tile(LogicalTileFactory::GetTile());
    logical_tile->AddColumns(tile_group, column_ids_);
    logical_tile->AddPositionList(std::move(position_list));
    LOG_INFO("Hybrid executor, Seq Scan :: Got a logical tile");
    SetOutput(logical_tile.release());
    return true;
  }

  return false;
}

bool HybridScanExecutor::IndexScanUtil() {
  // Already performed the index lookup
  assert(index_done_);

  while (result_itr_ < result_.size()) {  // Avoid returning empty tiles
    if (result_[result_itr_]->GetTupleCount() == 0) {
      result_itr_++;
      continue;
    } else {
      SetOutput(result_[result_itr_]);
      result_itr_++;
      return true;
    }
  }  // end while
  return false;
}

bool HybridScanExecutor::DExecute() {
  if (type_ == planner::SEQ) {
    return SeqScanUtil();
  } else if (type_ == planner::INDEX) {
    //  LOG_INFO("Hybrrd Scan executor, Index Scan :: 0 child");
    assert(children_.size() == 0);
    if (!index_done_) {
      if (index_->GetIndexType() == INDEX_CONSTRAINT_TYPE_PRIMARY_KEY) {
        auto status = ExecPrimaryIndexLookup();
        if (status == false) return false;
      } else {
        return false;
      }
    }

    return IndexScanUtil();
  } else {
    // do two part search
    if (index_done_ == false) {
      // Timer<> timer;
      // timer.Start();

      if (indexed_tile_offset_ == INVALID_OID) {
        index_done_ = true;
      } else {
        ExecPrimaryIndexLookup();
      }
    }

    if (IndexScanUtil() == true) {
      return true;
    }
    // Scan seq
    return SeqScanUtil();
  }
}

bool HybridScanExecutor::ExecPrimaryIndexLookup() {
  assert(!index_done_);

  const planner::HybridScanPlan &node = GetPlanNode<planner::HybridScanPlan>();

  std::vector<oid_t> key_column_ids_ = node.GetKeyColumnIds();
  std::vector<ExpressionType> expr_type_ = node.GetExprTypes();

  std::vector<ItemPointer *> tuple_location_ptrs;

  assert(index_->GetIndexType() == INDEX_CONSTRAINT_TYPE_PRIMARY_KEY);

  if (0 == key_column_ids_.size()) {
    index_->ScanAllKeys(tuple_location_ptrs);
  } else {
    index_->Scan(values_, key_column_ids_, expr_type_,
                 SCAN_DIRECTION_TYPE_FORWARD, tuple_location_ptrs);
  }

  LOG_INFO("Tuple_locations.size(): %lu", tuple_location_ptrs.size());

  auto &transaction_manager =
      concurrency::TransactionManagerFactory::GetInstance();

  if (tuple_location_ptrs.size() == 0) {
    index_done_ = true;
    return false;
  }

  // std::set<oid_t> oid_ts;

  std::map<oid_t, std::vector<oid_t>> visible_tuples;
  // for every tuple that is found in the index.
  for (auto tuple_location_ptr : tuple_location_ptrs) {
    ItemPointer tuple_location = *tuple_location_ptr;

    if (type_ == planner::HYBRID && tuple_location.block >= (block_threshold)) {
      item_pointers_.insert(tuple_location);
      //  oid_ts.insert(tuple_location.block);
    }

    auto &manager = catalog::Manager::GetInstance();
    auto tile_group = manager.GetTileGroup(tuple_location.block);
    auto tile_group_header = tile_group.get()->GetHeader();

    // perform transaction read
    size_t chain_length = 0;
    while (true) {
      ++chain_length;

      if (transaction_manager.IsVisible(tile_group_header,
                                        tuple_location.offset)) {
        visible_tuples[tuple_location.block].push_back(tuple_location.offset);
        auto res = transaction_manager.PerformRead(tuple_location);
        if (!res) {
          transaction_manager.SetTransactionResult(RESULT_FAILURE);
          return res;
        }
        break;
      } else {
        ItemPointer old_item = tuple_location;
        cid_t old_end_cid = tile_group_header->GetEndCommitId(old_item.offset);

        tuple_location = tile_group_header->GetNextItemPointer(old_item.offset);
        // there must exist a visible version.
        assert(tuple_location.IsNull() == false);

        cid_t max_committed_cid = transaction_manager.GetMaxCommittedCid();

        // check whether older version is garbage.
        if (old_end_cid < max_committed_cid) {
          assert(tile_group_header->GetTransactionId(old_item.offset) ==
                     INITIAL_TXN_ID ||
                 tile_group_header->GetTransactionId(old_item.offset) ==
                     INVALID_TXN_ID);

          if (tile_group_header->SetAtomicTransactionId(
                  old_item.offset, INVALID_TXN_ID) == true) {
            // atomically swap item pointer held in the index bucket.
            AtomicUpdateItemPointer(tuple_location_ptr, tuple_location);

            // currently, let's assume only primary index exists.
            // gc::GCManagerFactory::GetInstance().RecycleTupleSlot(
            //  table_->GetOid(), old_item.block, old_item.offset,
            //  max_committed_cid);
          }
        }

        tile_group = manager.GetTileGroup(tuple_location.block);
        tile_group_header = tile_group.get()->GetHeader();
      }
    }
  }

  // Construct a logical tile for each block
  for (auto tuples : visible_tuples) {
    auto &manager = catalog::Manager::GetInstance();
    auto tile_group = manager.GetTileGroup(tuples.first);

    std::unique_ptr<LogicalTile> logical_tile(LogicalTileFactory::GetTile());
    // Add relevant columns to logical tile
    logical_tile->AddColumns(tile_group, full_column_ids_);
    logical_tile->AddPositionList(std::move(tuples.second));
    if (column_ids_.size() != 0) {
      logical_tile->ProjectColumns(full_column_ids_, column_ids_);
    }

    result_.push_back(logical_tile.release());
  }

  index_done_ = true;

  LOG_TRACE("Result tiles : %lu", result_.size());

  return true;
}

}  // namespace executor
}  // namespace peloton
<|endoftext|>


<commit_before>/*****************************************************************************
 * Copyright (C) 2011-2015 Michael Ira Krufky
 *
 * Author: Michael Ira Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <stdio.h>
#include <sstream>
#include "value.h"

using namespace dvbtee::decode;

ValueBase::ValueBase(Type type, std::string name)
 : type(type)
 , name(name)
{
}

ValueBase::~ValueBase()
{
}

Object::Object()
{
	fprintf(stderr, "%s\n", __func__);
	//map.clear();
}

Object::~Object()
{
	fprintf(stderr, "%s\n", __func__);
	for (KeyValueMap::iterator it = map.begin(); it != map.end(); ++it) {
		//Value<TYPE, T> *value = (Value<TYPE, T>*)map[key];
		delete it->second;
	}
}

Object::Object(const Object &obj)
{
	for (KeyValueMap::const_iterator it = obj.map.begin(); it != obj.map.end(); ++it) {
		set(it->second);
	}

	fprintf(stderr, "%s(copy) %lu\n", __func__, map.size());
}

ValueBase *Object::get(std::string key)
{
	if (map.count(key))
		return map[key];

	return NULL;
}

std::string _toJson(ValueBase* val)
{
	std::stringstream s;

	switch(val->type) {
	case ValueBase::INTEGER:
		s << ((Value<ValueBase::INTEGER, int>*)val)->get();
		break;
	case ValueBase::STRING:
		s << "'" << ((Value<ValueBase::STRING, std::string>*)val)->get() << "'";
		break;
	case ValueBase::BOOLEAN:
		s << (((Value<ValueBase::BOOLEAN, bool>*)val)->get() ? "true" : "false");
		break;
	case ValueBase::DOUBLE:
		s << ((Value<ValueBase::DOUBLE, double>*)val)->get();
		break;
	case ValueBase::OBJECT:
		s << ((Value<ValueBase::OBJECT, Object>*)val)->get().toJson().c_str();
		break;
	case ValueBase::ARRAY:
		s << ((Value<ValueBase::ARRAY, Array>*)val)->get().toJson().c_str();
		break;
	}

	return s.str();
}

std::string Object::toJson()
{
	std::stringstream s;
	int count = 0;

	s << "{ ";
	for (KeyValueMap::iterator it = map.begin(); it != map.end(); ++it) {
		ValueBase *val = it->second;

		if (count) s << ", ";
		s << "'" << it->first << "': ";

		s << _toJson(val);

		count++;
	}
	s << " }";

	return s.str();
}

namespace dvbtee {
namespace decode {

template <>
int& Object::get<int>(std::string key)
{
	int def = 0;
	return get<ValueBase::INTEGER, int>(key, def);
}

template <>
std::string& Object::get<std::string>(std::string key)
{
	std::string def = "";
	return get<ValueBase::STRING, std::string>(key, def);
}

template <>
bool& Object::get<bool>(std::string key)
{
	bool def = false;
	return get<ValueBase::BOOLEAN, bool>(key, def);
}

template <>
double& Object::get<double>(std::string key)
{
	double def = 0.0;
	return get<ValueBase::DOUBLE, double>(key, def);
}

template <>
Object& Object::get<Object>(std::string key)
{
	Object def;
	return get<ValueBase::OBJECT, Object>(key, def);
}

template <>
Array& Object::get<Array>(std::string key)
{
	Array def;
	return get<ValueBase::ARRAY, Array>(key, def);
}

template <>
void Object::set<int>(std::string key, int val)
{
	return set<ValueBase::INTEGER, int>(key, val);
}

template <>
void Object::set<std::string>(std::string key, std::string val)
{
	return set<ValueBase::STRING, std::string>(key, val);
}

template <>
void Object::set<bool>(std::string key, bool val)
{
	return set<ValueBase::BOOLEAN, bool>(key, val);
}

template <>
void Object::set<double>(std::string key, double val)
{
	return set<ValueBase::DOUBLE, double>(key, val);
}

#if 0
template <>
void Object::set<Object>(std::string key, Object val)
{
	return set<ValueBase::OBJECT, Object>(key, val);
}

template <>
void Object::set<Array>(std::string key, Array val)
{
	return set<ValueBase::ARRAY, Array>(key, val);
}
#endif

}}

void Object::set(ValueBase *val)
{
	switch(val->type) {
	case ValueBase::INTEGER:
		set(val->name, ((Value<ValueBase::INTEGER, int>*)val)->get());
		break;
	case ValueBase::STRING:
		set(val->name, ((Value<ValueBase::STRING, std::string>*)val)->get());
		break;
	case ValueBase::BOOLEAN:
		set(val->name, ((Value<ValueBase::BOOLEAN, bool>*)val)->get());
		break;
	case ValueBase::DOUBLE:
		set(val->name, ((Value<ValueBase::DOUBLE, double>*)val)->get());
		break;
	case ValueBase::OBJECT:
		set(val->name, ((Value<ValueBase::OBJECT, Object>*)val)->get());
		break;
	case ValueBase::ARRAY:
		set(val->name, ((Value<ValueBase::ARRAY, Array>*)val)->get());
		break;
	}
}

Array::Array()
{

}

Array::~Array()
{

}

Array::Array(const Array &obj)
{
	for (KeyValueVector::const_iterator it = obj.vector.begin(); it != obj.vector.end(); ++it) {
		vector.push_back(*it);
	}
}

void Array::push(ValueBase *v)
{
	vector.push_back(v);
}

std::string Array::toJson()
{
	std::stringstream s;
	int count = 0;

	s << "[ ";

	for (KeyValueVector::const_iterator it = vector.begin(); it != vector.end(); ++it) {
		if (count) s << ", ";

		s << _toJson(*it);

		count++;
	}
	s << " ]";

	return s.str();

}

void Object::badType(ValueBase::Type typeRequested, ValueBase *val)
{
	fprintf(stderr, "Incorrect type requested for %s, requested %d, should be %d\n", val->name.c_str(), typeRequested, (int)val->type);
}
<commit_msg>decode/value: delete Values in Array::~Array destructor (disabled for now)<commit_after>/*****************************************************************************
 * Copyright (C) 2011-2015 Michael Ira Krufky
 *
 * Author: Michael Ira Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <stdio.h>
#include <sstream>
#include "value.h"

using namespace dvbtee::decode;

ValueBase::ValueBase(Type type, std::string name)
 : type(type)
 , name(name)
{
}

ValueBase::~ValueBase()
{
}

Object::Object()
{
	fprintf(stderr, "%s\n", __func__);
	//map.clear();
}

Object::~Object()
{
	fprintf(stderr, "%s\n", __func__);
	for (KeyValueMap::iterator it = map.begin(); it != map.end(); ++it) {
		//Value<TYPE, T> *value = (Value<TYPE, T>*)map[key];
		delete it->second;
	}
}

Object::Object(const Object &obj)
{
	for (KeyValueMap::const_iterator it = obj.map.begin(); it != obj.map.end(); ++it) {
		set(it->second);
	}

	fprintf(stderr, "%s(copy) %lu\n", __func__, map.size());
}

ValueBase *Object::get(std::string key)
{
	if (map.count(key))
		return map[key];

	return NULL;
}

std::string _toJson(ValueBase* val)
{
	std::stringstream s;

	switch(val->type) {
	case ValueBase::INTEGER:
		s << ((Value<ValueBase::INTEGER, int>*)val)->get();
		break;
	case ValueBase::STRING:
		s << "'" << ((Value<ValueBase::STRING, std::string>*)val)->get() << "'";
		break;
	case ValueBase::BOOLEAN:
		s << (((Value<ValueBase::BOOLEAN, bool>*)val)->get() ? "true" : "false");
		break;
	case ValueBase::DOUBLE:
		s << ((Value<ValueBase::DOUBLE, double>*)val)->get();
		break;
	case ValueBase::OBJECT:
		s << ((Value<ValueBase::OBJECT, Object>*)val)->get().toJson().c_str();
		break;
	case ValueBase::ARRAY:
		s << ((Value<ValueBase::ARRAY, Array>*)val)->get().toJson().c_str();
		break;
	}

	return s.str();
}

std::string Object::toJson()
{
	std::stringstream s;
	int count = 0;

	s << "{ ";
	for (KeyValueMap::iterator it = map.begin(); it != map.end(); ++it) {
		ValueBase *val = it->second;

		if (count) s << ", ";
		s << "'" << it->first << "': ";

		s << _toJson(val);

		count++;
	}
	s << " }";

	return s.str();
}

namespace dvbtee {
namespace decode {

template <>
int& Object::get<int>(std::string key)
{
	int def = 0;
	return get<ValueBase::INTEGER, int>(key, def);
}

template <>
std::string& Object::get<std::string>(std::string key)
{
	std::string def = "";
	return get<ValueBase::STRING, std::string>(key, def);
}

template <>
bool& Object::get<bool>(std::string key)
{
	bool def = false;
	return get<ValueBase::BOOLEAN, bool>(key, def);
}

template <>
double& Object::get<double>(std::string key)
{
	double def = 0.0;
	return get<ValueBase::DOUBLE, double>(key, def);
}

template <>
Object& Object::get<Object>(std::string key)
{
	Object def;
	return get<ValueBase::OBJECT, Object>(key, def);
}

template <>
Array& Object::get<Array>(std::string key)
{
	Array def;
	return get<ValueBase::ARRAY, Array>(key, def);
}

template <>
void Object::set<int>(std::string key, int val)
{
	return set<ValueBase::INTEGER, int>(key, val);
}

template <>
void Object::set<std::string>(std::string key, std::string val)
{
	return set<ValueBase::STRING, std::string>(key, val);
}

template <>
void Object::set<bool>(std::string key, bool val)
{
	return set<ValueBase::BOOLEAN, bool>(key, val);
}

template <>
void Object::set<double>(std::string key, double val)
{
	return set<ValueBase::DOUBLE, double>(key, val);
}

#if 0
template <>
void Object::set<Object>(std::string key, Object val)
{
	return set<ValueBase::OBJECT, Object>(key, val);
}

template <>
void Object::set<Array>(std::string key, Array val)
{
	return set<ValueBase::ARRAY, Array>(key, val);
}
#endif

}}

void Object::set(ValueBase *val)
{
	switch(val->type) {
	case ValueBase::INTEGER:
		set(val->name, ((Value<ValueBase::INTEGER, int>*)val)->get());
		break;
	case ValueBase::STRING:
		set(val->name, ((Value<ValueBase::STRING, std::string>*)val)->get());
		break;
	case ValueBase::BOOLEAN:
		set(val->name, ((Value<ValueBase::BOOLEAN, bool>*)val)->get());
		break;
	case ValueBase::DOUBLE:
		set(val->name, ((Value<ValueBase::DOUBLE, double>*)val)->get());
		break;
	case ValueBase::OBJECT:
		set(val->name, ((Value<ValueBase::OBJECT, Object>*)val)->get());
		break;
	case ValueBase::ARRAY:
		set(val->name, ((Value<ValueBase::ARRAY, Array>*)val)->get());
		break;
	}
}

Array::Array()
{
	fprintf(stderr, "%s\n", __func__);
}

Array::~Array()
{
	fprintf(stderr, "%s\n", __func__);
#if 0
	for (KeyValueVector::iterator it = vector.begin(); it != vector.end(); ++it) {
		delete *it;
	}
#endif
}

Array::Array(const Array &obj)
{
	for (KeyValueVector::const_iterator it = obj.vector.begin(); it != obj.vector.end(); ++it) {
		vector.push_back(*it);
	}
	fprintf(stderr, "%s(copy) %lu\n", __func__, vector.size());
}

void Array::push(ValueBase *v)
{
	vector.push_back(v);
}

std::string Array::toJson()
{
	std::stringstream s;
	int count = 0;

	s << "[ ";

	for (KeyValueVector::const_iterator it = vector.begin(); it != vector.end(); ++it) {
		if (count) s << ", ";

		s << _toJson(*it);

		count++;
	}
	s << " ]";

	return s.str();

}

void Object::badType(ValueBase::Type typeRequested, ValueBase *val)
{
	fprintf(stderr, "Incorrect type requested for %s, requested %d, should be %d\n", val->name.c_str(), typeRequested, (int)val->type);
}
<|endoftext|>