<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkThinPlateSplineMeshWarp.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to Tim Hutton (MINORI Project, Dental and Medical
             Informatics, Eastman Dental Institute, London, UK) who
             developed and contributed this class.

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkThinPlateSplineMeshWarp.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkThinPlateSplineMeshWarp* vtkThinPlateSplineMeshWarp::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkThinPlateSplineMeshWarp");
  if(ret)
    {
    return (vtkThinPlateSplineMeshWarp*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkThinPlateSplineMeshWarp;
}

vtkThinPlateSplineMeshWarp::vtkThinPlateSplineMeshWarp()
{
  this->SourceLandmarks=NULL;
  this->TargetLandmarks=NULL;
  this->Sigma=1.0;
}

vtkThinPlateSplineMeshWarp::~vtkThinPlateSplineMeshWarp()
{
  if (this->SourceLandmarks)
    {
    this->SourceLandmarks->Delete();
    }
  if (this->TargetLandmarks)
    {
    this->TargetLandmarks->Delete();
    }
}

//------------------------------------------------------------------------
// some dull matrix things

inline double** NewMatrix(int x,int y)
{
  double** m = new double*[x];
  for(int i=0;i<x;i++)
    {
    m[i] = new double[y];
    }
  return m;
}
inline void DeleteMatrix(double** m,int x,int y)
{
  for(int i=0;i<x;i++)
    {
    delete [] m[i]; // OK, we don't actually need y
    }
  delete [] m;
}
inline void FillMatrixWithZeros(double** m,int x,int y)
{
  int i,j;
  for(i=0;i<x;i++)
    {
    for(j=0;j<y;j++)
      {
      m[i][j]=0.0;
      }
    }
}
inline void TransposeMatrix(double*** m,int x,int y)
{
  double swap,*a,*b;
  int r,c;
  if(x==y)
    {
    // matrix is square, can just swap values over the diagonal (fast)
    for(c=1;c<x;c++)
      {
      for(r=0;r<c;r++)
        {
        a = &((*m)[r][c]); // (what a mess)
        b = &((*m)[c][r]);
        swap=*a;
        *a=*b;
        *b=swap;
        }
      }
    }
  else
    {
    // matrix is not square, must reallocate memory first
    double **result = NewMatrix(y,x);
    int r,c;
    for(r=0;r<y;r++)
      {
      for(c=0;c<x;c++)
        {
        result[r][c] = (*m)[c][r];
        }
      }
    // plug in the replacement matrix
    DeleteMatrix(*m,x,y);
    *m=result;
    }
}
inline void MatrixMultiply(double** a,double** b,double** c,int ar,int ac,
                           int br,int bc)
{
  if(ac!=br)
    {
    return;	// ac must equal br otherwise we can't proceed
    }

  // c must have size ar*bc (we assume this)
  const int cr=ar,cc=bc;
  int row,col,i;
  for(row=0;row<cr;row++)
    {
    for(col=0;col<cc;col++)
      {
      c[row][col]=0.0;
      for(i=0;i<ac;i++)
        {
        c[row][col] += a[row][i]*b[i][col];
        }
      }
    }
}

//------------------------------------------------------------------------

// a teeny-tiny but rather crucial function
inline float U(float x,float sigma) {

  if(x==0.0F)
    {
    return x;
    }
  else
    {
    return (x/sigma)*(x/sigma)*log(x/sigma);
    }
}

//------------------------------------------------------------------------

void vtkThinPlateSplineMeshWarp::Execute()
{
  if(this->SourceLandmarks==NULL)
    {
    vtkWarningMacro(<<"No source landmarks - output will be empty");
    return;
    }

  if(this->TargetLandmarks==NULL)
    {
    vtkWarningMacro(<<"No target landmarks - output will be empty");
    return;
    }

  // Notation and inspiration from:
  // Fred L. Bookstein (1997) "Shape and the Information in Medical Images:
  // A Decade of the Morphometric Synthesis" Computer Vision and Image
  // Understanding 66(2):97-118
  // and online work published by Tim Cootes (http://www.wiau.man.ac.uk/~bim)

  const int N = this->SourceLandmarks->GetNumberOfPoints();
  const int D = 3; // dimensions

  // the input matrices
  double **L = NewMatrix(N+D+1,N+D+1);
  double **X = NewMatrix(N+D+1,D);
  // the output weights matrix
  double **W = NewMatrix(N+D+1,D); // will be transposed later, mind

  // build L
  FillMatrixWithZeros(L,N+D+1,N+D+1); // will leave the bottom-right corner with zeros
  int r,c;
  float p[3],p2[3];
  for(r=0;r<N;r++)
    {
    this->SourceLandmarks->GetPoint(r,p);
    // fill in the top-right corner of L (Q)
    L[r][N] = 1.0;
    L[r][N+1] = p[0];
    L[r][N+2] = p[1];
    L[r][N+3] = p[2];
    // fill in the bottom-left corner of L (Q transposed)
    L[N][r] = 1.0;
    L[N+1][r] = p[0];
    L[N+2][r] = p[1];
    L[N+3][r] = p[2];
    // fill in the top-left corner of L (K)
    for(c=0;c<N;c++)
      {
      this->SourceLandmarks->GetPoint(c,p2);
      L[r][c] = U(sqrt(vtkMath::Distance2BetweenPoints(p,p2)),this->Sigma);
      }
    }

  // build X
  FillMatrixWithZeros(X,N+D+1,D);
  for(r=0;r<N;r++)
    {
    this->TargetLandmarks->GetPoint(r,p);
    X[r][0] = p[0];
    X[r][1] = p[1];
    X[r][2] = p[2];
    }

  // solve for W
  double **LI = NewMatrix(N+D+1,N+D+1);
  vtkMath::InvertMatrix(L,LI,N+D+1);
  MatrixMultiply(LI,X,W,N+D+1,N+D+1,N+D+1,D);
  TransposeMatrix(&W,N+D+1,D);
  //W = Transpose(Inverse(L)*X);
  // much easier if we have a decent matrix class, no?

  // resample input based on transform given by x' = Wu(x)
  vtkPolyData *input = this->GetInput();
  vtkPolyData *output = this->GetOutput();

  // copy the topology from the input mesh, as well as the point and cell
  // attributes
  output->CopyStructure(input);
  output->GetPointData()->PassData(input->GetPointData());
  output->GetCellData()->PassData(input->GetCellData());

  // create a new points structure for the output mesh
  vtkPoints *outputPoints = vtkPoints::New();
  output->SetPoints(outputPoints);
  outputPoints->SetNumberOfPoints(input->GetPoints()->GetNumberOfPoints());

  double **SOURCE = NewMatrix(D,1); // we know the target, we want the source
  double **UDX = NewMatrix(N+D+1,1);
  float *point;
  for(int j=0;j<input->GetPoints()->GetNumberOfPoints();j++)
    {
    point = input->GetPoints()->GetPoint(j);
    // build the N+D+1*1 vector UDX (Ud(x))
    for(int i=0;i<N;i++)
      {
      this->SourceLandmarks->GetPoint(i,p);
      UDX[i][0] = U(sqrt(vtkMath::Distance2BetweenPoints(point,p)),this->Sigma);
      }
    UDX[N][0] = 1.0;
    UDX[N+1][0] = point[0];
    UDX[N+2][0] = point[1];
    UDX[N+3][0] = point[2];
    // find the source point
    MatrixMultiply(W,UDX,SOURCE,D,N+D+1,N+D+1,1);
    //SOURCE = W*UDX; // would be so effortless...
    output->GetPoints()->SetPoint(j,SOURCE[0][0],SOURCE[1][0],SOURCE[2][0]);
    }

  DeleteMatrix(UDX,N+D+1,1);
  DeleteMatrix(SOURCE,D,1);
  DeleteMatrix(LI,N+D+1,N+D+1);
  DeleteMatrix(L,N+D+1,N+D+1);
  DeleteMatrix(X,N+D+1,D);
  DeleteMatrix(W,D,N+D+1); // W has been transposed since it was created
}

void vtkThinPlateSplineMeshWarp::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyDataToPolyDataFilter::PrintSelf(os,indent);

  os << indent << "Sigma:" << this->Sigma << "\n";
  os << indent << "Source Landmarks: " << this->SourceLandmarks << "\n";
  os << indent << "Target Landmarks: " << this->TargetLandmarks << "\n";
}

<commit_msg>ERR: memory leak.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkThinPlateSplineMeshWarp.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to Tim Hutton (MINORI Project, Dental and Medical
             Informatics, Eastman Dental Institute, London, UK) who
             developed and contributed this class.

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkThinPlateSplineMeshWarp.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkThinPlateSplineMeshWarp* vtkThinPlateSplineMeshWarp::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkThinPlateSplineMeshWarp");
  if(ret)
    {
    return (vtkThinPlateSplineMeshWarp*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkThinPlateSplineMeshWarp;
}

vtkThinPlateSplineMeshWarp::vtkThinPlateSplineMeshWarp()
{
  this->SourceLandmarks=NULL;
  this->TargetLandmarks=NULL;
  this->Sigma=1.0;
}

vtkThinPlateSplineMeshWarp::~vtkThinPlateSplineMeshWarp()
{
  if (this->SourceLandmarks)
    {
    this->SourceLandmarks->Delete();
    }
  if (this->TargetLandmarks)
    {
    this->TargetLandmarks->Delete();
    }
}

//------------------------------------------------------------------------
// some dull matrix things

inline double** NewMatrix(int x,int y)
{
  double** m = new double*[x];
  for(int i=0;i<x;i++)
    {
    m[i] = new double[y];
    }
  return m;
}
inline void DeleteMatrix(double** m,int x,int y)
{
  for(int i=0;i<x;i++)
    {
    delete [] m[i]; // OK, we don't actually need y
    }
  delete [] m;
}
inline void FillMatrixWithZeros(double** m,int x,int y)
{
  int i,j;
  for(i=0;i<x;i++)
    {
    for(j=0;j<y;j++)
      {
      m[i][j]=0.0;
      }
    }
}
inline void TransposeMatrix(double*** m,int x,int y)
{
  double swap,*a,*b;
  int r,c;
  if(x==y)
    {
    // matrix is square, can just swap values over the diagonal (fast)
    for(c=1;c<x;c++)
      {
      for(r=0;r<c;r++)
        {
        a = &((*m)[r][c]); // (what a mess)
        b = &((*m)[c][r]);
        swap=*a;
        *a=*b;
        *b=swap;
        }
      }
    }
  else
    {
    // matrix is not square, must reallocate memory first
    double **result = NewMatrix(y,x);
    int r,c;
    for(r=0;r<y;r++)
      {
      for(c=0;c<x;c++)
        {
        result[r][c] = (*m)[c][r];
        }
      }
    // plug in the replacement matrix
    DeleteMatrix(*m,x,y);
    *m=result;
    }
}
inline void MatrixMultiply(double** a,double** b,double** c,int ar,int ac,
                           int br,int bc)
{
  if(ac!=br)
    {
    return;	// ac must equal br otherwise we can't proceed
    }

  // c must have size ar*bc (we assume this)
  const int cr=ar,cc=bc;
  int row,col,i;
  for(row=0;row<cr;row++)
    {
    for(col=0;col<cc;col++)
      {
      c[row][col]=0.0;
      for(i=0;i<ac;i++)
        {
        c[row][col] += a[row][i]*b[i][col];
        }
      }
    }
}

//------------------------------------------------------------------------

// a teeny-tiny but rather crucial function
inline float U(float x,float sigma) {

  if(x==0.0F)
    {
    return x;
    }
  else
    {
    return (x/sigma)*(x/sigma)*log(x/sigma);
    }
}

//------------------------------------------------------------------------

void vtkThinPlateSplineMeshWarp::Execute()
{
  if(this->SourceLandmarks==NULL)
    {
    vtkWarningMacro(<<"No source landmarks - output will be empty");
    return;
    }

  if(this->TargetLandmarks==NULL)
    {
    vtkWarningMacro(<<"No target landmarks - output will be empty");
    return;
    }

  // Notation and inspiration from:
  // Fred L. Bookstein (1997) "Shape and the Information in Medical Images:
  // A Decade of the Morphometric Synthesis" Computer Vision and Image
  // Understanding 66(2):97-118
  // and online work published by Tim Cootes (http://www.wiau.man.ac.uk/~bim)

  const int N = this->SourceLandmarks->GetNumberOfPoints();
  const int D = 3; // dimensions

  // the input matrices
  double **L = NewMatrix(N+D+1,N+D+1);
  double **X = NewMatrix(N+D+1,D);
  // the output weights matrix
  double **W = NewMatrix(N+D+1,D); // will be transposed later, mind

  // build L
  FillMatrixWithZeros(L,N+D+1,N+D+1); // will leave the bottom-right corner with zeros
  int r,c;
  float p[3],p2[3];
  for(r=0;r<N;r++)
    {
    this->SourceLandmarks->GetPoint(r,p);
    // fill in the top-right corner of L (Q)
    L[r][N] = 1.0;
    L[r][N+1] = p[0];
    L[r][N+2] = p[1];
    L[r][N+3] = p[2];
    // fill in the bottom-left corner of L (Q transposed)
    L[N][r] = 1.0;
    L[N+1][r] = p[0];
    L[N+2][r] = p[1];
    L[N+3][r] = p[2];
    // fill in the top-left corner of L (K)
    for(c=0;c<N;c++)
      {
      this->SourceLandmarks->GetPoint(c,p2);
      L[r][c] = U(sqrt(vtkMath::Distance2BetweenPoints(p,p2)),this->Sigma);
      }
    }

  // build X
  FillMatrixWithZeros(X,N+D+1,D);
  for(r=0;r<N;r++)
    {
    this->TargetLandmarks->GetPoint(r,p);
    X[r][0] = p[0];
    X[r][1] = p[1];
    X[r][2] = p[2];
    }

  // solve for W
  double **LI = NewMatrix(N+D+1,N+D+1);
  vtkMath::InvertMatrix(L,LI,N+D+1);
  MatrixMultiply(LI,X,W,N+D+1,N+D+1,N+D+1,D);
  TransposeMatrix(&W,N+D+1,D);
  //W = Transpose(Inverse(L)*X);
  // much easier if we have a decent matrix class, no?

  // resample input based on transform given by x' = Wu(x)
  vtkPolyData *input = this->GetInput();
  vtkPolyData *output = this->GetOutput();

  // copy the topology from the input mesh, as well as the point and cell
  // attributes
  output->CopyStructure(input);
  output->GetPointData()->PassData(input->GetPointData());
  output->GetCellData()->PassData(input->GetCellData());

  // create a new points structure for the output mesh
  vtkPoints *outputPoints = vtkPoints::New();
  output->SetPoints(outputPoints);
  outputPoints->Delete();
  outputPoints->SetNumberOfPoints(input->GetPoints()->GetNumberOfPoints());

  double **SOURCE = NewMatrix(D,1); // we know the target, we want the source
  double **UDX = NewMatrix(N+D+1,1);
  float *point;
  for(int j=0;j<input->GetPoints()->GetNumberOfPoints();j++)
    {
    point = input->GetPoints()->GetPoint(j);
    // build the N+D+1*1 vector UDX (Ud(x))
    for(int i=0;i<N;i++)
      {
      this->SourceLandmarks->GetPoint(i,p);
      UDX[i][0] = U(sqrt(vtkMath::Distance2BetweenPoints(point,p)),this->Sigma);
      }
    UDX[N][0] = 1.0;
    UDX[N+1][0] = point[0];
    UDX[N+2][0] = point[1];
    UDX[N+3][0] = point[2];
    // find the source point
    MatrixMultiply(W,UDX,SOURCE,D,N+D+1,N+D+1,1);
    //SOURCE = W*UDX; // would be so effortless...
    output->GetPoints()->SetPoint(j,SOURCE[0][0],SOURCE[1][0],SOURCE[2][0]);
    }

  DeleteMatrix(UDX,N+D+1,1);
  DeleteMatrix(SOURCE,D,1);
  DeleteMatrix(LI,N+D+1,N+D+1);
  DeleteMatrix(L,N+D+1,N+D+1);
  DeleteMatrix(X,N+D+1,D);
  DeleteMatrix(W,D,N+D+1); // W has been transposed since it was created
}

void vtkThinPlateSplineMeshWarp::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyDataToPolyDataFilter::PrintSelf(os,indent);

  os << indent << "Sigma:" << this->Sigma << "\n";
  os << indent << "Source Landmarks: " << this->SourceLandmarks << "\n";
  os << indent << "Target Landmarks: " << this->TargetLandmarks << "\n";
}

<|endoftext|>


<commit_before>
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrContextFactory.h"
#include "gl/GLTestContext.h"

#if SK_ANGLE
    #include "gl/angle/GLTestContext_angle.h"
#endif
#include "gl/command_buffer/GLTestContext_command_buffer.h"
#include "gl/debug/DebugGLTestContext.h"
#ifdef SK_VULKAN
#include "vk/VkTestContext.h"
#endif
#ifdef SK_METAL
#include "mtl/MtlTestContext.h"
#endif
#include "gl/null/NullGLTestContext.h"
#include "gl/GrGLGpu.h"
#include "mock/MockTestContext.h"
#include "GrCaps.h"

#if defined(SK_BUILD_FOR_WIN32) && defined(SK_ENABLE_DISCRETE_GPU)
extern "C" {
    // NVIDIA documents that the presence and value of this symbol programmatically enable the high
    // performance GPU in laptops with switchable graphics.
    //   https://docs.nvidia.com/gameworks/content/technologies/desktop/optimus.htm
    // From testing, including this symbol, even if it is set to 0, we still get the NVIDIA GPU.
    _declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;

    // AMD has a similar mechanism, although I don't have an AMD laptop, so this is untested.
    //   https://community.amd.com/thread/169965
    __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
#endif

namespace sk_gpu_test {
GrContextFactory::GrContextFactory() { }

GrContextFactory::GrContextFactory(const GrContextOptions& opts)
    : fGlobalOptions(opts) {
}

GrContextFactory::~GrContextFactory() {
    this->destroyContexts();
}

void GrContextFactory::destroyContexts() {
    for (Context& context : fContexts) {
        SkScopeExit restore(nullptr);
        if (context.fTestContext) {
            restore = context.fTestContext->makeCurrentAndAutoRestore();
        }
        if (!context.fGrContext->unique()) {
            context.fGrContext->releaseResourcesAndAbandonContext();
            context.fAbandoned = true;
        }
        context.fGrContext->unref();
        delete context.fTestContext;
    }
    fContexts.reset();
}

void GrContextFactory::abandonContexts() {
    for (Context& context : fContexts) {
        if (!context.fAbandoned) {
            if (context.fTestContext) {
                auto restore = context.fTestContext->makeCurrentAndAutoRestore();
                context.fTestContext->testAbandon();
                delete(context.fTestContext);
                context.fTestContext = nullptr;
            }
            context.fGrContext->abandonContext();
            context.fAbandoned = true;
        }
    }
}

void GrContextFactory::releaseResourcesAndAbandonContexts() {
    for (Context& context : fContexts) {
        SkScopeExit restore(nullptr);
        if (!context.fAbandoned) {
            if (context.fTestContext) {
                restore = context.fTestContext->makeCurrentAndAutoRestore();
            }
            context.fGrContext->releaseResourcesAndAbandonContext();
            context.fAbandoned = true;
            if (context.fTestContext) {
                delete context.fTestContext;
                context.fTestContext = nullptr;
            }
        }
    }
}

GrContext* GrContextFactory::get(ContextType type, ContextOverrides overrides) {
    return this->getContextInfo(type, overrides).grContext();
}

ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOverrides overrides,
                                                     GrContext* shareContext, uint32_t shareIndex) {
    // (shareIndex != 0) -> (shareContext != nullptr)
    SkASSERT((shareIndex == 0) || (shareContext != nullptr));

    for (int i = 0; i < fContexts.count(); ++i) {
        Context& context = fContexts[i];
        if (context.fType == type &&
            context.fOverrides == overrides &&
            context.fShareContext == shareContext &&
            context.fShareIndex == shareIndex &&
            !context.fAbandoned) {
            context.fTestContext->makeCurrent();
            return ContextInfo(context.fType, context.fTestContext, context.fGrContext,
                               context.fOptions);
        }
    }

    // If we're trying to create a context in a share group, find the master context
    Context* masterContext = nullptr;
    if (shareContext) {
        for (int i = 0; i < fContexts.count(); ++i) {
            if (!fContexts[i].fAbandoned && fContexts[i].fGrContext == shareContext) {
                masterContext = &fContexts[i];
                break;
            }
        }
        SkASSERT(masterContext && masterContext->fType == type);
    }

    std::unique_ptr<TestContext> testCtx;
    GrBackend backend = ContextTypeBackend(type);
    switch (backend) {
        case kOpenGL_GrBackend: {
            GLTestContext* glShareContext = masterContext
                    ? static_cast<GLTestContext*>(masterContext->fTestContext) : nullptr;
            GLTestContext* glCtx;
            switch (type) {
                case kGL_ContextType:
                    glCtx = CreatePlatformGLTestContext(kGL_GrGLStandard, glShareContext);
                    break;
                case kGLES_ContextType:
                    glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard, glShareContext);
                    break;
#if SK_ANGLE
                case kANGLE_D3D9_ES2_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D9, ANGLEContextVersion::kES2,
                                                 glShareContext).release();
                    break;
                case kANGLE_D3D11_ES2_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES2,
                                                 glShareContext).release();
                    break;
                case kANGLE_D3D11_ES3_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES3,
                                                 glShareContext).release();
                    break;
                case kANGLE_GL_ES2_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES2,
                                                 glShareContext).release();
                    break;
                case kANGLE_GL_ES3_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES3,
                                                 glShareContext).release();
                    break;
#endif
#ifndef SK_NO_COMMAND_BUFFER
                case kCommandBuffer_ContextType:
                    glCtx = CommandBufferGLTestContext::Create(glShareContext);
                    break;
#endif
                case kNullGL_ContextType:
                    glCtx = CreateNullGLTestContext(
                            ContextOverrides::kRequireNVPRSupport & overrides, glShareContext);
                    break;
                case kDebugGL_ContextType:
                    glCtx = CreateDebugGLTestContext(glShareContext);
                    break;
                default:
                    return ContextInfo();
            }
            if (!glCtx) {
                return ContextInfo();
            }
            testCtx.reset(glCtx);
            break;
        }
#ifdef SK_VULKAN
        case kVulkan_GrBackend: {
            VkTestContext* vkSharedContext = masterContext
                    ? static_cast<VkTestContext*>(masterContext->fTestContext) : nullptr;
            SkASSERT(kVulkan_ContextType == type);
            if (ContextOverrides::kRequireNVPRSupport & overrides) {
                return ContextInfo();
            }
            testCtx.reset(CreatePlatformVkTestContext(vkSharedContext));
            if (!testCtx) {
                return ContextInfo();
            }

            // There is some bug (either in Skia or the NV Vulkan driver) where VkDevice
            // destruction will hang occaisonally. For some reason having an existing GL
            // context fixes this.
            if (!fSentinelGLContext) {
                fSentinelGLContext.reset(CreatePlatformGLTestContext(kGL_GrGLStandard));
                if (!fSentinelGLContext) {
                    fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
                }
            }
            break;
        }
#endif
#ifdef SK_METAL
        case kMetal_GrBackend: {
            SkASSERT(!masterContext);
            testCtx.reset(CreatePlatformMtlTestContext(nullptr));
            if (!testCtx) {
                return ContextInfo();
            }
            break;
        }
#endif
        case kMock_GrBackend: {
            TestContext* sharedContext = masterContext ? masterContext->fTestContext : nullptr;
            SkASSERT(kMock_ContextType == type);
            if (ContextOverrides::kRequireNVPRSupport & overrides) {
                return ContextInfo();
            }
            testCtx.reset(CreateMockTestContext(sharedContext));
            if (!testCtx) {
                return ContextInfo();
            }
            break;
        }
        default:
            return ContextInfo();
    }

    SkASSERT(testCtx && testCtx->backend() == backend);
    GrContextOptions grOptions = fGlobalOptions;
    if (ContextOverrides::kDisableNVPR & overrides) {
        grOptions.fSuppressPathRendering = true;
    }
    if (ContextOverrides::kAllowSRGBWithoutDecodeControl & overrides) {
        grOptions.fRequireDecodeDisableForSRGB = false;
    }
    if (ContextOverrides::kAvoidStencilBuffers & overrides) {
        grOptions.fAvoidStencilBuffers = true;
    }
    sk_sp<GrContext> grCtx;
    {
        auto restore = testCtx->makeCurrentAndAutoRestore();
        grCtx = testCtx->makeGrContext(grOptions);
    }
    if (!grCtx.get()) {
        return ContextInfo();
    }
    if (ContextOverrides::kRequireNVPRSupport & overrides) {
        if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) {
            return ContextInfo();
        }
    }
    if (ContextOverrides::kRequireSRGBSupport & overrides) {
        if (!grCtx->caps()->srgbSupport()) {
            return ContextInfo();
        }
    }

    Context& context = fContexts.push_back();
    context.fBackend = backend;
    context.fTestContext = testCtx.release();
    context.fGrContext = SkRef(grCtx.get());
    context.fType = type;
    context.fOverrides = overrides;
    context.fAbandoned = false;
    context.fShareContext = shareContext;
    context.fShareIndex = shareIndex;
    context.fOptions = grOptions;
    context.fTestContext->makeCurrent();
    return ContextInfo(context.fType, context.fTestContext, context.fGrContext, context.fOptions);
}

ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides overrides) {
    return this->getContextInfoInternal(type, overrides, nullptr, 0);
}

ContextInfo GrContextFactory::getSharedContextInfo(GrContext* shareContext, uint32_t shareIndex) {
    SkASSERT(shareContext);
    for (int i = 0; i < fContexts.count(); ++i) {
        if (!fContexts[i].fAbandoned && fContexts[i].fGrContext == shareContext) {
            return this->getContextInfoInternal(fContexts[i].fType, fContexts[i].fOverrides,
                                                shareContext, shareIndex);
        }
    }

    return ContextInfo();
}

}  // namespace sk_gpu_test
<commit_msg>Delete Gr testing contexts in reverse order<commit_after>
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrContextFactory.h"
#include "gl/GLTestContext.h"

#if SK_ANGLE
    #include "gl/angle/GLTestContext_angle.h"
#endif
#include "gl/command_buffer/GLTestContext_command_buffer.h"
#include "gl/debug/DebugGLTestContext.h"
#ifdef SK_VULKAN
#include "vk/VkTestContext.h"
#endif
#ifdef SK_METAL
#include "mtl/MtlTestContext.h"
#endif
#include "gl/null/NullGLTestContext.h"
#include "gl/GrGLGpu.h"
#include "mock/MockTestContext.h"
#include "GrCaps.h"

#if defined(SK_BUILD_FOR_WIN32) && defined(SK_ENABLE_DISCRETE_GPU)
extern "C" {
    // NVIDIA documents that the presence and value of this symbol programmatically enable the high
    // performance GPU in laptops with switchable graphics.
    //   https://docs.nvidia.com/gameworks/content/technologies/desktop/optimus.htm
    // From testing, including this symbol, even if it is set to 0, we still get the NVIDIA GPU.
    _declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;

    // AMD has a similar mechanism, although I don't have an AMD laptop, so this is untested.
    //   https://community.amd.com/thread/169965
    __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
#endif

namespace sk_gpu_test {
GrContextFactory::GrContextFactory() { }

GrContextFactory::GrContextFactory(const GrContextOptions& opts)
    : fGlobalOptions(opts) {
}

GrContextFactory::~GrContextFactory() {
    this->destroyContexts();
}

void GrContextFactory::destroyContexts() {
    // We must delete the test contexts in reverse order so that any child context is finished and
    // deleted before a parent context. This relies on the fact that when we make a new context we
    // append it to the end of fContexts array.
    // TODO: Look into keeping a dependency dag for contexts and deletion order
    for (int i = fContexts.count() - 1; i >= 0; --i) {
        Context& context = fContexts[i];
        SkScopeExit restore(nullptr);
        if (context.fTestContext) {
            restore = context.fTestContext->makeCurrentAndAutoRestore();
        }
        if (!context.fGrContext->unique()) {
            context.fGrContext->releaseResourcesAndAbandonContext();
            context.fAbandoned = true;
        }
        context.fGrContext->unref();
        delete context.fTestContext;
    }
    fContexts.reset();
}

void GrContextFactory::abandonContexts() {
    // We must abandon the test contexts in reverse order so that any child context is finished and
    // abandoned before a parent context. This relies on the fact that when we make a new context we
    // append it to the end of fContexts array.
    // TODO: Look into keeping a dependency dag for contexts and deletion order
    for (int i = fContexts.count() - 1; i >= 0; --i) {
        Context& context = fContexts[i];
        if (!context.fAbandoned) {
            if (context.fTestContext) {
                auto restore = context.fTestContext->makeCurrentAndAutoRestore();
                context.fTestContext->testAbandon();
                delete(context.fTestContext);
                context.fTestContext = nullptr;
            }
            context.fGrContext->abandonContext();
            context.fAbandoned = true;
        }
    }
}

void GrContextFactory::releaseResourcesAndAbandonContexts() {
    // We must abandon the test contexts in reverse order so that any child context is finished and
    // abandoned before a parent context. This relies on the fact that when we make a new context we
    // append it to the end of fContexts array.
    // TODO: Look into keeping a dependency dag for contexts and deletion order
    for (int i = fContexts.count() - 1; i >= 0; --i) {
        Context& context = fContexts[i];
        SkScopeExit restore(nullptr);
        if (!context.fAbandoned) {
            if (context.fTestContext) {
                restore = context.fTestContext->makeCurrentAndAutoRestore();
            }
            context.fGrContext->releaseResourcesAndAbandonContext();
            context.fAbandoned = true;
            if (context.fTestContext) {
                delete context.fTestContext;
                context.fTestContext = nullptr;
            }
        }
    }
}

GrContext* GrContextFactory::get(ContextType type, ContextOverrides overrides) {
    return this->getContextInfo(type, overrides).grContext();
}

ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOverrides overrides,
                                                     GrContext* shareContext, uint32_t shareIndex) {
    // (shareIndex != 0) -> (shareContext != nullptr)
    SkASSERT((shareIndex == 0) || (shareContext != nullptr));

    for (int i = 0; i < fContexts.count(); ++i) {
        Context& context = fContexts[i];
        if (context.fType == type &&
            context.fOverrides == overrides &&
            context.fShareContext == shareContext &&
            context.fShareIndex == shareIndex &&
            !context.fAbandoned) {
            context.fTestContext->makeCurrent();
            return ContextInfo(context.fType, context.fTestContext, context.fGrContext,
                               context.fOptions);
        }
    }

    // If we're trying to create a context in a share group, find the master context
    Context* masterContext = nullptr;
    if (shareContext) {
        for (int i = 0; i < fContexts.count(); ++i) {
            if (!fContexts[i].fAbandoned && fContexts[i].fGrContext == shareContext) {
                masterContext = &fContexts[i];
                break;
            }
        }
        SkASSERT(masterContext && masterContext->fType == type);
    }

    std::unique_ptr<TestContext> testCtx;
    GrBackend backend = ContextTypeBackend(type);
    switch (backend) {
        case kOpenGL_GrBackend: {
            GLTestContext* glShareContext = masterContext
                    ? static_cast<GLTestContext*>(masterContext->fTestContext) : nullptr;
            GLTestContext* glCtx;
            switch (type) {
                case kGL_ContextType:
                    glCtx = CreatePlatformGLTestContext(kGL_GrGLStandard, glShareContext);
                    break;
                case kGLES_ContextType:
                    glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard, glShareContext);
                    break;
#if SK_ANGLE
                case kANGLE_D3D9_ES2_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D9, ANGLEContextVersion::kES2,
                                                 glShareContext).release();
                    break;
                case kANGLE_D3D11_ES2_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES2,
                                                 glShareContext).release();
                    break;
                case kANGLE_D3D11_ES3_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES3,
                                                 glShareContext).release();
                    break;
                case kANGLE_GL_ES2_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES2,
                                                 glShareContext).release();
                    break;
                case kANGLE_GL_ES3_ContextType:
                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES3,
                                                 glShareContext).release();
                    break;
#endif
#ifndef SK_NO_COMMAND_BUFFER
                case kCommandBuffer_ContextType:
                    glCtx = CommandBufferGLTestContext::Create(glShareContext);
                    break;
#endif
                case kNullGL_ContextType:
                    glCtx = CreateNullGLTestContext(
                            ContextOverrides::kRequireNVPRSupport & overrides, glShareContext);
                    break;
                case kDebugGL_ContextType:
                    glCtx = CreateDebugGLTestContext(glShareContext);
                    break;
                default:
                    return ContextInfo();
            }
            if (!glCtx) {
                return ContextInfo();
            }
            testCtx.reset(glCtx);
            break;
        }
#ifdef SK_VULKAN
        case kVulkan_GrBackend: {
            VkTestContext* vkSharedContext = masterContext
                    ? static_cast<VkTestContext*>(masterContext->fTestContext) : nullptr;
            SkASSERT(kVulkan_ContextType == type);
            if (ContextOverrides::kRequireNVPRSupport & overrides) {
                return ContextInfo();
            }
            testCtx.reset(CreatePlatformVkTestContext(vkSharedContext));
            if (!testCtx) {
                return ContextInfo();
            }

            // There is some bug (either in Skia or the NV Vulkan driver) where VkDevice
            // destruction will hang occaisonally. For some reason having an existing GL
            // context fixes this.
            if (!fSentinelGLContext) {
                fSentinelGLContext.reset(CreatePlatformGLTestContext(kGL_GrGLStandard));
                if (!fSentinelGLContext) {
                    fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
                }
            }
            break;
        }
#endif
#ifdef SK_METAL
        case kMetal_GrBackend: {
            SkASSERT(!masterContext);
            testCtx.reset(CreatePlatformMtlTestContext(nullptr));
            if (!testCtx) {
                return ContextInfo();
            }
            break;
        }
#endif
        case kMock_GrBackend: {
            TestContext* sharedContext = masterContext ? masterContext->fTestContext : nullptr;
            SkASSERT(kMock_ContextType == type);
            if (ContextOverrides::kRequireNVPRSupport & overrides) {
                return ContextInfo();
            }
            testCtx.reset(CreateMockTestContext(sharedContext));
            if (!testCtx) {
                return ContextInfo();
            }
            break;
        }
        default:
            return ContextInfo();
    }

    SkASSERT(testCtx && testCtx->backend() == backend);
    GrContextOptions grOptions = fGlobalOptions;
    if (ContextOverrides::kDisableNVPR & overrides) {
        grOptions.fSuppressPathRendering = true;
    }
    if (ContextOverrides::kAllowSRGBWithoutDecodeControl & overrides) {
        grOptions.fRequireDecodeDisableForSRGB = false;
    }
    if (ContextOverrides::kAvoidStencilBuffers & overrides) {
        grOptions.fAvoidStencilBuffers = true;
    }
    sk_sp<GrContext> grCtx;
    {
        auto restore = testCtx->makeCurrentAndAutoRestore();
        grCtx = testCtx->makeGrContext(grOptions);
    }
    if (!grCtx.get()) {
        return ContextInfo();
    }
    if (ContextOverrides::kRequireNVPRSupport & overrides) {
        if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) {
            return ContextInfo();
        }
    }
    if (ContextOverrides::kRequireSRGBSupport & overrides) {
        if (!grCtx->caps()->srgbSupport()) {
            return ContextInfo();
        }
    }

    // We must always add new contexts by pushing to the back so that when we delete them we delete
    // them in reverse order in which they were made.
    Context& context = fContexts.push_back();
    context.fBackend = backend;
    context.fTestContext = testCtx.release();
    context.fGrContext = SkRef(grCtx.get());
    context.fType = type;
    context.fOverrides = overrides;
    context.fAbandoned = false;
    context.fShareContext = shareContext;
    context.fShareIndex = shareIndex;
    context.fOptions = grOptions;
    context.fTestContext->makeCurrent();
    return ContextInfo(context.fType, context.fTestContext, context.fGrContext, context.fOptions);
}

ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides overrides) {
    return this->getContextInfoInternal(type, overrides, nullptr, 0);
}

ContextInfo GrContextFactory::getSharedContextInfo(GrContext* shareContext, uint32_t shareIndex) {
    SkASSERT(shareContext);
    for (int i = 0; i < fContexts.count(); ++i) {
        if (!fContexts[i].fAbandoned && fContexts[i].fGrContext == shareContext) {
            return this->getContextInfoInternal(fContexts[i].fType, fContexts[i].fOverrides,
                                                shareContext, shareIndex);
        }
    }

    return ContextInfo();
}

}  // namespace sk_gpu_test
<|endoftext|>


<commit_before>#ifndef GENERIC_ALGORITHM_HPP
# define GENERIC_ALGORITHM_HPP
# pragma once

#include <cstddef>

#include <type_traits>

#include <utility>

#include "meta.hpp"

namespace generic
{

// min, max
template <typename T>
constexpr inline T const& max(T const& a, T const& b) noexcept
{
  return a > b ? a : b;
}

template <typename T>
constexpr inline T const& min(T const& a, T const& b) noexcept
{
  return a < b ? a : b;
}

template <typename T, typename ...A>
constexpr inline typename ::std::enable_if<
  bool(sizeof...(A)) &&
  all_of<
    ::std::is_same<
      typename ::std::decay<T>::type,
      typename ::std::decay<A>::type
    >...
  >{},
  T
>::type
max(T const& a, T const& b, A&& ...args) noexcept
{
  return a > b ?
    max(a, ::std::forward<A>(args)...) :
    max(b, ::std::forward<A>(args)...);
}

template <typename T, typename ...A>
constexpr inline typename ::std::enable_if<
  bool(sizeof...(A)) &&
  all_of<
    ::std::is_same<
      typename ::std::decay<T>::type,
      typename ::std::decay<A>::type
    >...
  >{},
  T
>::type
min(T const& a, T const& b, A&& ...args) noexcept
{
  return a < b ?
    min(a, ::std::forward<A>(args)...) :
    min(b, ::std::forward<A>(args)...);
}

template <typename ...A>
constexpr inline typename ::std::enable_if<
  bool(sizeof...(A)) &&
  all_of<
    ::std::is_same<
      typename ::std::decay<typename front<A...>::type>::type,
      typename ::std::decay<A>::type
    >...
  >{},
  ::std::pair<
    typename ::std::decay<typename front<A...>::type>::type,
    typename ::std::decay<typename front<A...>::type>::type
  >
>::type
minmax(A&& ...args) noexcept
{
  return {
    min(::std::forward<A>(args)...),
    max(::std::forward<A>(args)...)
  };
}

template<typename T, typename U, typename V>
constexpr inline ::std::enable_if_t<
  ::std::is_same<T, U>{} &&
  ::std::is_same<U, V>{},
  T const&
>
clamp(T const& v, U const& lo, V const& hi) noexcept
{
  return v < lo ?
    lo :
    hi < v ?
      hi :
      v;
}

}

#endif // GENERIC_ALGORITHM_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_ALGORITHM_HPP
# define GENERIC_ALGORITHM_HPP
# pragma once

#include <cstddef>

#include <type_traits>

#include <utility>

#include "meta.hpp"

namespace generic
{

// min, max
template <typename T>
constexpr inline T const& max(T const& a, T const& b) noexcept
{
  return a > b ? a : b;
}

template <typename T>
constexpr inline T const& min(T const& a, T const& b) noexcept
{
  return a < b ? a : b;
}

template <typename T, typename ...A>
constexpr inline ::std::enable_if_t<
  bool(sizeof...(A)) &&
  all_of<
    ::std::is_same<
      typename ::std::decay<T>::type,
      typename ::std::decay<A>::type
    >...
  >{},
  T
>
max(T const& a, T const& b, A&& ...args) noexcept
{
  return a > b ?
    max(a, ::std::forward<A>(args)...) :
    max(b, ::std::forward<A>(args)...);
}

template <typename T, typename ...A>
constexpr inline ::std::enable_if_t<
  bool(sizeof...(A)) &&
  all_of<
    ::std::is_same<
      typename ::std::decay<T>::type,
      typename ::std::decay<A>::type
    >...
  >{},
  T
>
min(T const& a, T const& b, A&& ...args) noexcept
{
  return a < b ?
    min(a, ::std::forward<A>(args)...) :
    min(b, ::std::forward<A>(args)...);
}

template <typename ...A>
constexpr inline typename ::std::enable_if_t<
  bool(sizeof...(A)) &&
  all_of<
    ::std::is_same<
      typename ::std::decay<typename front<A...>::type>::type,
      typename ::std::decay<A>::type
    >...
  >{},
  ::std::pair<
    typename ::std::decay<typename front<A...>::type>::type,
    typename ::std::decay<typename front<A...>::type>::type
  >
>
minmax(A&& ...args) noexcept
{
  return {
    min(::std::forward<A>(args)...),
    max(::std::forward<A>(args)...)
  };
}

template<typename T, typename U, typename V>
constexpr inline ::std::enable_if_t<
  ::std::is_same<T, U>{} &&
  ::std::is_same<U, V>{},
  T const&
>
clamp(T const& v, U const& lo, V const& hi) noexcept
{
  return v < lo ?
    lo :
    hi < v ?
      hi :
      v;
}

}

#endif // GENERIC_ALGORITHM_HPP
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "stdafx.h"

// This include needs to be kept in order to make sure the
// auto_ptr<dynamic_context> manages to dealocate the
// dynamic_context object.
#include "context/dynamic_context.h"

#include "runtime/function_item/function_item.h"
#include "runtime/core/fncall_iterator.h"
#include "runtime/base/plan_iterator.h"
#include "runtime/api/plan_iterator_wrapper.h"
#include "runtime/visitors/planiter_visitor.h"

#include "compiler/api/compilercb.h"
#include "compiler/expression/var_expr.h"
#include "compiler/expression/function_item_expr.h"
#include "compiler/expression/expr_manager.h"

#include "functions/signature.h"
#include "functions/udf.h"

#include "store/api/temp_seq.h"

#include "zorbaserialization/serialize_template_types.h"
#include "zorbaserialization/serialize_zorba_types.h"

namespace zorba
{

SERIALIZABLE_CLASS_VERSIONS(DynamicFunctionInfo)

SERIALIZABLE_CLASS_VERSIONS(FunctionItem)

SERIALIZABLE_CLASS_VERSIONS(DynamicFunctionIterator)

/*******************************************************************************

********************************************************************************/
DynamicFunctionInfo::DynamicFunctionInfo(// CompilerCB *ccb,
                                         static_context* closureSctx,
                                         const QueryLoc& loc,
                                         function* func,
                                         store::Item_t qname,
                                         uint32_t arity,
                                         bool isInline,
                                         bool needsContextItem)
  :
  theMustDeleteCCB(false),
  theClosureSctx(closureSctx),
  theLoc(loc),
  theFunction(func),
  theQName(qname),
  theArity(arity),
  theIsInline(isInline),
  theNeedsContextItem(needsContextItem)
{
}

DynamicFunctionInfo::DynamicFunctionInfo(::zorba::serialization::Archiver& ar)
{
}

DynamicFunctionInfo::~DynamicFunctionInfo()
{
  if (theMustDeleteCCB)
    delete theCCB;
}

void DynamicFunctionInfo::serialize(::zorba::serialization::Archiver& ar)
{
  ar & theCCB;
  ar & theMustDeleteCCB;
  ar & theClosureSctx;
  ar & theLoc;
  ar & theFunction;
  ar & theQName;
  ar & theArity;
  ar & theIsInline;
  ar & theNeedsContextItem;

  // These are not serialized
  // ar & theScopedVarsValues;
  // ar & theSubstVarsValues;

  ar & theScopedVarsNames;
  ar & theIsGlobalVar;
  ar & theVarId;

  ar & theScopedVarsIterators;

  if (ar.is_serializing_out())
  {
    uint32_t planStateSize;
    (void)static_cast<user_function*>(theFunction.getp())->getPlan(planStateSize);
  }
}

void DynamicFunctionInfo::add_variable(expr* var, var_expr* substVar, const store::Item_t& name, int isGlobal)
{
  theScopedVarsValues.push_back(var);
  theSubstVarsValues.push_back(substVar);
  theScopedVarsNames.push_back(name);
  theIsGlobalVar.push_back(isGlobal);
  theVarId.push_back(0);
}

/*******************************************************************************

********************************************************************************/
FunctionItem::FunctionItem(::zorba::serialization::Archiver& ar)
  :
  store::Item(store::Item::FUNCTION)
{
}

FunctionItem::FunctionItem(const DynamicFunctionInfo_t& dynamicFunctionInfo,
                           dynamic_context* dctx)
  :
  store::Item(store::Item::FUNCTION),
  theDynamicFunctionInfo(dynamicFunctionInfo),
  theArity(dynamicFunctionInfo->theArity),
  theClosureDctx(dctx)
{
  assert(theDynamicFunctionInfo->theFunction->isUdf());
  theArgumentsValues.resize(theDynamicFunctionInfo->theArity);
}

void FunctionItem::serialize(::zorba::serialization::Archiver& ar)
{
  ar & theDynamicFunctionInfo;
  ar & theArity;
  ar & theArgumentsValues;
}

const store::Item_t FunctionItem::getFunctionName() const
{
  return theDynamicFunctionInfo->theQName;
}

uint32_t FunctionItem::getArity() const
{
  return theArity;
}

uint32_t FunctionItem::getStartArity() const
{
  return theDynamicFunctionInfo->theArity;
}

const signature& FunctionItem::getSignature() const
{
  return theDynamicFunctionInfo->theFunction->getSignature();
}

const std::vector<PlanIter_t>& FunctionItem::getArgumentsValues() const
{
  return theArgumentsValues;
}

bool FunctionItem::isArgumentApplied(unsigned int pos) const
{
  assert(pos < theArgumentsValues.size());
  return (theArgumentsValues[pos].getp() != NULL);
}

void FunctionItem::setArgumentValue(unsigned int pos, const PlanIter_t& value)
{
  theArity--;

  // find the pos-th NULL value and fill it
  for (unsigned int i=0; i<theArgumentsValues.size(); i++)
    if (theArgumentsValues[i] == NULL)
    {
      if (pos == 0)
      {
        theArgumentsValues[i] = value;
        return;
      }
      else
        pos--;
    }

  assert(false);
}

PlanIter_t FunctionItem::getImplementation(const std::vector<PlanIter_t>& dynChildren, CompilerCB* ccb)
{
  std::vector<PlanIter_t> args;
  args.resize(theArgumentsValues.size());

  std::vector<PlanIter_t>::iterator argsIte = args.begin();
  std::vector<PlanIter_t>::iterator ite = theArgumentsValues.begin();
  std::vector<PlanIter_t>::const_iterator ite2 = dynChildren.begin();
  ++ite2; // skip the first child because it's the function item

  for( ; argsIte != args.end(); ++argsIte, ++ite)
  {
    if (*ite != NULL)
    {
      *argsIte = *ite;
      static_cast<PlanStateIteratorWrapper*>(ite->getp())->reset();
    }
    else
    {
      *argsIte = *ite2;
      ++ite2;
    }
  }

//  if (theDynamicFunctionInfo->theCCB != NULL)
//    ccb = theDynamicFunctionInfo->theCCB;

  std::cerr << "--> FunctionItem::getImplementation() using CompilerCB: " << ccb << std::endl;

  expr* dummy = ccb->theEM->create_function_item_expr(NULL, NULL, theDynamicFunctionInfo->theLoc, NULL, false, false);

  PlanIter_t udfCallIterator =
      theDynamicFunctionInfo->theFunction->codegen(ccb,
                                                   theDynamicFunctionInfo->theClosureSctx,
                                                   theDynamicFunctionInfo->theLoc,
                                                   args,
                                                   *dummy);

  UDFunctionCallIterator* udfIter = static_cast<UDFunctionCallIterator*>(udfCallIterator.getp());
  udfIter->setDynamic();
  udfIter->setFunctionItem(this);
  return udfCallIterator;
}

zstring FunctionItem::show() const
{
  std::ostringstream lRes;
  lRes << getFunctionName()->getStringValue();
  if (!isInline())
    lRes << "#" << getArity() << " (" << theDynamicFunctionInfo->theLoc << ")";
  return lRes.str();
}

/*******************************************************************************

********************************************************************************/
void DynamicFunctionIterator::serialize(::zorba::serialization::Archiver& ar)
{
  serialize_baseclass(ar, (NaryBaseIterator<DynamicFunctionIterator, PlanIteratorState>*)this);
  ar & theDynamicFunctionInfo;
}

/*******************************************************************************

********************************************************************************/
DynamicFunctionIterator::DynamicFunctionIterator(
      static_context* sctx,
      const QueryLoc& loc,
      DynamicFunctionInfo* fnInfo)
  :
  NaryBaseIterator<DynamicFunctionIterator, PlanIteratorState>(sctx, loc, fnInfo->theScopedVarsIterators),
  theDynamicFunctionInfo(fnInfo)
{
}

DynamicFunctionIterator::~DynamicFunctionIterator()
{
}

bool DynamicFunctionIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  PlanIteratorState* state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  // This portion is taken from the eval iterator
  {
    // Create the dynamic context for the eval query
    std::auto_ptr<dynamic_context> evalDctx;
    evalDctx.reset(new dynamic_context(planState.theGlobalDynCtx));

    // Import the outer environment.
    importOuterEnv(planState, theDynamicFunctionInfo->theCCB, theDynamicFunctionInfo->theClosureSctx, evalDctx.get());

    result = new FunctionItem(theDynamicFunctionInfo, evalDctx.release());
  }

  STACK_PUSH ( result != NULL, state );
  STACK_END (state);
}

/********************************************************************************

  These functions are copied from the EvalIterator -- maybe they could be shared.

********************************************************************************/

/****************************************************************************//**
  This method imports a static and dynamic environment from the quter query into
  the eval query. In particular:

  (a) imports into the importSctx all the outer vars of the eval query
  (b) imports into the importSctx all the ns bindings of the outer query at the
      place where the eval call appears at
  (c) Copies all the var values from the outer-query global dctx into the eval-
      query dctx.
  (d) For each of the non-global outer vars, places its value into the eval dctx.
      The var value is represented as a PlanIteratorWrapper over the subplan that
      evaluates the domain expr of the eval var.
  (e) Computes the max var id of all the var values set in steps (c) and (d).
      This max varid will be passed to the compiler of the eval query so that
      the varids that will be generated for the eval query will not conflict with
      the varids of the outer vars and the outer-query global vars.
********************************************************************************/
void DynamicFunctionIterator::importOuterEnv(
    PlanState& planState,
    CompilerCB* evalCCB,
    static_context* importSctx,
    dynamic_context* evalDctx) const
{
  ulong maxOuterVarId = 1;

  // Copy all the var values from the outer-query global dctx into the eval-query
  // dctx. This is need to handle the following scenario: (a) $x is an outer-query
  // global var that is not among the outer vars of the eval query (because $x was
  // hidden at the point where the eval call is made inside the outer query), and
  // (b) foo() is a function decalred in the outer query that accessed $x and is
  // invoked by the eval query. The copying must be done using the same positions
  // (i.e., var ids) in the eval dctx as in the outer-query dctx.

  dynamic_context* outerDctx = evalDctx->getParent();

  const std::vector<dynamic_context::VarValue>& outerGlobalValues =
  outerDctx->get_variables();

  csize numOuterGlobalVars = outerGlobalValues.size();

  for (csize i = 0; i < numOuterGlobalVars; ++i)
  {
    const dynamic_context::VarValue& outerVar = outerGlobalValues[i];

    if (!outerVar.isSet())
      continue;

    ulong outerVarId = static_cast<ulong>(i);

    if (outerVarId > maxOuterVarId)
      maxOuterVarId = outerVarId;

    store::Item_t itemValue;
    store::TempSeq_t seqValue;

    if (outerVar.hasItemValue())
    {
      store::Item_t value = outerVar.theValue.item;
      evalDctx->add_variable(outerVarId, value);
    }
    else
    {
      store::Iterator_t iteValue = outerVar.theValue.temp_seq->getIterator();
      evalDctx->add_variable(outerVarId, iteValue);
    }
  }

  ++maxOuterVarId;

  // Import the outer vars. Specifically, for each outer var:
  // (a) create a declaration inside the importSctx.
  // (b) Set its var id
  // (c) If it is not a global one, set its value within the eval dctx.

  csize curChild = -1;

  csize numOuterVars = theDynamicFunctionInfo->theScopedVarsNames.size();

  for (csize i = 0; i < numOuterVars; ++i)
  {
    if (!theDynamicFunctionInfo->theIsGlobalVar[i])
    {
      ++curChild;

      store::Iterator_t iter = new PlanIteratorWrapper(theChildren[curChild], planState);

      evalDctx->add_variable(theDynamicFunctionInfo->theVarId[i], iter);
    }
  }

  // Import the outer-query ns bindings
  store::NsBindings::const_iterator ite = theDynamicFunctionInfo->theLocalBindings.begin();
  store::NsBindings::const_iterator end = theDynamicFunctionInfo->theLocalBindings.end();

  for (; ite != end; ++ite)
  {
    importSctx->bind_ns(ite->first, ite->second, loc);
  }
}

/****************************************************************************//**

********************************************************************************/
void DynamicFunctionIterator::setExternalVariables(
    CompilerCB* ccb,
    static_context* importSctx,
    dynamic_context* evalDctx) const
{
  std::vector<VarInfo*> innerVars;

  CompilerCB::SctxMap::const_iterator sctxIte = ccb->theSctxMap.begin();
  CompilerCB::SctxMap::const_iterator sctxEnd = ccb->theSctxMap.end();

  for (; sctxIte != sctxEnd; ++sctxIte)
  {
    sctxIte->second->getVariables(innerVars, true, false, true);
  }

  FOR_EACH(std::vector<VarInfo*>, ite, innerVars)
  {
    VarInfo* innerVar = (*ite);

    if (!innerVar->isExternal())
      continue;

    ulong innerVarId = innerVar->getId();

    VarInfo* outerVar = importSctx->lookup_var(innerVar->getName());

    if (!outerVar)
      continue;

    store::Item_t itemValue;
    store::TempSeq_t seqValue;

    evalDctx->get_variable(outerVar->getId(),
                           outerVar->getName(),
                           loc,
                           itemValue,
                           seqValue);

    if (itemValue != NULL)
    {
      evalDctx->add_variable(innerVarId, itemValue);
    }
    else
    {
      store::Iterator_t iteValue = seqValue->getIterator();
      evalDctx->add_variable(innerVarId, iteValue);
    }
  }
}

NARY_ACCEPT(DynamicFunctionIterator)

} //namespace zorba
/* vim:set et sw=2 ts=2: */
<commit_msg>Removed a debug message<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "stdafx.h"

// This include needs to be kept in order to make sure the
// auto_ptr<dynamic_context> manages to dealocate the
// dynamic_context object.
#include "context/dynamic_context.h"

#include "runtime/function_item/function_item.h"
#include "runtime/core/fncall_iterator.h"
#include "runtime/base/plan_iterator.h"
#include "runtime/api/plan_iterator_wrapper.h"
#include "runtime/visitors/planiter_visitor.h"

#include "compiler/api/compilercb.h"
#include "compiler/expression/var_expr.h"
#include "compiler/expression/function_item_expr.h"
#include "compiler/expression/expr_manager.h"

#include "functions/signature.h"
#include "functions/udf.h"

#include "store/api/temp_seq.h"

#include "zorbaserialization/serialize_template_types.h"
#include "zorbaserialization/serialize_zorba_types.h"

namespace zorba
{

SERIALIZABLE_CLASS_VERSIONS(DynamicFunctionInfo)

SERIALIZABLE_CLASS_VERSIONS(FunctionItem)

SERIALIZABLE_CLASS_VERSIONS(DynamicFunctionIterator)

/*******************************************************************************

********************************************************************************/
DynamicFunctionInfo::DynamicFunctionInfo(// CompilerCB *ccb,
                                         static_context* closureSctx,
                                         const QueryLoc& loc,
                                         function* func,
                                         store::Item_t qname,
                                         uint32_t arity,
                                         bool isInline,
                                         bool needsContextItem)
  :
  theMustDeleteCCB(false),
  theClosureSctx(closureSctx),
  theLoc(loc),
  theFunction(func),
  theQName(qname),
  theArity(arity),
  theIsInline(isInline),
  theNeedsContextItem(needsContextItem)
{
}

DynamicFunctionInfo::DynamicFunctionInfo(::zorba::serialization::Archiver& ar)
{
}

DynamicFunctionInfo::~DynamicFunctionInfo()
{
  if (theMustDeleteCCB)
    delete theCCB;
}

void DynamicFunctionInfo::serialize(::zorba::serialization::Archiver& ar)
{
  ar & theCCB;
  ar & theMustDeleteCCB;
  ar & theClosureSctx;
  ar & theLoc;
  ar & theFunction;
  ar & theQName;
  ar & theArity;
  ar & theIsInline;
  ar & theNeedsContextItem;

  // These are not serialized
  // ar & theScopedVarsValues;
  // ar & theSubstVarsValues;

  ar & theScopedVarsNames;
  ar & theIsGlobalVar;
  ar & theVarId;

  ar & theScopedVarsIterators;

  if (ar.is_serializing_out())
  {
    uint32_t planStateSize;
    (void)static_cast<user_function*>(theFunction.getp())->getPlan(planStateSize);
  }
}

void DynamicFunctionInfo::add_variable(expr* var, var_expr* substVar, const store::Item_t& name, int isGlobal)
{
  theScopedVarsValues.push_back(var);
  theSubstVarsValues.push_back(substVar);
  theScopedVarsNames.push_back(name);
  theIsGlobalVar.push_back(isGlobal);
  theVarId.push_back(0);
}

/*******************************************************************************

********************************************************************************/
FunctionItem::FunctionItem(::zorba::serialization::Archiver& ar)
  :
  store::Item(store::Item::FUNCTION)
{
}

FunctionItem::FunctionItem(const DynamicFunctionInfo_t& dynamicFunctionInfo,
                           dynamic_context* dctx)
  :
  store::Item(store::Item::FUNCTION),
  theDynamicFunctionInfo(dynamicFunctionInfo),
  theArity(dynamicFunctionInfo->theArity),
  theClosureDctx(dctx)
{
  assert(theDynamicFunctionInfo->theFunction->isUdf());
  theArgumentsValues.resize(theDynamicFunctionInfo->theArity);
}

void FunctionItem::serialize(::zorba::serialization::Archiver& ar)
{
  ar & theDynamicFunctionInfo;
  ar & theArity;
  ar & theArgumentsValues;
}

const store::Item_t FunctionItem::getFunctionName() const
{
  return theDynamicFunctionInfo->theQName;
}

uint32_t FunctionItem::getArity() const
{
  return theArity;
}

uint32_t FunctionItem::getStartArity() const
{
  return theDynamicFunctionInfo->theArity;
}

const signature& FunctionItem::getSignature() const
{
  return theDynamicFunctionInfo->theFunction->getSignature();
}

const std::vector<PlanIter_t>& FunctionItem::getArgumentsValues() const
{
  return theArgumentsValues;
}

bool FunctionItem::isArgumentApplied(unsigned int pos) const
{
  assert(pos < theArgumentsValues.size());
  return (theArgumentsValues[pos].getp() != NULL);
}

void FunctionItem::setArgumentValue(unsigned int pos, const PlanIter_t& value)
{
  theArity--;

  // find the pos-th NULL value and fill it
  for (unsigned int i=0; i<theArgumentsValues.size(); i++)
    if (theArgumentsValues[i] == NULL)
    {
      if (pos == 0)
      {
        theArgumentsValues[i] = value;
        return;
      }
      else
        pos--;
    }

  assert(false);
}

PlanIter_t FunctionItem::getImplementation(const std::vector<PlanIter_t>& dynChildren, CompilerCB* ccb)
{
  std::vector<PlanIter_t> args;
  args.resize(theArgumentsValues.size());

  std::vector<PlanIter_t>::iterator argsIte = args.begin();
  std::vector<PlanIter_t>::iterator ite = theArgumentsValues.begin();
  std::vector<PlanIter_t>::const_iterator ite2 = dynChildren.begin();
  ++ite2; // skip the first child because it's the function item

  for( ; argsIte != args.end(); ++argsIte, ++ite)
  {
    if (*ite != NULL)
    {
      *argsIte = *ite;
      static_cast<PlanStateIteratorWrapper*>(ite->getp())->reset();
    }
    else
    {
      *argsIte = *ite2;
      ++ite2;
    }
  }

//  if (theDynamicFunctionInfo->theCCB != NULL)
//    ccb = theDynamicFunctionInfo->theCCB;

  expr* dummy = ccb->theEM->create_function_item_expr(NULL, NULL, theDynamicFunctionInfo->theLoc, NULL, false, false);

  PlanIter_t udfCallIterator =
      theDynamicFunctionInfo->theFunction->codegen(ccb,
                                                   theDynamicFunctionInfo->theClosureSctx,
                                                   theDynamicFunctionInfo->theLoc,
                                                   args,
                                                   *dummy);

  UDFunctionCallIterator* udfIter = static_cast<UDFunctionCallIterator*>(udfCallIterator.getp());
  udfIter->setDynamic();
  udfIter->setFunctionItem(this);
  return udfCallIterator;
}

zstring FunctionItem::show() const
{
  std::ostringstream lRes;
  lRes << getFunctionName()->getStringValue();
  if (!isInline())
    lRes << "#" << getArity() << " (" << theDynamicFunctionInfo->theLoc << ")";
  return lRes.str();
}

/*******************************************************************************

********************************************************************************/
void DynamicFunctionIterator::serialize(::zorba::serialization::Archiver& ar)
{
  serialize_baseclass(ar, (NaryBaseIterator<DynamicFunctionIterator, PlanIteratorState>*)this);
  ar & theDynamicFunctionInfo;
}

/*******************************************************************************

********************************************************************************/
DynamicFunctionIterator::DynamicFunctionIterator(
      static_context* sctx,
      const QueryLoc& loc,
      DynamicFunctionInfo* fnInfo)
  :
  NaryBaseIterator<DynamicFunctionIterator, PlanIteratorState>(sctx, loc, fnInfo->theScopedVarsIterators),
  theDynamicFunctionInfo(fnInfo)
{
}

DynamicFunctionIterator::~DynamicFunctionIterator()
{
}

bool DynamicFunctionIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  PlanIteratorState* state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  // This portion is taken from the eval iterator
  {
    // Create the dynamic context for the eval query
    std::auto_ptr<dynamic_context> evalDctx;
    evalDctx.reset(new dynamic_context(planState.theGlobalDynCtx));

    // Import the outer environment.
    importOuterEnv(planState, theDynamicFunctionInfo->theCCB, theDynamicFunctionInfo->theClosureSctx, evalDctx.get());

    result = new FunctionItem(theDynamicFunctionInfo, evalDctx.release());
  }

  STACK_PUSH ( result != NULL, state );
  STACK_END (state);
}

/********************************************************************************

  These functions are copied from the EvalIterator -- maybe they could be shared.

********************************************************************************/

/****************************************************************************//**
  This method imports a static and dynamic environment from the quter query into
  the eval query. In particular:

  (a) imports into the importSctx all the outer vars of the eval query
  (b) imports into the importSctx all the ns bindings of the outer query at the
      place where the eval call appears at
  (c) Copies all the var values from the outer-query global dctx into the eval-
      query dctx.
  (d) For each of the non-global outer vars, places its value into the eval dctx.
      The var value is represented as a PlanIteratorWrapper over the subplan that
      evaluates the domain expr of the eval var.
  (e) Computes the max var id of all the var values set in steps (c) and (d).
      This max varid will be passed to the compiler of the eval query so that
      the varids that will be generated for the eval query will not conflict with
      the varids of the outer vars and the outer-query global vars.
********************************************************************************/
void DynamicFunctionIterator::importOuterEnv(
    PlanState& planState,
    CompilerCB* evalCCB,
    static_context* importSctx,
    dynamic_context* evalDctx) const
{
  ulong maxOuterVarId = 1;

  // Copy all the var values from the outer-query global dctx into the eval-query
  // dctx. This is need to handle the following scenario: (a) $x is an outer-query
  // global var that is not among the outer vars of the eval query (because $x was
  // hidden at the point where the eval call is made inside the outer query), and
  // (b) foo() is a function decalred in the outer query that accessed $x and is
  // invoked by the eval query. The copying must be done using the same positions
  // (i.e., var ids) in the eval dctx as in the outer-query dctx.

  dynamic_context* outerDctx = evalDctx->getParent();

  const std::vector<dynamic_context::VarValue>& outerGlobalValues =
  outerDctx->get_variables();

  csize numOuterGlobalVars = outerGlobalValues.size();

  for (csize i = 0; i < numOuterGlobalVars; ++i)
  {
    const dynamic_context::VarValue& outerVar = outerGlobalValues[i];

    if (!outerVar.isSet())
      continue;

    ulong outerVarId = static_cast<ulong>(i);

    if (outerVarId > maxOuterVarId)
      maxOuterVarId = outerVarId;

    store::Item_t itemValue;
    store::TempSeq_t seqValue;

    if (outerVar.hasItemValue())
    {
      store::Item_t value = outerVar.theValue.item;
      evalDctx->add_variable(outerVarId, value);
    }
    else
    {
      store::Iterator_t iteValue = outerVar.theValue.temp_seq->getIterator();
      evalDctx->add_variable(outerVarId, iteValue);
    }
  }

  ++maxOuterVarId;

  // Import the outer vars. Specifically, for each outer var:
  // (a) create a declaration inside the importSctx.
  // (b) Set its var id
  // (c) If it is not a global one, set its value within the eval dctx.

  csize curChild = -1;

  csize numOuterVars = theDynamicFunctionInfo->theScopedVarsNames.size();

  for (csize i = 0; i < numOuterVars; ++i)
  {
    if (!theDynamicFunctionInfo->theIsGlobalVar[i])
    {
      ++curChild;

      store::Iterator_t iter = new PlanIteratorWrapper(theChildren[curChild], planState);

      evalDctx->add_variable(theDynamicFunctionInfo->theVarId[i], iter);
    }
  }

  // Import the outer-query ns bindings
  store::NsBindings::const_iterator ite = theDynamicFunctionInfo->theLocalBindings.begin();
  store::NsBindings::const_iterator end = theDynamicFunctionInfo->theLocalBindings.end();

  for (; ite != end; ++ite)
  {
    importSctx->bind_ns(ite->first, ite->second, loc);
  }
}

/****************************************************************************//**

********************************************************************************/
void DynamicFunctionIterator::setExternalVariables(
    CompilerCB* ccb,
    static_context* importSctx,
    dynamic_context* evalDctx) const
{
  std::vector<VarInfo*> innerVars;

  CompilerCB::SctxMap::const_iterator sctxIte = ccb->theSctxMap.begin();
  CompilerCB::SctxMap::const_iterator sctxEnd = ccb->theSctxMap.end();

  for (; sctxIte != sctxEnd; ++sctxIte)
  {
    sctxIte->second->getVariables(innerVars, true, false, true);
  }

  FOR_EACH(std::vector<VarInfo*>, ite, innerVars)
  {
    VarInfo* innerVar = (*ite);

    if (!innerVar->isExternal())
      continue;

    ulong innerVarId = innerVar->getId();

    VarInfo* outerVar = importSctx->lookup_var(innerVar->getName());

    if (!outerVar)
      continue;

    store::Item_t itemValue;
    store::TempSeq_t seqValue;

    evalDctx->get_variable(outerVar->getId(),
                           outerVar->getName(),
                           loc,
                           itemValue,
                           seqValue);

    if (itemValue != NULL)
    {
      evalDctx->add_variable(innerVarId, itemValue);
    }
    else
    {
      store::Iterator_t iteValue = seqValue->getIterator();
      evalDctx->add_variable(innerVarId, iteValue);
    }
  }
}

NARY_ACCEPT(DynamicFunctionIterator)

} //namespace zorba
/* vim:set et sw=2 ts=2: */
<|endoftext|>


<commit_before>#include <memory.h>

#include "vtrc-hash-iface.h"
#include "hash/sha2-traits.h"

namespace vtrc { namespace common {  namespace hash {

    namespace {

        template <typename HashTraits>
        struct hasher_sha: public hash_iface {

            size_t hash_size( ) const
            {
                return HashTraits::digest_length;
            }

            std::string get_data_hash(const void *data,
                                      size_t      length ) const
            {
                typename HashTraits::context_type context;
                HashTraits::init( &context );
                HashTraits::update( &context,
                    reinterpret_cast<const vtrc::uint8_t *>(data), length );

                return HashTraits::fin( &context );
            }

            void get_data_hash(const void *data, size_t length,
                                     void *result_hash ) const
            {
                typename HashTraits::context_type context;
                HashTraits::init( &context );
                HashTraits::update( &context,
                    reinterpret_cast< const u_int8_t * >(data), length );

                HashTraits::fin( &context,
                                reinterpret_cast<vtrc::uint8_t *>(result_hash));
            }

            bool check_data_hash( const void *  data  ,
                                  size_t        length,
                                  const void *  hash  ) const
            {
                std::string h = get_data_hash( data, length );
                return memcmp( h.c_str( ), hash,
                               HashTraits::digest_length ) == 0;
            }

        };
    }

    namespace sha2 {
        hash_iface *create256( )
        {
            return new hasher_sha<vtrc::hash::hash_SHA256_traits>;
        }

        hash_iface *create348( )
        {
            return new hasher_sha<vtrc::hash::hash_SHA384_traits>;
        }

        hash_iface *create512( )
        {
            return new hasher_sha<vtrc::hash::hash_SHA512_traits>;
        }
    }

}}}
<commit_msg>hash finish->fin<commit_after>#include <memory.h>

#include "vtrc-hash-iface.h"
#include "hash/sha2-traits.h"

namespace vtrc { namespace common {  namespace hash {

    namespace {

        template <typename HashTraits>
        struct hasher_sha: public hash_iface {

            size_t hash_size( ) const
            {
                return HashTraits::digest_length;
            }

            std::string get_data_hash(const void *data,
                                      size_t      length ) const
            {
                typename HashTraits::context_type context;
                HashTraits::init( &context );
                HashTraits::update( &context,
                    reinterpret_cast<const vtrc::uint8_t *>(data), length );

                return HashTraits::fin( &context );
            }

            void get_data_hash(const void *data, size_t length,
                                     void *result_hash ) const
            {
                typename HashTraits::context_type context;
                HashTraits::init( &context );
                HashTraits::update( &context,
                    reinterpret_cast<const vtrc::uint8_t *>(data), length );

                HashTraits::fin( &context,
                                reinterpret_cast<vtrc::uint8_t *>(result_hash));
            }

            bool check_data_hash( const void *  data  ,
                                  size_t        length,
                                  const void *  hash  ) const
            {
                std::string h = get_data_hash( data, length );
                return memcmp( h.c_str( ), hash,
                               HashTraits::digest_length ) == 0;
            }

        };
    }

    namespace sha2 {
        hash_iface *create256( )
        {
            return new hasher_sha<vtrc::hash::hash_SHA256_traits>;
        }

        hash_iface *create348( )
        {
            return new hasher_sha<vtrc::hash::hash_SHA384_traits>;
        }

        hash_iface *create512( )
        {
            return new hasher_sha<vtrc::hash::hash_SHA512_traits>;
        }
    }

}}}
<|endoftext|>


<commit_before>#include "vtrc-pool-pair.h"

#include "vtrc-thread.h"
#include "vtrc-mutex-typedefs.h"

//#include "boost/asio.hpp"

namespace vtrc { namespace common {

    namespace basio = boost::asio;

    struct pool_pair::impl {

        thread_pool *genegal_;
        thread_pool *rpc_;
        const bool   same_;

        impl( unsigned thread_count )
            :genegal_(new thread_pool(thread_count ? thread_count : 1))
            ,rpc_(genegal_)
            ,same_(true)
        {

        }

        impl( unsigned thread_count, unsigned rpc_thread_count )
            :genegal_(new thread_pool(thread_count ? thread_count : 1))
            ,rpc_(new thread_pool(rpc_thread_count ? rpc_thread_count : 1))
            ,same_(false)
        {

        }

        ~impl( )
        {
            stop_all( );
            join_all( );

            delete genegal_;
            if( !same_ ) delete rpc_;
        }

        void stop_all( )
        {
            genegal_->stop( );
            if( !same_ ) rpc_->stop( );
        }

        void join_all( )
        {
            genegal_->join_all( );
            if(!same_) rpc_->join_all( );
        }

    };

    pool_pair::pool_pair( unsigned thread_count )
        :impl_(new impl(thread_count))
    {}

    pool_pair::pool_pair( unsigned thread_count, unsigned rpc_thread_count )
        :impl_(new impl(thread_count, rpc_thread_count))
    {}

    pool_pair::~pool_pair( )
    {
        delete impl_;
    }

    boost::asio::io_service &pool_pair::get_io_service( )
    {
        return impl_->genegal_->get_io_service( );
    }

    const boost::asio::io_service &pool_pair::get_io_service( ) const
    {
        return impl_->genegal_->get_io_service( );
    }

    boost::asio::io_service &pool_pair::get_rpc_service( )
    {
        return impl_->rpc_->get_io_service( );
    }

    const boost::asio::io_service &pool_pair::get_rpc_service( ) const
    {
        return impl_->rpc_->get_io_service( );
    }

    thread_pool &pool_pair::get_io_pool( )
    {
        return *impl_->genegal_;
    }

    const thread_pool &pool_pair::get_io_pool( ) const
    {
        return *impl_->genegal_;
    }

    thread_pool &pool_pair::get_rpc_pool( )
    {
        return *impl_->rpc_;
    }

    const thread_pool &pool_pair::get_rpc_pool( ) const
    {
        return *impl_->rpc_;
    }

    void pool_pair::stop_all( )
    {
        impl_->stop_all( );
    }

    void pool_pair::join_all( )
    {
        impl_->join_all( );
    }

}}

<commit_msg>proto<commit_after>#include "vtrc-pool-pair.h"

#include "vtrc-thread.h"
#include "vtrc-mutex-typedefs.h"

//#include "boost/asio.hpp"

namespace vtrc { namespace common {

    namespace basio = boost::asio;

    struct pool_pair::impl {

        thread_pool *genegal_;
        thread_pool *rpc_;
        const bool   same_;

        impl( unsigned thread_count )
            :genegal_(new thread_pool(thread_count))
            ,rpc_(genegal_)
            ,same_(true)
        {

        }

        impl( unsigned thread_count, unsigned rpc_thread_count )
            :genegal_(new thread_pool(thread_count))
            ,rpc_(new thread_pool(rpc_thread_count))
            ,same_(false)
        {

        }

        ~impl( )
        {
            stop_all( );
            join_all( );

            delete genegal_;
            if( !same_ ) delete rpc_;
        }

        void stop_all( )
        {
            genegal_->stop( );
            if( !same_ ) rpc_->stop( );
        }

        void join_all( )
        {
            genegal_->join_all( );
            if(!same_) rpc_->join_all( );
        }

    };

    pool_pair::pool_pair( unsigned thread_count )
        :impl_(new impl(thread_count))
    {}

    pool_pair::pool_pair( unsigned thread_count, unsigned rpc_thread_count )
        :impl_(new impl(thread_count, rpc_thread_count))
    {}

    pool_pair::~pool_pair( )
    {
        delete impl_;
    }

    boost::asio::io_service &pool_pair::get_io_service( )
    {
        return impl_->genegal_->get_io_service( );
    }

    const boost::asio::io_service &pool_pair::get_io_service( ) const
    {
        return impl_->genegal_->get_io_service( );
    }

    boost::asio::io_service &pool_pair::get_rpc_service( )
    {
        return impl_->rpc_->get_io_service( );
    }

    const boost::asio::io_service &pool_pair::get_rpc_service( ) const
    {
        return impl_->rpc_->get_io_service( );
    }

    thread_pool &pool_pair::get_io_pool( )
    {
        return *impl_->genegal_;
    }

    const thread_pool &pool_pair::get_io_pool( ) const
    {
        return *impl_->genegal_;
    }

    thread_pool &pool_pair::get_rpc_pool( )
    {
        return *impl_->rpc_;
    }

    const thread_pool &pool_pair::get_rpc_pool( ) const
    {
        return *impl_->rpc_;
    }

    void pool_pair::stop_all( )
    {
        impl_->stop_all( );
    }

    void pool_pair::join_all( )
    {
        impl_->join_all( );
    }

}}

<|endoftext|>


<commit_before>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

namespace kurento
{

std::string generateUUID ();

}
<commit_msg>UUIDGenerator: Set macros to prevent multi-include dependancies<commit_after>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#ifndef __UUID_GENERATOR_HPP__
#define __UUID_GENERATOR_HPP__

namespace kurento
{

std::string generateUUID ();

}

#endif /* __UUID_GENERATOR_HPP__ */
<|endoftext|>


<commit_before>/**
* \file      main.cc
* \brief     Program for giving an indication when a rfid card has been detected, a database connection has been made and a string has been encrypted
* \author    Tim IJntema, Stefan de Beer, Arco Gelderblom, Rik Honcoop, Koen de Groot
* \copyright Copyright (c) 2017, The R2D2 Team
* \license   See LICENSE
*/

#include "mysql.hh"
#include "mfrc522.hh"
#include "led-controller.hh"
#include "matrix-keypad.hh"
#include "config-file-parser.hh"

#include <wiringPi.h>
#include <wiringPiSPI.h>

#include <iostream>

struct MFAuthentData {
    uint8_t command_code;
    uint8_t blockAddress;
    uint8_t sectorKey[5];
    uint8_t serialNumber[4];
};

int main(int argc, char **argv) {
    try {
        std::string ip;
        std::string username;
        std::string password;
        int encryptionKey;

        ConfigFileParser factory("database-config.txt");
        factory.loadDatabaseSettings(ip, username, password);

        MySql connection;

        connection.connectTo(ip, username, password);
        connection.selectDatabase("R2D2");

        std::cout << "Made connection to the database\n";
        wiringPiSetup();
        wiringPiSPISetup(0, 10000000);//max speed for mfrc522 is 10Mhz
        Mfrc522 rfid;
        rfid.init();

        //Keypad pinSetup
        const int keypadRow[] = {4, 1, 16, 15};
        const int keypadColumn[] = {2, 7, 9, 8};

        //Keypad objects
        MatrixKeypad keypad(keypadRow, keypadColumn, 4);
        char c;

        LedController led(0);

        while (true) {
            std::cout << "\n\nWaiting for rfid tag: \n";

            while (!rfid.isTagPresent()) {
            }
            MFAuthentData x;
            uint8_t receiveData[64];
            rfid.communicateWithTag(Mfrc522::mfrc522Commands::receive,
                                    nullptr,
                                    0,
                                    receiveData;
                                    64*8);
//            rfid.communicateWithTag(Mfrc522::mfrc522Commands::mfAuthent, nullptr, 0, nullptr, 0);

            std::cout << "Hello tag\n";
            std::cout << "Your id = ";
            for(size_t i = 0; i < 4; i++){
                std::cout << std::hex << receiveData[0];
            }
            std::cout << "\n";

            std::cout << "Waiting for key press\n";
            while ((c = keypad.getKey()) == 'h') {
                delay(100);
            }

            //c = keypad.getKey();
            std::cout << c << " key has been pressed\n";

            connection.executeQuery("SELECT * FROM RFID");

            std::cout << "Database information: "
                      << connection.getPreviousResponseColumn("CARD_ID")
                      << '\n';

            std::cout << "String before encryption: R2D2 project\n";
            std::cout << "String after encryption: "
                      << '\n';

            led.blinkLed(1000);
        }
    } catch (const std::string &error) {
        std::cerr << error << '\n';
        exit(EXIT_FAILURE);
    } catch (...) {
        std::cerr << "Something went wrong\n";
        exit(EXIT_FAILURE);
    }
    return 0;
}

<commit_msg>[RFID-02] semicolon to comma<commit_after>/**
* \file      main.cc
* \brief     Program for giving an indication when a rfid card has been detected, a database connection has been made and a string has been encrypted
* \author    Tim IJntema, Stefan de Beer, Arco Gelderblom, Rik Honcoop, Koen de Groot
* \copyright Copyright (c) 2017, The R2D2 Team
* \license   See LICENSE
*/

#include "mysql.hh"
#include "mfrc522.hh"
#include "led-controller.hh"
#include "matrix-keypad.hh"
#include "config-file-parser.hh"

#include <wiringPi.h>
#include <wiringPiSPI.h>

#include <iostream>

struct MFAuthentData {
    uint8_t command_code;
    uint8_t blockAddress;
    uint8_t sectorKey[5];
    uint8_t serialNumber[4];
};

int main(int argc, char **argv) {
    try {
        std::string ip;
        std::string username;
        std::string password;
        int encryptionKey;

        ConfigFileParser factory("database-config.txt");
        factory.loadDatabaseSettings(ip, username, password);

        MySql connection;

        connection.connectTo(ip, username, password);
        connection.selectDatabase("R2D2");

        std::cout << "Made connection to the database\n";
        wiringPiSetup();
        wiringPiSPISetup(0, 10000000);//max speed for mfrc522 is 10Mhz
        Mfrc522 rfid;
        rfid.init();

        //Keypad pinSetup
        const int keypadRow[] = {4, 1, 16, 15};
        const int keypadColumn[] = {2, 7, 9, 8};

        //Keypad objects
        MatrixKeypad keypad(keypadRow, keypadColumn, 4);
        char c;

        LedController led(0);

        while (true) {
            std::cout << "\n\nWaiting for rfid tag: \n";

            while (!rfid.isTagPresent()) {
            }
            MFAuthentData x;
            uint8_t receiveData[64];
            rfid.communicateWithTag(Mfrc522::mfrc522Commands::receive,
                                    nullptr,
                                    0,
                                    receiveData,
                                    64*8);
//            rfid.communicateWithTag(Mfrc522::mfrc522Commands::mfAuthent, nullptr, 0, nullptr, 0);

            std::cout << "Hello tag\n";
            std::cout << "Your id = ";
            for(size_t i = 0; i < 4; i++){
                std::cout << std::hex << receiveData[0];
            }
            std::cout << "\n";

            std::cout << "Waiting for key press\n";
            while ((c = keypad.getKey()) == 'h') {
                delay(100);
            }

            //c = keypad.getKey();
            std::cout << c << " key has been pressed\n";

            connection.executeQuery("SELECT * FROM RFID");

            std::cout << "Database information: "
                      << connection.getPreviousResponseColumn("CARD_ID")
                      << '\n';

            std::cout << "String before encryption: R2D2 project\n";
            std::cout << "String after encryption: "
                      << '\n';

            led.blinkLed(1000);
        }
    } catch (const std::string &error) {
        std::cerr << error << '\n';
        exit(EXIT_FAILURE);
    } catch (...) {
        std::cerr << "Something went wrong\n";
        exit(EXIT_FAILURE);
    }
    return 0;
}

<|endoftext|>