<commit_before>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "primBuilder.h"
#include "gfxDevice.h"
#include "console/console.h"

//*****************************************************************************
// Primitive Builder
//*****************************************************************************
namespace PrimBuild
{
Vector<GFXVertexPCT> mTempVertBuff;
GFXVertexBufferHandle<GFXVertexPCT> mVertBuff;
GFXPrimitiveType  mType;
U32               mCurVertIndex;
ColorI            mCurColor( 255, 255, 255 );
Point2F           mCurTexCoord;
const ColorI      _colWhite( 255, 255, 255, 255 );

#ifdef TORQUE_DEBUG
U32 mMaxVerts;

#define INIT_VERTEX_SIZE(x) mMaxVerts = x;
#define VERTEX_BOUNDS_CHECK() AssertFatal( mCurVertIndex < mMaxVerts, "PrimBuilder encountered an out of bounds vertex! Break and debug!" );

// This next check shouldn't really be used a lot unless you are tracking down
// a specific bug. -pw
#define VERTEX_SIZE_CHECK() AssertFatal( mCurVertIndex <= mMaxVerts, "PrimBuilder allocated more verts than you used! Break and debug or rendering artifacts could occur." );

#else

#define INIT_VERTEX_SIZE(x)
#define VERTEX_BOUNDS_CHECK()
#define VERTEX_SIZE_CHECK()

#endif

//-----------------------------------------------------------------------------
// begin
//-----------------------------------------------------------------------------
void begin( GFXPrimitiveType type, U32 maxVerts )
{
   AssertFatal( type >= GFXPT_FIRST && type < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );

   mType = type;
   mCurVertIndex = 0;
   INIT_VERTEX_SIZE( maxVerts );
   mTempVertBuff.setSize( maxVerts );
}

void beginToBuffer( GFXPrimitiveType type, U32 maxVerts )
{
   AssertFatal( type >= GFXPT_FIRST && type < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );

   mType = type;
   mCurVertIndex = 0;
   INIT_VERTEX_SIZE( maxVerts );
   mTempVertBuff.setSize( maxVerts );
}

//-----------------------------------------------------------------------------
// end
//-----------------------------------------------------------------------------
GFXVertexBuffer * endToBuffer( U32 &numPrims )
{
   mVertBuff.set(GFX, mTempVertBuff.size(), GFXBufferTypeVolatile);
   GFXVertexPCT *verts = mVertBuff.lock();
   dMemcpy( verts, mTempVertBuff.address(), mTempVertBuff.size() * sizeof(GFXVertexPCT) );
   mVertBuff.unlock();

   VERTEX_SIZE_CHECK();

   switch( mType )
   {
      case GFXPointList:
      {
         numPrims = mCurVertIndex;
         break;
      }

      case GFXLineList:
      {
         numPrims = mCurVertIndex / 2;
         break;
      }

      case GFXLineStrip:
      {
         numPrims = mCurVertIndex - 1;
         break;
      }

      case GFXTriangleList:
      {
         numPrims = mCurVertIndex / 3;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         numPrims = mCurVertIndex - 2;
         break;
      }
      case GFXPT_COUNT:
         // handle warning
         break;
   }

   return mVertBuff;
}

void end( bool useGenericShaders )
{
   if ( mCurVertIndex == 0 )
      return;

   VERTEX_SIZE_CHECK();

   U32 vertStride = 1;
   U32 stripStart = 0;

   AssertFatal( mType >= GFXPT_FIRST && mType < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );

   switch( mType )
   {
      default:
      case GFXPointList:
      {
         vertStride = 1;
         break;
      }

      case GFXLineList:
      {
         vertStride = 2;
         break;
      }

      case GFXTriangleList:
      {
         vertStride = 3;
         break;
      }

      case GFXLineStrip:
      {
         stripStart = 1;
         vertStride = 1;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         stripStart = 2;
         vertStride = 1;
         break;
      }
   }

   if ( useGenericShaders )
   {
	   GFXStateBlock *currentBlock = GFX->getStateBlock();
	   if (currentBlock && currentBlock->getDesc().samplersDefined)
	   {
		   if (currentBlock->getDesc().vertexColorEnable)
      GFX->setupGenericShaders( GFXDevice::GSModColorTexture );
		   else
			   GFX->setupGenericShaders( GFXDevice::GSTexture );
	   }
	   else
		   GFX->setupGenericShaders( GFXDevice::GSColor );
   }

   const GFXVertexPCT *srcVerts = mTempVertBuff.address();
   U32 numVerts = mCurVertIndex;

   // Make sure we don't have a dirty prim buffer left.
   GFX->setPrimitiveBuffer( NULL );

   if ( stripStart > 0 )
   {
      // TODO: Fix this to allow > MAX_DYNAMIC_VERTS!

      U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
      mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

      GFXVertexPCT *verts = mVertBuff.lock();
      dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
      mVertBuff.unlock();

      U32 numPrims = ( copyVerts / vertStride ) - stripStart;
      GFX->setVertexBuffer( mVertBuff );
      GFX->drawPrimitive( mType, 0, numPrims );
   }
   else
   {
      while ( numVerts > 0 )
      {
         U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
         copyVerts -= copyVerts % vertStride;

         mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

         GFXVertexPCT *verts = mVertBuff.lock();
         dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
         mVertBuff.unlock();

         U32 numPrims = copyVerts / vertStride;
         GFX->setVertexBuffer( mVertBuff );
         GFX->drawPrimitive( mType, 0, numPrims );

         srcVerts += copyVerts;
         numVerts -= copyVerts;
      }
   }
}

//-----------------------------------------------------------------------------
// vertex2f
//-----------------------------------------------------------------------------
void vertex2f( F32 x, F32 y )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.x = x;
   vert->point.y = y;
   vert->point.z = 0.0;
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// vertex3f
//-----------------------------------------------------------------------------
void vertex3f( F32 x, F32 y, F32 z )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.x = x;
   vert->point.y = y;
   vert->point.z = z;
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// vertex3fv
//-----------------------------------------------------------------------------
void vertex3fv( const F32 *data )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.set( data[0], data[1], data[2] );
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// vertex2fv
//-----------------------------------------------------------------------------
void vertex2fv( const F32 *data )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.set( data[0], data[1], 0.f );
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// color
//-----------------------------------------------------------------------------
void color( const ColorI &inColor )
{
   mCurColor = inColor;
}

void color( const ColorF &inColor )
{
   mCurColor = inColor;
}

void color3i( U8 red, U8 green, U8 blue )
{
   mCurColor.set( red, green, blue );
}

void color4i( U8 red, U8 green, U8 blue, U8 alpha )
{
   mCurColor.set( red, green, blue, alpha );
}

void color3f( F32 red, F32 green, F32 blue )
{
   mCurColor.set( U8( red * 255 ), U8( green * 255 ), U8( blue * 255 ) );
}

void color4f( F32 red, F32 green, F32 blue, F32 alpha )
{
   mCurColor.set( U8( red * 255 ), U8( green * 255 ), U8( blue * 255 ), U8( alpha * 255 ) );
}

//-----------------------------------------------------------------------------
// texCoord
//-----------------------------------------------------------------------------
void texCoord2f( F32 x, F32 y )
{
   mCurTexCoord.set( x, y );
}

void shutdown()
{
   mVertBuff = NULL;
}

}  // namespace PrimBuild
<commit_msg>Fix TAB vs Spaces on Engine/source/gfx/primBuilder.cpp<commit_after>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "primBuilder.h"
#include "gfxDevice.h"
#include "console/console.h"

//*****************************************************************************
// Primitive Builder
//*****************************************************************************
namespace PrimBuild
{
Vector<GFXVertexPCT> mTempVertBuff;
GFXVertexBufferHandle<GFXVertexPCT> mVertBuff;
GFXPrimitiveType  mType;
U32               mCurVertIndex;
ColorI            mCurColor( 255, 255, 255 );
Point2F           mCurTexCoord;
const ColorI      _colWhite( 255, 255, 255, 255 );

#ifdef TORQUE_DEBUG
U32 mMaxVerts;

#define INIT_VERTEX_SIZE(x) mMaxVerts = x;
#define VERTEX_BOUNDS_CHECK() AssertFatal( mCurVertIndex < mMaxVerts, "PrimBuilder encountered an out of bounds vertex! Break and debug!" );

// This next check shouldn't really be used a lot unless you are tracking down
// a specific bug. -pw
#define VERTEX_SIZE_CHECK() AssertFatal( mCurVertIndex <= mMaxVerts, "PrimBuilder allocated more verts than you used! Break and debug or rendering artifacts could occur." );

#else

#define INIT_VERTEX_SIZE(x)
#define VERTEX_BOUNDS_CHECK()
#define VERTEX_SIZE_CHECK()

#endif

//-----------------------------------------------------------------------------
// begin
//-----------------------------------------------------------------------------
void begin( GFXPrimitiveType type, U32 maxVerts )
{
   AssertFatal( type >= GFXPT_FIRST && type < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );

   mType = type;
   mCurVertIndex = 0;
   INIT_VERTEX_SIZE( maxVerts );
   mTempVertBuff.setSize( maxVerts );
}

void beginToBuffer( GFXPrimitiveType type, U32 maxVerts )
{
   AssertFatal( type >= GFXPT_FIRST && type < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );

   mType = type;
   mCurVertIndex = 0;
   INIT_VERTEX_SIZE( maxVerts );
   mTempVertBuff.setSize( maxVerts );
}

//-----------------------------------------------------------------------------
// end
//-----------------------------------------------------------------------------
GFXVertexBuffer * endToBuffer( U32 &numPrims )
{
   mVertBuff.set(GFX, mTempVertBuff.size(), GFXBufferTypeVolatile);
   GFXVertexPCT *verts = mVertBuff.lock();
   dMemcpy( verts, mTempVertBuff.address(), mTempVertBuff.size() * sizeof(GFXVertexPCT) );
   mVertBuff.unlock();

   VERTEX_SIZE_CHECK();

   switch( mType )
   {
      case GFXPointList:
      {
         numPrims = mCurVertIndex;
         break;
      }

      case GFXLineList:
      {
         numPrims = mCurVertIndex / 2;
         break;
      }

      case GFXLineStrip:
      {
         numPrims = mCurVertIndex - 1;
         break;
      }

      case GFXTriangleList:
      {
         numPrims = mCurVertIndex / 3;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         numPrims = mCurVertIndex - 2;
         break;
      }
      case GFXPT_COUNT:
         // handle warning
         break;
   }

   return mVertBuff;
}

void end( bool useGenericShaders )
{
   if ( mCurVertIndex == 0 )
      return;

   VERTEX_SIZE_CHECK();

   U32 vertStride = 1;
   U32 stripStart = 0;

   AssertFatal( mType >= GFXPT_FIRST && mType < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );

   switch( mType )
   {
      default:
      case GFXPointList:
      {
         vertStride = 1;
         break;
      }

      case GFXLineList:
      {
         vertStride = 2;
         break;
      }

      case GFXTriangleList:
      {
         vertStride = 3;
         break;
      }

      case GFXLineStrip:
      {
         stripStart = 1;
         vertStride = 1;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         stripStart = 2;
         vertStride = 1;
         break;
      }
   }

    if ( useGenericShaders )
    {
        GFXStateBlock *currentBlock = GFX->getStateBlock();
        if (currentBlock && currentBlock->getDesc().samplersDefined)
        {
            if (currentBlock->getDesc().vertexColorEnable)
                GFX->setupGenericShaders( GFXDevice::GSModColorTexture );
            else
                GFX->setupGenericShaders( GFXDevice::GSTexture );
        }
        else
            GFX->setupGenericShaders( GFXDevice::GSColor );
    }

   const GFXVertexPCT *srcVerts = mTempVertBuff.address();
   U32 numVerts = mCurVertIndex;

   // Make sure we don't have a dirty prim buffer left.
   GFX->setPrimitiveBuffer( NULL );

   if ( stripStart > 0 )
   {
      // TODO: Fix this to allow > MAX_DYNAMIC_VERTS!

      U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
      mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

      GFXVertexPCT *verts = mVertBuff.lock();
      dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
      mVertBuff.unlock();

      U32 numPrims = ( copyVerts / vertStride ) - stripStart;
      GFX->setVertexBuffer( mVertBuff );
      GFX->drawPrimitive( mType, 0, numPrims );
   }
   else
   {
      while ( numVerts > 0 )
      {
         U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
         copyVerts -= copyVerts % vertStride;

         mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

         GFXVertexPCT *verts = mVertBuff.lock();
         dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
         mVertBuff.unlock();

         U32 numPrims = copyVerts / vertStride;
         GFX->setVertexBuffer( mVertBuff );
         GFX->drawPrimitive( mType, 0, numPrims );

         srcVerts += copyVerts;
         numVerts -= copyVerts;
      }
   }
}

//-----------------------------------------------------------------------------
// vertex2f
//-----------------------------------------------------------------------------
void vertex2f( F32 x, F32 y )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.x = x;
   vert->point.y = y;
   vert->point.z = 0.0;
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// vertex3f
//-----------------------------------------------------------------------------
void vertex3f( F32 x, F32 y, F32 z )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.x = x;
   vert->point.y = y;
   vert->point.z = z;
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// vertex3fv
//-----------------------------------------------------------------------------
void vertex3fv( const F32 *data )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.set( data[0], data[1], data[2] );
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// vertex2fv
//-----------------------------------------------------------------------------
void vertex2fv( const F32 *data )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.set( data[0], data[1], 0.f );
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// color
//-----------------------------------------------------------------------------
void color( const ColorI &inColor )
{
   mCurColor = inColor;
}

void color( const ColorF &inColor )
{
   mCurColor = inColor;
}

void color3i( U8 red, U8 green, U8 blue )
{
   mCurColor.set( red, green, blue );
}

void color4i( U8 red, U8 green, U8 blue, U8 alpha )
{
   mCurColor.set( red, green, blue, alpha );
}

void color3f( F32 red, F32 green, F32 blue )
{
   mCurColor.set( U8( red * 255 ), U8( green * 255 ), U8( blue * 255 ) );
}

void color4f( F32 red, F32 green, F32 blue, F32 alpha )
{
   mCurColor.set( U8( red * 255 ), U8( green * 255 ), U8( blue * 255 ), U8( alpha * 255 ) );
}

//-----------------------------------------------------------------------------
// texCoord
//-----------------------------------------------------------------------------
void texCoord2f( F32 x, F32 y )
{
   mCurTexCoord.set( x, y );
}

void shutdown()
{
   mVertBuff = NULL;
}

}  // namespace PrimBuild
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <iomanip>
#include <kvs/StructuredVolumeObject>
#include <kvs/StructuredVolumeImporter>
#include <kvs/HydrogenVolumeData>
#include <kvs/RayCastingRenderer>
#include <kvs/Timer>
#include <kvs/egl/Screen>

int main( int argc, char** argv )
{
    kvs::StructuredVolumeObject* volume = NULL;
    if ( argc > 1 ) volume = new kvs::StructuredVolumeImporter( std::string( argv[1] ) );
    else            volume = new kvs::HydrogenVolumeData( kvs::Vec3u( 64, 64, 64 ) );

    kvs::StructuredVolumeObject* object = volume;
    // kvs::RayCastingRenderer* renderer = new kvs::RayCastingRenderer();
    kvs::glsl::RayCastingRenderer* renderer = new kvs::glsl::RayCastingRenderer();

    kvs::egl::Screen screen;
    screen.setGeometry( 0, 0, 512, 512 );
    screen.registerObject( object, renderer );

    screen.displayInfo();
    kvs::Timer timer( kvs::Timer::Start );
    for ( size_t i = 0; i < 4; i++ )
    {
        std::stringstream num; num << std::setw(3) << std::setfill('0') << i;
        std::string filename = "output_" + num.str() + ".bmp";

        std::cout << "rendering to ... " << std::flush;
        object->multiplyXform( kvs::Xform::Rotation( kvs::Mat3::RotationY( 30 ) ) );
        screen.draw();
        screen.capture().write( filename );
        std::cout << filename << std::endl;
    }
    timer.stop();

    std::cout << "Total rendering time:   " << timer.sec() << " [sec]" << std::endl;
    std::cout << "Average rendering time: " << timer.sec() / 4.0f << " [sec]" << std::endl;

    return 0;
}
<commit_msg>Modified.<commit_after>#include <iostream>
#include <sstream>
#include <iomanip>
#include <kvs/StructuredVolumeObject>
#include <kvs/StructuredVolumeImporter>
#include <kvs/HydrogenVolumeData>
#include <kvs/RayCastingRenderer>
#include <kvs/Timer>
#include <kvs/egl/Screen>

int main( int argc, char** argv )
{
    std::cout << "EGL version: " << kvs::egl::Version() << std::endl;

    kvs::StructuredVolumeObject* volume = NULL;
    if ( argc > 1 ) volume = new kvs::StructuredVolumeImporter( std::string( argv[1] ) );
    else            volume = new kvs::HydrogenVolumeData( kvs::Vec3u( 64, 64, 64 ) );

    kvs::StructuredVolumeObject* object = volume;
    // kvs::RayCastingRenderer* renderer = new kvs::RayCastingRenderer();
    kvs::glsl::RayCastingRenderer* renderer = new kvs::glsl::RayCastingRenderer();

    kvs::egl::Screen screen;
    screen.setGeometry( 0, 0, 512, 512 );
    screen.registerObject( object, renderer );

    screen.displayInfo();
    kvs::Timer timer( kvs::Timer::Start );
    for ( size_t i = 0; i < 12; i++ )
    {
        std::stringstream num; num << std::setw(3) << std::setfill('0') << i;
        std::string filename = "output_" + num.str() + ".bmp";

        std::cout << "rendering to ... " << std::flush;
        object->multiplyXform( kvs::Xform::Rotation( kvs::Mat3::RotationY( 30 ) ) );
        screen.draw();
        screen.capture().write( filename );
        std::cout << filename << std::endl;
    }
    timer.stop();

    std::cout << "Total rendering time:   " << timer.sec() << " [sec]" << std::endl;
    std::cout << "Average rendering time: " << timer.sec() / 4.0f << " [sec]" << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include "gtest/gtest.h"

#include <hspp/Managers/GameAgent.hpp>
#include <hspp/Tasks/PlayerTasks/BriefTask.hpp>

using namespace Hearthstonepp;
using namespace PlayerTasks;

TEST(BriefTask, GetTaskID)
{
    const BriefTask brief;
    EXPECT_EQ(brief.GetTaskID(), +TaskID::BRIEF);
}

TEST(BriefTask, Run)
{
    BriefTask brief;
    GameAgent agent(CardClass::ROGUE, CardClass::DRUID, PlayerType::PLAYER1);

    agent.GetPlayer1().SetID(100);

    MetaData result = brief.Run(agent.GetPlayer1());
    EXPECT_EQ(result, MetaData::BRIEF);

    TaskMeta meta;
    result = brief.Run(agent.GetPlayer1(), meta);
    EXPECT_EQ(result, MetaData::BRIEF);
    EXPECT_EQ(meta.GetID(), +TaskID::BRIEF);
    EXPECT_EQ(meta.GetStatus(), MetaData::BRIEF);
    EXPECT_EQ(meta.GetUserID(), agent.GetPlayer1().GetID());
}
<commit_msg>refactor: Replace GameAgent to Game<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include "gtest/gtest.h"

#include <hspp/Game/Game.hpp>
#include <hspp/Tasks/PlayerTasks/BriefTask.hpp>

using namespace Hearthstonepp;
using namespace PlayerTasks;

TEST(BriefTask, GetTaskID)
{
    const BriefTask brief;
    EXPECT_EQ(brief.GetTaskID(), +TaskID::BRIEF);
}

TEST(BriefTask, Run)
{
    BriefTask brief;
    Game game(CardClass::ROGUE, CardClass::DRUID, PlayerType::PLAYER1);

    game.GetPlayer1().SetID(100);

    MetaData result = brief.Run(game.GetPlayer1());
    EXPECT_EQ(result, MetaData::BRIEF);
}
<|endoftext|>


<commit_before>// PWHistDlg.cpp : implementation file
//

#include "stdafx.h"

#include "PasswordSafe.h"
#include "ThisMfcApp.h"
#include "resource.h"
#include "PWHistDlg.h"
#include "corelib/ItemData.h"
#include ".\pwhistdlg.h"

// CPWHistDlg dialog

IMPLEMENT_DYNAMIC(CPWHistDlg, CDialog)
CPWHistDlg::CPWHistDlg(CWnd* pParent, bool IsReadOnly,
             CMyString &HistStr, PWHistList &PWHistList,
             int NumPWHistory, int &MaxPWHistory,
             BOOL &SavePWHistory)
: CDialog(CPWHistDlg::IDD, pParent),
  m_IsReadOnly(IsReadOnly),
  m_HistStr(HistStr), m_PWHistList(PWHistList),
  m_NumPWHistory(NumPWHistory), m_MaxPWHistory(MaxPWHistory),
  m_SavePWHistory(SavePWHistory),
  m_ClearPWHistory(false),
  m_iSortedColumn(-1), m_bSortAscending(TRUE)
{
  m_oldMaxPWHistory = m_MaxPWHistory;
}

CPWHistDlg::~CPWHistDlg()
{
}

void CPWHistDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
  DDX_Control(pDX, IDC_PWHISTORY_LIST, m_PWHistListCtrl);
  DDX_Check(pDX, IDC_SAVE_PWHIST, m_SavePWHistory);
  DDX_Text(pDX, IDC_MAXPWHISTORY, m_MaxPWHistory);
  DDV_MinMaxInt(pDX, m_MaxPWHistory, 1, 25);
}

BEGIN_MESSAGE_MAP(CPWHistDlg, CDialog)
ON_BN_CLICKED(IDC_CLEAR_PWHIST, OnBnClickedClearPWHist)
ON_BN_CLICKED(IDC_SAVE_PWHIST, OnCheckedSavePasswordHistory)
ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked)
ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
ON_NOTIFY(NM_CLICK, IDC_PWHISTORY_LIST, OnHistListClick)
ON_BN_CLICKED(IDC_PWH_COPY_ALL, OnBnClickedPwhCopyAll)
END_MESSAGE_MAP()

BOOL CPWHistDlg::OnInitDialog()
{
  CDialog::OnInitDialog();

  GetDlgItem(IDC_MAXPWHISTORY)->EnableWindow(m_SavePWHistory ? TRUE : FALSE);

  BOOL bpwh_count = (m_PWHistList.GetCount() == 0) ? FALSE : TRUE;
  GetDlgItem(IDC_CLEAR_PWHIST)->EnableWindow(bpwh_count);
  GetDlgItem(IDC_PWHISTORY_LIST)->EnableWindow(bpwh_count);

  if (m_IsReadOnly) {
    GetDlgItem(IDOK)->EnableWindow(FALSE);
    GetDlgItem(IDC_SAVE_PWHIST)->EnableWindow(FALSE);
    GetDlgItem(IDC_CLEAR_PWHIST)->EnableWindow(FALSE);  // overrides count
  }

  m_PWHistListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT);
  m_PWHistListCtrl.InsertColumn(0, _T("Set Date/Time"));
  m_PWHistListCtrl.InsertColumn(1, _T("Password"));

  int nPos = 0;
  POSITION itempos;

  POSITION listpos = m_PWHistList.GetHeadPosition();
  while (listpos != NULL) {
    itempos = listpos;
    const PWHistEntry pwhentry = m_PWHistList.GetAt(listpos);
    nPos = m_PWHistListCtrl.InsertItem(nPos, pwhentry.changedate);
    m_PWHistListCtrl.SetItemText(nPos, 1, pwhentry.password);
    m_PWHistListCtrl.SetItemData(nPos, (DWORD)itempos);
    m_PWHistList.GetNext(listpos);
  }

  m_PWHistListCtrl.SetRedraw(FALSE);
  for (int i = 0; i < 2; i++) {
    m_PWHistListCtrl.SetColumnWidth(i, LVSCW_AUTOSIZE);
    int nColumnWidth = m_PWHistListCtrl.GetColumnWidth(i);
    m_PWHistListCtrl.SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
    int nHeaderWidth = m_PWHistListCtrl.GetColumnWidth(i);
    m_PWHistListCtrl.SetColumnWidth(i, max(nColumnWidth, nHeaderWidth));
  }
  m_PWHistListCtrl.SetRedraw(TRUE);

  char buffer[10];
#if _MSC_VER >= 1400
  sprintf_s(buffer, 10, "%d", m_NumPWHistory);
#else
  sprintf(buffer, "%d", m_NumPWHistory);
#endif

  CSpinButtonCtrl* pspin = (CSpinButtonCtrl *)GetDlgItem(IDC_PWHSPIN);

  if (m_MaxPWHistory == 0)
  	m_MaxPWHistory = 1;

  pspin->SetBuddy(GetDlgItem(IDC_MAXPWHISTORY));
  pspin->SetRange(1, 25);
  pspin->SetBase(10);
  pspin->SetPos(m_MaxPWHistory);

  return TRUE;
}

// CPWHistDlg message handlers
void CPWHistDlg::OnBnClickedClearPWHist()
{
  m_ClearPWHistory = true;
  m_PWHistListCtrl.DeleteAllItems();
}

void
CPWHistDlg::OnOK()
{
  UpdateData(TRUE);
  /* Handle history header.
   * Header is in the form fmmnn, where:
   * f = {0,1} if password history is on/off
   * mm = 2 digits max size of history list
   * nn = 2 digits current size of history list
   *
   * Special case: history empty and password history off - do nothing
   */

  const CMyString oldHistStr = m_HistStr;

  if (m_ClearPWHistory == TRUE) {
    m_PWHistList.RemoveAll();
    m_HistStr = m_HistStr.Left(5);
  }

  if (!(m_HistStr.IsEmpty() && m_SavePWHistory == FALSE)) {
    TCHAR buffer[6];
#if _MSC_VER >= 1400
    sprintf_s
#else
      sprintf
#endif
      (buffer,
#if _MSC_VER >= 1400
       6,
#endif
       "%1x%02x%02x",
       (m_SavePWHistory == FALSE) ? 0 : 1,
       m_MaxPWHistory,
       m_PWHistList.GetCount()
       );
    if (m_HistStr.GetLength() >= 5) {
      for (int i = 0; i < 5; i++) m_HistStr.SetAt(i, buffer[i]);
    } else {
      m_HistStr = buffer;
    }
  }
  CDialog::OnOK();
}

void
CPWHistDlg::OnCheckedSavePasswordHistory()
{
  m_SavePWHistory = ((CButton*)GetDlgItem(IDC_SAVE_PWHIST))->GetCheck();
  GetDlgItem(IDC_MAXPWHISTORY)->EnableWindow(m_SavePWHistory ? TRUE : FALSE);
}

void
CPWHistDlg::OnHistListClick(NMHDR* pNMHDR, LRESULT*)
{
  LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) pNMHDR;
  ASSERT(lpnmitem != NULL);
  int item = lpnmitem->iItem;
  POSITION itempos = POSITION(m_PWHistListCtrl.GetItemData(item));
  const PWHistEntry pwhentry = m_PWHistList.GetAt(itempos);
  app.SetClipboardData(pwhentry.password);
}

void
CPWHistDlg::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
  HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;

  if(phdn->iButton == 0) {
    // User clicked on header using left mouse button
    if(phdn->iItem == m_iSortedColumn)
      m_bSortAscending = !m_bSortAscending;
    else
      m_bSortAscending = TRUE;

    m_iSortedColumn = phdn->iItem;
    m_PWHistListCtrl.SortItems(CompareFunc, (LPARAM)this);

    // Note: WINVER defines the minimum system level for which this is program compiled and
    // NOT the level of system it is running on!
    // In this case, these values are defined in Windows XP and later and supported
    // by V6 of comctl32.dll (supplied with Windows XP) and later.
    // They should be ignored by earlier levels of this dll or .....
    //     we can check the dll version (code available on request)!

#if (WINVER < 0x0501)	// These are already defined for WinXP and later
#define HDF_SORTUP 0x0400
#define HDF_SORTDOWN 0x0200
#endif
    HDITEM HeaderItem;
    HeaderItem.mask = HDI_FORMAT;
    m_PWHistListCtrl.GetHeaderCtrl()->GetItem(m_iSortedColumn, &HeaderItem);
    // Turn off all arrows
    HeaderItem.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
    // Turn on the correct arrow
    HeaderItem.fmt |= ((m_bSortAscending == TRUE) ? HDF_SORTUP : HDF_SORTDOWN);
    m_PWHistListCtrl.GetHeaderCtrl()->SetItem(m_iSortedColumn, &HeaderItem);
  }

  *pResult = 0;
}

int CALLBACK CPWHistDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2,
                                     LPARAM closure)
{
  CPWHistDlg *self = (CPWHistDlg*)closure;
  int nSortColumn = self->m_iSortedColumn;
  POSITION Lpos = (POSITION)lParam1;
  POSITION Rpos = (POSITION)lParam2;
  const PWHistEntry pLHS = self->m_PWHistList.GetAt(Lpos);
  const PWHistEntry pRHS = self->m_PWHistList.GetAt(Rpos);
  CMyString password1, changedate1;
  CMyString password2, changedate2;
  time_t t1, t2;

  int iResult;
  switch(nSortColumn) {
  case 0:
    t1 = pLHS.changetttdate;
    t2 = pRHS.changetttdate;
    iResult = ((long) t1 < (long) t2) ? -1 : 1;
    break;
  case 1:
    password1 = pLHS.password;
    password2 = pRHS.password;
    iResult = ((CString)password1).Compare(password2);
    break;
  default:
    iResult = 0; // should never happen - just keep compiler happy
    ASSERT(FALSE);
  }

  if (!self->m_bSortAscending)
    iResult *= -1;

  return iResult;
}

void CPWHistDlg::OnBnClickedPwhCopyAll()
{
  CMyString HistStr;
  POSITION pos = m_PWHistList.GetHeadPosition();

  while (pos != NULL) {
    const PWHistEntry &ent = m_PWHistList.GetNext(pos);
    HistStr += ent.changedate;
    HistStr += _T("\t");
    HistStr += ent.password;
    HistStr += _T("\r\n");
  }
  app.SetClipboardData(HistStr);
}
<commit_msg>Fix [1529305] Crash in Password History<commit_after>// PWHistDlg.cpp : implementation file
//

#include "stdafx.h"

#include "PasswordSafe.h"
#include "ThisMfcApp.h"
#include "resource.h"
#include "PWHistDlg.h"
#include "corelib/ItemData.h"
#include ".\pwhistdlg.h"

// CPWHistDlg dialog

IMPLEMENT_DYNAMIC(CPWHistDlg, CDialog)
CPWHistDlg::CPWHistDlg(CWnd* pParent, bool IsReadOnly,
             CMyString &HistStr, PWHistList &PWHistList,
             int NumPWHistory, int &MaxPWHistory,
             BOOL &SavePWHistory)
: CDialog(CPWHistDlg::IDD, pParent),
  m_IsReadOnly(IsReadOnly),
  m_HistStr(HistStr), m_PWHistList(PWHistList),
  m_NumPWHistory(NumPWHistory), m_MaxPWHistory(MaxPWHistory),
  m_SavePWHistory(SavePWHistory),
  m_ClearPWHistory(false),
  m_iSortedColumn(-1), m_bSortAscending(TRUE)
{
  m_oldMaxPWHistory = m_MaxPWHistory;
}

CPWHistDlg::~CPWHistDlg()
{
}

void CPWHistDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
  DDX_Control(pDX, IDC_PWHISTORY_LIST, m_PWHistListCtrl);
  DDX_Check(pDX, IDC_SAVE_PWHIST, m_SavePWHistory);
  DDX_Text(pDX, IDC_MAXPWHISTORY, m_MaxPWHistory);
  DDV_MinMaxInt(pDX, m_MaxPWHistory, 1, 25);
}

BEGIN_MESSAGE_MAP(CPWHistDlg, CDialog)
ON_BN_CLICKED(IDC_CLEAR_PWHIST, OnBnClickedClearPWHist)
ON_BN_CLICKED(IDC_SAVE_PWHIST, OnCheckedSavePasswordHistory)
ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked)
ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
ON_NOTIFY(NM_CLICK, IDC_PWHISTORY_LIST, OnHistListClick)
ON_BN_CLICKED(IDC_PWH_COPY_ALL, OnBnClickedPwhCopyAll)
END_MESSAGE_MAP()

BOOL CPWHistDlg::OnInitDialog()
{
  CDialog::OnInitDialog();

  GetDlgItem(IDC_MAXPWHISTORY)->EnableWindow(m_SavePWHistory ? TRUE : FALSE);

  BOOL bpwh_count = (m_PWHistList.GetCount() == 0) ? FALSE : TRUE;
  GetDlgItem(IDC_CLEAR_PWHIST)->EnableWindow(bpwh_count);
  GetDlgItem(IDC_PWHISTORY_LIST)->EnableWindow(bpwh_count);

  if (m_IsReadOnly) {
    GetDlgItem(IDOK)->EnableWindow(FALSE);
    GetDlgItem(IDC_SAVE_PWHIST)->EnableWindow(FALSE);
    GetDlgItem(IDC_CLEAR_PWHIST)->EnableWindow(FALSE);  // overrides count
  }

  m_PWHistListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT);
  m_PWHistListCtrl.InsertColumn(0, _T("Set Date/Time"));
  m_PWHistListCtrl.InsertColumn(1, _T("Password"));

  int nPos = 0;
  POSITION itempos;

  POSITION listpos = m_PWHistList.GetHeadPosition();
  while (listpos != NULL) {
    itempos = listpos;
    const PWHistEntry pwhentry = m_PWHistList.GetAt(listpos);
    nPos = m_PWHistListCtrl.InsertItem(nPos, pwhentry.changedate);
    m_PWHistListCtrl.SetItemText(nPos, 1, pwhentry.password);
    m_PWHistListCtrl.SetItemData(nPos, (DWORD)itempos);
    m_PWHistList.GetNext(listpos);
  }

  m_PWHistListCtrl.SetRedraw(FALSE);
  for (int i = 0; i < 2; i++) {
    m_PWHistListCtrl.SetColumnWidth(i, LVSCW_AUTOSIZE);
    int nColumnWidth = m_PWHistListCtrl.GetColumnWidth(i);
    m_PWHistListCtrl.SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
    int nHeaderWidth = m_PWHistListCtrl.GetColumnWidth(i);
    m_PWHistListCtrl.SetColumnWidth(i, max(nColumnWidth, nHeaderWidth));
  }
  m_PWHistListCtrl.SetRedraw(TRUE);

  char buffer[10];
#if _MSC_VER >= 1400
  sprintf_s(buffer, 10, "%d", m_NumPWHistory);
#else
  sprintf(buffer, "%d", m_NumPWHistory);
#endif

  CSpinButtonCtrl* pspin = (CSpinButtonCtrl *)GetDlgItem(IDC_PWHSPIN);

  if (m_MaxPWHistory == 0)
  	m_MaxPWHistory = 1;

  pspin->SetBuddy(GetDlgItem(IDC_MAXPWHISTORY));
  pspin->SetRange(1, 25);
  pspin->SetBase(10);
  pspin->SetPos(m_MaxPWHistory);

  return TRUE;
}

// CPWHistDlg message handlers
void CPWHistDlg::OnBnClickedClearPWHist()
{
  m_ClearPWHistory = true;
  m_PWHistListCtrl.DeleteAllItems();
}

void
CPWHistDlg::OnOK()
{
  UpdateData(TRUE);
  /* Handle history header.
   * Header is in the form fmmnn, where:
   * f = {0,1} if password history is on/off
   * mm = 2 digits max size of history list
   * nn = 2 digits current size of history list
   *
   * Special case: history empty and password history off - do nothing
   */

  const CMyString oldHistStr = m_HistStr;

  if (m_ClearPWHistory == TRUE) {
    m_PWHistList.RemoveAll();
    m_HistStr = m_HistStr.Left(5);
  }

  if (!(m_HistStr.IsEmpty() && m_SavePWHistory == FALSE)) {
    TCHAR buffer[6];
#if _MSC_VER >= 1400
    sprintf_s
#else
      sprintf
#endif
      (buffer,
#if _MSC_VER >= 1400
       6,
#endif
       "%1x%02x%02x",
       (m_SavePWHistory == FALSE) ? 0 : 1,
       m_MaxPWHistory,
       m_PWHistList.GetCount()
       );
    if (m_HistStr.GetLength() >= 5) {
      for (int i = 0; i < 5; i++) m_HistStr.SetAt(i, buffer[i]);
    } else {
      m_HistStr = buffer;
    }
  }
  CDialog::OnOK();
}

void
CPWHistDlg::OnCheckedSavePasswordHistory()
{
  m_SavePWHistory = ((CButton*)GetDlgItem(IDC_SAVE_PWHIST))->GetCheck();
  GetDlgItem(IDC_MAXPWHISTORY)->EnableWindow(m_SavePWHistory ? TRUE : FALSE);
}

void
CPWHistDlg::OnHistListClick(NMHDR* pNMHDR, LRESULT*)
{
  LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) pNMHDR;
  ASSERT(lpnmitem != NULL);
  int item = lpnmitem->iItem;
  if (item == -1)
	  return;
  POSITION itempos = POSITION(m_PWHistListCtrl.GetItemData(item));
  const PWHistEntry pwhentry = m_PWHistList.GetAt(itempos);
  app.SetClipboardData(pwhentry.password);
}

void
CPWHistDlg::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
  HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;

  if(phdn->iButton == 0) {
    // User clicked on header using left mouse button
    if(phdn->iItem == m_iSortedColumn)
      m_bSortAscending = !m_bSortAscending;
    else
      m_bSortAscending = TRUE;

    m_iSortedColumn = phdn->iItem;
    m_PWHistListCtrl.SortItems(CompareFunc, (LPARAM)this);

    // Note: WINVER defines the minimum system level for which this is program compiled and
    // NOT the level of system it is running on!
    // In this case, these values are defined in Windows XP and later and supported
    // by V6 of comctl32.dll (supplied with Windows XP) and later.
    // They should be ignored by earlier levels of this dll or .....
    //     we can check the dll version (code available on request)!

#if (WINVER < 0x0501)	// These are already defined for WinXP and later
#define HDF_SORTUP 0x0400
#define HDF_SORTDOWN 0x0200
#endif
    HDITEM HeaderItem;
    HeaderItem.mask = HDI_FORMAT;
    m_PWHistListCtrl.GetHeaderCtrl()->GetItem(m_iSortedColumn, &HeaderItem);
    // Turn off all arrows
    HeaderItem.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
    // Turn on the correct arrow
    HeaderItem.fmt |= ((m_bSortAscending == TRUE) ? HDF_SORTUP : HDF_SORTDOWN);
    m_PWHistListCtrl.GetHeaderCtrl()->SetItem(m_iSortedColumn, &HeaderItem);
  }

  *pResult = 0;
}

int CALLBACK CPWHistDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2,
                                     LPARAM closure)
{
  CPWHistDlg *self = (CPWHistDlg*)closure;
  int nSortColumn = self->m_iSortedColumn;
  POSITION Lpos = (POSITION)lParam1;
  POSITION Rpos = (POSITION)lParam2;
  const PWHistEntry pLHS = self->m_PWHistList.GetAt(Lpos);
  const PWHistEntry pRHS = self->m_PWHistList.GetAt(Rpos);
  CMyString password1, changedate1;
  CMyString password2, changedate2;
  time_t t1, t2;

  int iResult;
  switch(nSortColumn) {
  case 0:
    t1 = pLHS.changetttdate;
    t2 = pRHS.changetttdate;
    iResult = ((long) t1 < (long) t2) ? -1 : 1;
    break;
  case 1:
    password1 = pLHS.password;
    password2 = pRHS.password;
    iResult = ((CString)password1).Compare(password2);
    break;
  default:
    iResult = 0; // should never happen - just keep compiler happy
    ASSERT(FALSE);
  }

  if (!self->m_bSortAscending)
    iResult *= -1;

  return iResult;
}

void CPWHistDlg::OnBnClickedPwhCopyAll()
{
  CMyString HistStr;
  POSITION pos = m_PWHistList.GetHeadPosition();

  while (pos != NULL) {
    const PWHistEntry &ent = m_PWHistList.GetNext(pos);
    HistStr += ent.changedate;
    HistStr += _T("\t");
    HistStr += ent.password;
    HistStr += _T("\r\n");
  }
  app.SetClipboardData(HistStr);
}
<|endoftext|>


<commit_before>#include "websocketbroker.h"
#include "logger.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QVector>
#include <QFile>
#include <QCoreApplication>
#include <QRegularExpression>

WebSocketBroker::WebSocketBroker(const QString& vssFile)
{
    loadJson(vssFile);
    loadTempSignalList();

    connect(&m_webSocket, &QWebSocket::connected, this, &WebSocketBroker::onConnected);
    //connect(&m_webSocket, &QWebSocket::disconnected, this, &WebSocketBroker::closed);
    m_webSocket.open(QUrl("ws://localhost:42"));
}

bool WebSocketBroker::getSignalValue(const QString& path, QJsonArray& values)
{
    // Check if path is single leaf.
    // Check if path is single branch.
    // Check if path contains asterisk.
    // Check if path contains asterisk and leaf.
    QJsonArray paths = parseGetPath(path);

    // Check if signal exists.
    if(checkSignals(paths, true)) { return false; }

    // Create message to send
    QJsonObject message;
    message.insert("get", paths);
    QJsonDocument jsonDoc(message);

    // Lock and send message.
    QMutexLocker locker(&m_mutex);
    sendMessage(jsonDoc.toJson());

    // TODO Need to implement some kind of timer here.
    while(!m_messageReceivedFromBroker)
    {
        //DEBUG("TEST","Waiting for response...");
    }

    jsonDoc = QJsonDocument(m_receivedMessage);

    // TODO Add check of Success in response.
    // Could just return false, instead of array, if error?
    if(jsonDoc.object()["get"].isArray())
    {
        values = jsonDoc.object()["get"].toArray();
        return true;
    }
    return false;
}

bool WebSocketBroker::setSignalValue(const QString& path, const QVariant& values)
{
    QJsonArray paths = parseSetPath(path, values.toJsonValue());

    // Check if signal exists.
    if(checkSignals(paths, false)) { return false; }

    // Create message to send
    QJsonObject message;
    message.insert("set", paths);
    QJsonDocument jsonDoc(message);

    // Lock and send message.
    QMutexLocker locker(&m_mutex);
    sendMessage(jsonDoc.toJson());

    // TODO Need to implement some kind of timer here.
    while(!m_messageReceivedFromBroker)
    {
        //DEBUG("TEST","Waiting for response...");
    }

    jsonDoc = QJsonDocument(m_receivedMessage);

    // Should return false, or 0 if not bool. So should work without checking if bool
    return jsonDoc.object()["set"].toBool();
}

QJsonObject WebSocketBroker::getVSSNode(const QString& path)
{

    // clear old
    m_vssTreeNode = QJsonObject();

    if (m_vssTree.empty())
    {
        DEBUG("Server","Empty VSS tree. Returning empty node.");
        return m_vssTreeNode;
    }
    else if (path == "")
    {
        DEBUG("Server","Empty path. Returning full tree.");
        return m_vssTree;
    }
    else
    {
        QStringList tokens = path.split('.');

        // Make a copy of the full tree
        QJsonObject tree = m_vssTree;

        QVector<JsonNode> nodes;
        getTreeNodes(tree, tokens, nodes);

        QJsonObject obj;
        createJsonVssTree(nodes, obj);

        return m_vssTreeNode;
    }
}

QJsonObject WebSocketBroker::getVSSTree(const QString& path)
{
    QString p = path;
    QJsonObject tree;
    return tree;
}

void WebSocketBroker::sendMessage(const QString& message)
{
    m_messageReceivedFromBroker = false;
    m_webSocket.sendTextMessage(message);
    m_webSocket.flush();
}

void WebSocketBroker::onConnected()
{
    connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &WebSocketBroker::onTextMessageReceived);
}

void WebSocketBroker::onTextMessageReceived(QString message)
{
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &parseError);
    if(parseError.error != QJsonParseError::NoError)
    {
        m_receivedMessage = doc.object(); // Change to error.
        m_messageReceivedFromBroker = true;
        return;
    }
    m_receivedMessage = doc.object();
    m_messageReceivedFromBroker = true;
}

void WebSocketBroker::getTreeNodes(QJsonObject& tree, QStringList& path, QVector<JsonNode>& nodes)
{
    if (path.length() > 0)
    {
        QString key = path[0];
        JsonNode node;
        node.isBranch = path.length() > 1;
        node.key = key;

        if (node.isBranch)
        {
            removeAllKeysButOne(tree, key);
        }

        tree = tree.value(key).toObject();

        QJsonObject treeCopy = tree;

        if (node.isBranch)
        {
            removeOne(treeCopy, "children");
            tree = tree.value("children").toObject();
        }

        node.json = treeCopy;

        nodes.push_front(node);

        path.removeFirst();
        getTreeNodes(tree, path, nodes);
    }
}

void WebSocketBroker::createJsonVssTree(QVector<JsonNode>& nodes, QJsonObject& json)
{

    if (nodes.size() > 0)
    {
        JsonNode node = nodes.first();
        QJsonObject obj;

        if (node.isBranch)
        {
            node.json.insert("children", json);
            obj.insert(node.key, node.json);
        }
        else
        {
            obj.insert(node.key, node.json);
        }

        nodes.removeFirst();
        createJsonVssTree(nodes, obj);
    }
    else
    {
        m_vssTreeNode = json;
    }
}

void WebSocketBroker::removeAllKeysButOne(QJsonObject& json, const QString& filter)
{
    foreach (QString key, json.keys())
    {
        if (filter != key)
        {
            json.remove(key);
        }
    }
}

void WebSocketBroker::removeOne(QJsonObject& json, const QString& filter)
{
    foreach (QString key, json.keys())
    {
        if (filter == key)
        {
            json.remove(key);
        }
    }
}

void WebSocketBroker::loadJson(const QString &fileName)
{
    QFile jsonFile(fileName);
    QJsonDocument doc;

    if (jsonFile.exists())
    {
        jsonFile.open(QFile::ReadOnly);
        doc = QJsonDocument().fromJson(jsonFile.readAll());
    }
    else
    {
        WARNING("Server",QString("VSS File %1 not found!").arg(fileName));
    }

    m_vssTree = doc.object();
}

void WebSocketBroker::loadTempSignalList()
{
    QRegularExpression regex(QString("^(\\S+) \\d+"));

    QFile file(QCoreApplication::applicationDirPath() + "/vss_rel_1.vsi");
    file.open(QFile::ReadOnly);
    if(!file.exists())
    {
        WARNING("Server", "The flattened vsi signal file could not be found for the Signal Broker!");
        file.close();
        return;
    }
    while(!file.atEnd())
    {
        QRegularExpressionMatch match = regex.match(file.readLine());
        if(match.hasMatch()) { m_tempSignalList.append(match.captured(1).trimmed()); }
    }
}

QJsonArray WebSocketBroker::parseGetPath(const QString& path)
{
    QStringList sl = splitPath(path);
    QJsonArray values;

    if(sl.length() == 1)
        foreach(auto const item, getPath(sl.first()))
    {
        QJsonObject value;
        value.insert(item,"");
        values.append(value);
    }
    else
        foreach(auto const item, getPath(sl.first(), sl.last()))
    {
        QJsonObject value;
        value.insert(item,"");
        values.append(value);
    }

    return values;
}

QJsonArray WebSocketBroker::parseSetPath(const QString& path, const QJsonValue &setValues)
{
    QStringList sl = splitPath(path);
    QJsonArray values;

    if(setValues.isArray())
    {
        foreach(QJsonValue const val, setValues.toArray())
        {
            QJsonObject value;
            QJsonObject obj = val.toObject();

            QString valuePath = sl.first() + "." + obj.keys().first();
            QJsonValue tmp = obj.value(obj.keys().first());

            if(tmp.isDouble())
            {
                value.insert(valuePath, tmp.toDouble());
            }
            else if(tmp.isBool())
            {
                value.insert(valuePath, tmp.toBool());
            }
            else
            {
                value.insert(valuePath, tmp.toString());
            }

            values.append(value);
        }
    }
    else
    {
        QJsonObject value;

        if(setValues.isDouble())
        {
            value.insert(path, setValues.toDouble());
        }
        else if(setValues.isBool())
        {
            value.insert(path, setValues.toBool());
        }
        else
        {
            value.insert(path, setValues.toString());
        }

        values .append(value);
    }

    return values;
}

bool WebSocketBroker::checkSignals(const QJsonArray &paths, bool getOrSet)
{
    foreach (QJsonValue const &value, paths)
    {
        QJsonObject signal = getVSSNode(value.toString());
        if(signal.isEmpty()) { return false; }

        if(getOrSet)
        {
            // TODO Check if the signal is ok to get
        }
        else
        {
            // TODO Check if the signal is ok to set
        }
    }
    return true;
}

QStringList WebSocketBroker::getPath(QString startsWith)
{
    return getPath(startsWith, "");
}

QStringList WebSocketBroker::getPath(QString startsWith, QString endsWith)
{
    return m_tempSignalList.filter(QRegularExpression(QString("^%1.*%2$").arg(startsWith, endsWith)));
}

QStringList WebSocketBroker::splitPath(QString path)
{
    QStringList sl;
    int i = path.lastIndexOf("*");
    if(i == -1) { sl << path; return sl; }

    foreach(QString item, path.split("*"))
    {
        // Trim '.' from items.
        if(item.startsWith(".")) { item = item.remove(0,1); }
        if(item.endsWith(".")) { item = item.remove(item.length() -1, 1); }

        sl << item;
    }
    return sl;
}
<commit_msg>Fixed some bugs in signal broker.<commit_after>#include "websocketbroker.h"
#include "logger.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QVector>
#include <QFile>
#include <QCoreApplication>
#include <QRegularExpression>

WebSocketBroker::WebSocketBroker(const QString& vssFile)
{
    loadJson(vssFile);
    loadTempSignalList();

    connect(&m_webSocket, &QWebSocket::connected, this, &WebSocketBroker::onConnected);
    //connect(&m_webSocket, &QWebSocket::disconnected, this, &WebSocketBroker::closed);
    m_webSocket.open(QUrl("ws://localhost:8008"));
}

bool WebSocketBroker::getSignalValue(const QString& path, QJsonArray& values)
{
    // Check if path is single leaf.
    // Check if path is single branch.
    // Check if path contains asterisk.
    // Check if path contains asterisk and leaf.
    QJsonArray paths = parseGetPath(path);

    // Check if signal exists.
    if(!checkSignals(paths, true)) { return false; }

    // Create message to send
    QJsonObject message;
    message.insert("get", paths);
    QJsonDocument jsonDoc(message);

    // Lock and send message.
    QMutexLocker locker(&m_mutex);
    sendMessage(jsonDoc.toJson());

    // TODO Need to implement some kind of timer here.
    while(!m_messageReceivedFromBroker)
    {
        //DEBUG("TEST","Waiting for response...");
    }

    jsonDoc = QJsonDocument(m_receivedMessage);

    // TODO Add check of Success in response.
    // Could just return false, instead of array, if error?
    if(jsonDoc.object()["get"].isArray())
    {
        values = jsonDoc.object()["get"].toArray();
        return true;
    }
    return false;
}

bool WebSocketBroker::setSignalValue(const QString& path, const QVariant& values)
{
    QJsonArray paths = parseSetPath(path, values.toJsonValue());

    // Check if signal exists.
    if(!checkSignals(paths, false)) { return false; }

    // Create message to send
    QJsonObject message;
    message.insert("set", paths);
    QJsonDocument jsonDoc(message);

    // Lock and send message.
    QMutexLocker locker(&m_mutex);
    sendMessage(jsonDoc.toJson());

    // TODO Need to implement some kind of timer here.
    while(!m_messageReceivedFromBroker)
    {
        //DEBUG("TEST","Waiting for response...");
    }

    jsonDoc = QJsonDocument(m_receivedMessage);

    // Should return false, or 0 if not bool. So should work without checking if bool
    return jsonDoc.object()["set"].toBool();
}

QJsonObject WebSocketBroker::getVSSNode(const QString& path)
{

    // clear old
    m_vssTreeNode = QJsonObject();

    if (m_vssTree.empty())
    {
        DEBUG("Server","Empty VSS tree. Returning empty node.");
        return m_vssTreeNode;
    }
    else if (path == "")
    {
        DEBUG("Server","Empty path. Returning full tree.");
        return m_vssTree;
    }
    else
    {
        QStringList tokens = path.split('.');

        // Make a copy of the full tree
        QJsonObject tree = m_vssTree;

        QVector<JsonNode> nodes;
        getTreeNodes(tree, tokens, nodes);

        QJsonObject obj;
        createJsonVssTree(nodes, obj);

        return m_vssTreeNode;
    }
}

QJsonObject WebSocketBroker::getVSSTree(const QString& path)
{
    QString p = path;
    QJsonObject tree;
    return tree;
}

void WebSocketBroker::sendMessage(const QString& message)
{
    m_messageReceivedFromBroker = false;
    m_webSocket.sendTextMessage(message);
    m_webSocket.flush();
}

void WebSocketBroker::onConnected()
{
    connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &WebSocketBroker::onTextMessageReceived);
}

void WebSocketBroker::onTextMessageReceived(QString message)
{
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &parseError);
    if(parseError.error != QJsonParseError::NoError)
    {
        m_receivedMessage = doc.object(); // Change to error.
        m_messageReceivedFromBroker = true;
        return;
    }
    m_receivedMessage = doc.object();
    m_messageReceivedFromBroker = true;
}

void WebSocketBroker::getTreeNodes(QJsonObject& tree, QStringList& path, QVector<JsonNode>& nodes)
{
    if (path.length() > 0)
    {
        QString key = path[0];
        JsonNode node;
        node.isBranch = path.length() > 1;
        node.key = key;

        if (node.isBranch)
        {
            removeAllKeysButOne(tree, key);
        }

        tree = tree.value(key).toObject();

        QJsonObject treeCopy = tree;

        if (node.isBranch)
        {
            removeOne(treeCopy, "children");
            tree = tree.value("children").toObject();
        }

        node.json = treeCopy;

        nodes.push_front(node);

        path.removeFirst();
        getTreeNodes(tree, path, nodes);
    }
}

void WebSocketBroker::createJsonVssTree(QVector<JsonNode>& nodes, QJsonObject& json)
{

    if (nodes.size() > 0)
    {
        JsonNode node = nodes.first();
        QJsonObject obj;

        if (node.isBranch)
        {
            node.json.insert("children", json);
            obj.insert(node.key, node.json);
        }
        else
        {
            obj.insert(node.key, node.json);
        }

        nodes.removeFirst();
        createJsonVssTree(nodes, obj);
    }
    else
    {
        m_vssTreeNode = json;
    }
}

void WebSocketBroker::removeAllKeysButOne(QJsonObject& json, const QString& filter)
{
    foreach (QString key, json.keys())
    {
        if (filter != key)
        {
            json.remove(key);
        }
    }
}

void WebSocketBroker::removeOne(QJsonObject& json, const QString& filter)
{
    foreach (QString key, json.keys())
    {
        if (filter == key)
        {
            json.remove(key);
        }
    }
}

void WebSocketBroker::loadJson(const QString &fileName)
{
    QFile jsonFile(fileName);
    QJsonDocument doc;

    if (jsonFile.exists())
    {
        jsonFile.open(QFile::ReadOnly);
        doc = QJsonDocument().fromJson(jsonFile.readAll());
    }
    else
    {
        WARNING("Server",QString("VSS File %1 not found!").arg(fileName));
    }

    m_vssTree = doc.object();
}

void WebSocketBroker::loadTempSignalList()
{
    QRegularExpression regex(QString("^(\\S+) \\d+"));

    QFile file(QCoreApplication::applicationDirPath() + "/vss_rel_1.vsi");
    file.open(QFile::ReadOnly);
    if(!file.exists())
    {
        WARNING("Server", "The flattened vsi signal file could not be found for the Signal Broker!");
        file.close();
        return;
    }
    while(!file.atEnd())
    {
        QRegularExpressionMatch match = regex.match(file.readLine());
        if(match.hasMatch()) { m_tempSignalList.append(match.captured(1).trimmed()); }
    }
}

QJsonArray WebSocketBroker::parseGetPath(const QString& path)
{
    QStringList sl = splitPath(path);
    QJsonArray values;

    if(sl.length() == 1)
        foreach(auto const item, getPath(sl.first()))
    {
        QJsonObject value;
        value.insert(item,"");
        values.append(value);
    }
    else
        foreach(auto const item, getPath(sl.first(), sl.last()))
    {
        QJsonObject value;
        value.insert(item,"");
        values.append(value);
    }

    return values;
}

QJsonArray WebSocketBroker::parseSetPath(const QString& path, const QJsonValue &setValues)
{
    QStringList sl = splitPath(path);
    QJsonArray values;

    if(setValues.isArray())
    {
        foreach(QJsonValue const val, setValues.toArray())
        {
            QJsonObject value;
            QJsonObject obj = val.toObject();

            QString valuePath = sl.first() + "." + obj.keys().first();
            QJsonValue tmp = obj.value(obj.keys().first());

            if(tmp.isDouble())
            {
                value.insert(valuePath, tmp.toDouble());
            }
            else if(tmp.isBool())
            {
                value.insert(valuePath, tmp.toBool());
            }
            else
            {
                value.insert(valuePath, tmp.toString());
            }

            values.append(value);
        }
    }
    else
    {
        QJsonObject value;

        if(setValues.isDouble())
        {
            value.insert(path, setValues.toDouble());
        }
        else if(setValues.isBool())
        {
            value.insert(path, setValues.toBool());
        }
        else
        {
            value.insert(path, setValues.toString());
        }

        values .append(value);
    }

    return values;
}

bool WebSocketBroker::checkSignals(const QJsonArray &paths, bool getOrSet)
{
    foreach (QJsonValue const &obj, paths)
    {
        foreach (QJsonValue key, obj.toObject().keys())
        {
            QJsonObject signal = getVSSNode(key.toString());
            if(signal.isEmpty()) { return false; }

            if(getOrSet)
            {
                // TODO Check if the signal is ok to get
            }
            else
            {
                // TODO Check if the signal is ok to set
                // Check if set is correct type
            }
        }
    }
    return true;
}

QStringList WebSocketBroker::getPath(QString startsWith)
{
    return getPath(startsWith, "");
}

QStringList WebSocketBroker::getPath(QString startsWith, QString endsWith)
{
    return m_tempSignalList.filter(QRegularExpression(QString("^%1.*%2$").arg(startsWith, endsWith)));
}

QStringList WebSocketBroker::splitPath(QString path)
{
    QStringList sl;
    int i = path.lastIndexOf("*");
    if(i == -1) { sl << path; return sl; }

    foreach(QString item, path.split("*"))
    {
        // Trim '.' from items.
        if(item.startsWith(".")) { item = item.remove(0,1); }
        if(item.endsWith(".")) { item = item.remove(item.length() -1, 1); }

        sl << item;
    }
    return sl;
}
<|endoftext|>


<commit_before>/*
 * opencog/atoms/core/Checkers.cc
 *
 * Copyright (C) 2017 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/Atom.h>
#include <opencog/atoms/base/ClassServer.h>

using namespace opencog;

/// Provide static factory-time type checking.
/// This only performs a very simple kind of type checking;
/// it does not check deep types, nor does it check arity.

/// Check to see if every input atom is of Evaluatable type.
bool check_evaluatable(const Handle& bool_atom)
{
	// Make an exception for AndLink, its used in pattern matcher
	// in an unseemly way.
	if (bool_atom->get_type() == AND_LINK) return true;

	for (const Handle& h: bool_atom->getOutgoingSet())
	{
		Type t = h->get_type();
		// PutLinks and GetLinks cannot be type-checked statically.
		// Checking has to be defered until runtime.
		if (PUT_LINK == t) continue;
		if (GET_LINK == t) continue;
		if (VARIABLE_NODE == t) continue;

		// Fucking quote links. I hate those with a passion.
		if (QUOTE_LINK == t) continue;
		if (UNQUOTE_LINK == t) continue;

		if (not h->is_type(EVALUATABLE_LINK)) return false;
	}
	return true;
}

/// Check to see if every input atom is of Numeric type.
bool check_numeric(const Handle& bool_atom)
{
	for (const Handle& h: bool_atom->getOutgoingSet())
	{
		Type t = h->get_type();
		// PutLinks and GetLinks cannot be type-checked statically.
		// Checking has to be defered until runtime.
		if (PUT_LINK == t) continue;
		if (GET_LINK == t) continue;
		if (VARIABLE_NODE == t) continue;
		if (NUMBER_NODE == t) continue;

		// Oddly enough, sets of numbers are allowed.
		if (SET_LINK == t and check_numeric(h)) continue;

		if (not h->is_type(NUMERIC_OUTPUT_LINK)) return false;
	}
	return true;
}

/* This runs when the shared lib is loaded. */
static __attribute__ ((constructor)) void init(void)
{
	classserver().addValidator(BOOLEAN_LINK, check_evaluatable);
	classserver().addValidator(NUMERIC_LINK, check_numeric);
}
<commit_msg>Another allowed type<commit_after>/*
 * opencog/atoms/core/Checkers.cc
 *
 * Copyright (C) 2017 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/Atom.h>
#include <opencog/atoms/base/ClassServer.h>

using namespace opencog;

/// Provide static factory-time type checking.
/// This only performs a very simple kind of type checking;
/// it does not check deep types, nor does it check arity.

/// Check to see if every input atom is of Evaluatable type.
bool check_evaluatable(const Handle& bool_atom)
{
	// Make an exception for AndLink, its used in pattern matcher
	// in an unseemly way.
	if (bool_atom->get_type() == AND_LINK) return true;

	for (const Handle& h: bool_atom->getOutgoingSet())
	{
		Type t = h->get_type();
		// PutLinks and GetLinks cannot be type-checked statically.
		// Checking has to be defered until runtime.
		if (PUT_LINK == t) continue;
		if (GET_LINK == t) continue;
		if (VARIABLE_NODE == t) continue;
		if (DEFINED_PREDICATE_NODE == t) continue;

		// Fucking quote links. I hate those with a passion.
		if (QUOTE_LINK == t) continue;
		if (UNQUOTE_LINK == t) continue;

		if (not h->is_type(EVALUATABLE_LINK)) return false;
	}
	return true;
}

/// Check to see if every input atom is of Numeric type.
bool check_numeric(const Handle& bool_atom)
{
	for (const Handle& h: bool_atom->getOutgoingSet())
	{
		Type t = h->get_type();
		// PutLinks and GetLinks cannot be type-checked statically.
		// Checking has to be defered until runtime.
		if (PUT_LINK == t) continue;
		if (GET_LINK == t) continue;
		if (VARIABLE_NODE == t) continue;
		if (NUMBER_NODE == t) continue;

		// Oddly enough, sets of numbers are allowed.
		if (SET_LINK == t and check_numeric(h)) continue;

		if (not h->is_type(NUMERIC_OUTPUT_LINK)) return false;
	}
	return true;
}

/* This runs when the shared lib is loaded. */
static __attribute__ ((constructor)) void init(void)
{
	classserver().addValidator(BOOLEAN_LINK, check_evaluatable);
	classserver().addValidator(NUMERIC_LINK, check_numeric);
}
<|endoftext|>


<commit_before>// Do nothing, if no thread support
#ifdef QT_THREAD_SUPPORT

#include "threads.h"
#include "mainframe.h"
#include <BALL/MOLMEC/MINIMIZATION/energyMinimizer.h>
#include <BALL/MOLMEC/MDSIMULATION/molecularDynamics.h>
#include <BALL/VIEW/WIDGETS/scene.h>
#include <BALL/MOLMEC/AMBER/amber.h>

namespace BALL
{
	using namespace VIEW;

SimulationThread::SimulationThread()
	: QThread(),
		main_frame_(0),
		dcd_file_(0),
		composite_(0)
{
}

void SimulationThread::run()
{
	// overloaded in derived classes
}

void SimulationThread::updateScene_()
{
	Mainframe::UpdateCompositeEvent* se = new Mainframe::UpdateCompositeEvent;
	se->setComposite(composite_);
	postEvent(main_frame_, se);

	/*
	// old behavior: no rebuilding of surfaces
	Scene* scene= (Scene*) Scene::getInstance(0);
	Scene::SceneUpdateEvent* su = new Scene::SceneUpdateEvent;
	postEvent(scene, su);  // Qt will delete it when done
	*/
}

void SimulationThread::output_(const String& string)
{
	Mainframe::SimulationOutput* su = new Mainframe::SimulationOutput;
	su->setMessage(string);
	postEvent(main_frame_, su);  // Qt will delete it when done
}

void SimulationThread::outputAmberResult_(const AmberFF& amber)
{
	output_(
		"\nAMBER Energy:\n"
		" - electrostatic     : " + String(amber.getESEnergy()) + " kJ/mol\n" +
		" - van der Waals     : " + String(amber.getVdWEnergy()) + " kJ/mol\n" +
		" - bond stretch      : " + String(amber.getStretchEnergy()) + " kJ/mol\n" +
		" - angle bend        : " + String(amber.getBendEnergy()) + " kJ/mol\n" +
		" - torsion           : " + String(amber.getTorsionEnergy()) + " kJ/mol\n"+
		"---------------------------------------\n" +
		"  total energy       : " + String(amber.getEnergy()) + " kJ/mol\n"
	);
}

void SimulationThread::finish_()
{
	Mainframe::SimulationThreadFinished* su = new Mainframe::SimulationThreadFinished;
	postEvent(main_frame_, su);  // Qt will delete it when done
}

void EnergyMinimizerThread::run()
{
	if (minimizer_ == 0 ||
			minimizer_->getForceField() == 0 ||
			minimizer_->getForceField()->getSystem() == 0 ||
			main_frame_ == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}
	AmberFF& amber =*(AmberFF*)minimizer_->getForceField();

	// iterate until done and refresh the screen every "steps" iterations
	while (!minimizer_->minimize(steps_between_updates_, true) &&
					minimizer_->getNumberOfIterations() < minimizer_->getMaxNumberOfIterations() &&
				 !main_frame_->stopedSimulation())
	{
		updateScene_();
		msleep(90);

		QString message;
		message.sprintf("Iteration %d: energy = %f kJ/mol, RMS gradient = %f kJ/mol A",
										minimizer_->getNumberOfIterations(),
										amber.getEnergy(), amber.getRMSGradient());
		output_(message.ascii());
	}

	outputAmberResult_(amber);
	output_("final RMS gadient    : " + String(amber.getRMSGradient()) + " kJ/(mol A)   after "
					+ String(minimizer_->getNumberOfIterations()) + " iterations\n");
	finish_();
}

EnergyMinimizerThread::EnergyMinimizerThread()
	: SimulationThread(),
		minimizer_(0)
{
}

EnergyMinimizerThread::~EnergyMinimizerThread()
{
	if (minimizer_ != 0)
	{
		delete minimizer_;
	}
}

void EnergyMinimizerThread::setEnergyMinimizer(EnergyMinimizer* minimizer)
{
	if (minimizer_ != 0)
	{
		delete minimizer_;
	}
	minimizer_ = minimizer;
}

// =====================================================
void MDSimulationThread::run()
	throw(Exception::NullPointer)
{
	if (md_ == 0 ||
			md_->getForceField() == 0 ||
			md_->getForceField()->getSystem() == 0 ||
			main_frame_ == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}
	AmberFF& amber =*(AmberFF*)md_->getForceField();

	SnapShotManager manager(amber.getSystem(), &amber, dcd_file_);
	manager.setFlushToDiskFrequency(10);
	// iterate until done and refresh the screen every "steps" iterations

	while (md_->getNumberOfIterations() < steps_ &&
				 !main_frame_->stopedSimulation())
	{
		md_->simulateIterations(steps_between_updates_, true);
		updateScene_();

		QString message;
		message.sprintf("Iteration %d: energy = %f kJ/mol, RMS gradient = %f kJ/mol A",
										md_->getNumberOfIterations(), amber.getEnergy(),
										amber.getRMSGradient());
		output_(message.ascii());

		msleep(90);

		if (save_images_)
		{
			Scene* scene= (Scene*) Scene::getInstance(0);
			scene->exportPNG();
		}

		if (dcd_file_) manager.takeSnapShot();
	}

	if (dcd_file_) manager.flushToDisk();

	outputAmberResult_(*(AmberFF*)md_->getForceField());
	output_("final RMS gadient    : " + String(amber.getRMSGradient()) + " kJ/(mol A)   after "
					+ String(md_->getNumberOfIterations()) + " iterations\n");
	finish_();
}

MDSimulationThread::MDSimulationThread()
	: SimulationThread(),
		md_(0),
		save_images_(false)
{
}

MDSimulationThread::~MDSimulationThread()
{
	if (md_ != 0)
	{
		delete md_;
	}
}

void MDSimulationThread::setMolecularDynamics(MolecularDynamics* md)
{
	if (md_ != 0)
	{
		delete md_;
	}

	md_ = md;
}

}
#endif //Thread support
<commit_msg>fixed postEvent -> qApp->postEvent<commit_after>// Do nothing, if no thread support
#ifdef QT_THREAD_SUPPORT

#include "threads.h"
#include "mainframe.h"
#include <BALL/MOLMEC/MINIMIZATION/energyMinimizer.h>
#include <BALL/MOLMEC/MDSIMULATION/molecularDynamics.h>
#include <BALL/VIEW/WIDGETS/scene.h>
#include <BALL/MOLMEC/AMBER/amber.h>

namespace BALL
{
	using namespace VIEW;

SimulationThread::SimulationThread()
	: QThread(),
		main_frame_(0),
		dcd_file_(0),
		composite_(0)
{
}

void SimulationThread::run()
{
	// overloaded in derived classes
}

void SimulationThread::updateScene_()
{
	Mainframe::UpdateCompositeEvent* se = new Mainframe::UpdateCompositeEvent;
	se->setComposite(composite_);
	qApp->postEvent(main_frame_, se);

	/*
	// old behavior: no rebuilding of surfaces
	Scene* scene= (Scene*) Scene::getInstance(0);
	Scene::SceneUpdateEvent* su = new Scene::SceneUpdateEvent;
	qApp->postEvent(scene, su);  // Qt will delete it when done
	*/
}

void SimulationThread::output_(const String& string)
{
	Mainframe::SimulationOutput* su = new Mainframe::SimulationOutput;
	su->setMessage(string);
	qApp->postEvent(main_frame_, su);  // Qt will delete it when done
}

void SimulationThread::outputAmberResult_(const AmberFF& amber)
{
	output_(
		"\nAMBER Energy:\n"
		" - electrostatic     : " + String(amber.getESEnergy()) + " kJ/mol\n" +
		" - van der Waals     : " + String(amber.getVdWEnergy()) + " kJ/mol\n" +
		" - bond stretch      : " + String(amber.getStretchEnergy()) + " kJ/mol\n" +
		" - angle bend        : " + String(amber.getBendEnergy()) + " kJ/mol\n" +
		" - torsion           : " + String(amber.getTorsionEnergy()) + " kJ/mol\n"+
		"---------------------------------------\n" +
		"  total energy       : " + String(amber.getEnergy()) + " kJ/mol\n"
	);
}

void SimulationThread::finish_()
{
	Mainframe::SimulationThreadFinished* su = new Mainframe::SimulationThreadFinished;
	qApp->postEvent(main_frame_, su);  // Qt will delete it when done
}

void EnergyMinimizerThread::run()
{
	if (minimizer_ == 0 ||
			minimizer_->getForceField() == 0 ||
			minimizer_->getForceField()->getSystem() == 0 ||
			main_frame_ == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}
	AmberFF& amber =*(AmberFF*)minimizer_->getForceField();

	// iterate until done and refresh the screen every "steps" iterations
	while (!minimizer_->minimize(steps_between_updates_, true) &&
					minimizer_->getNumberOfIterations() < minimizer_->getMaxNumberOfIterations() &&
				 !main_frame_->stopedSimulation())
	{
		updateScene_();
		msleep(90);

		QString message;
		message.sprintf("Iteration %d: energy = %f kJ/mol, RMS gradient = %f kJ/mol A",
										minimizer_->getNumberOfIterations(),
										amber.getEnergy(), amber.getRMSGradient());
		output_(message.ascii());
	}

	outputAmberResult_(amber);
	output_("final RMS gadient    : " + String(amber.getRMSGradient()) + " kJ/(mol A)   after "
					+ String(minimizer_->getNumberOfIterations()) + " iterations\n");
	finish_();
}

EnergyMinimizerThread::EnergyMinimizerThread()
	: SimulationThread(),
		minimizer_(0)
{
}

EnergyMinimizerThread::~EnergyMinimizerThread()
{
	if (minimizer_ != 0)
	{
		delete minimizer_;
	}
}

void EnergyMinimizerThread::setEnergyMinimizer(EnergyMinimizer* minimizer)
{
	if (minimizer_ != 0)
	{
		delete minimizer_;
	}
	minimizer_ = minimizer;
}

// =====================================================
void MDSimulationThread::run()
	throw(Exception::NullPointer)
{
	if (md_ == 0 ||
			md_->getForceField() == 0 ||
			md_->getForceField()->getSystem() == 0 ||
			main_frame_ == 0)
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}
	AmberFF& amber =*(AmberFF*)md_->getForceField();

	SnapShotManager manager(amber.getSystem(), &amber, dcd_file_);
	manager.setFlushToDiskFrequency(10);
	// iterate until done and refresh the screen every "steps" iterations

	while (md_->getNumberOfIterations() < steps_ &&
				 !main_frame_->stopedSimulation())
	{
		md_->simulateIterations(steps_between_updates_, true);
		updateScene_();

		QString message;
		message.sprintf("Iteration %d: energy = %f kJ/mol, RMS gradient = %f kJ/mol A",
										md_->getNumberOfIterations(), amber.getEnergy(),
										amber.getRMSGradient());
		output_(message.ascii());

		msleep(90);

		if (save_images_)
		{
			Scene* scene= (Scene*) Scene::getInstance(0);
			scene->exportPNG();
		}

		if (dcd_file_) manager.takeSnapShot();
	}

	if (dcd_file_) manager.flushToDisk();

	outputAmberResult_(*(AmberFF*)md_->getForceField());
	output_("final RMS gadient    : " + String(amber.getRMSGradient()) + " kJ/(mol A)   after "
					+ String(md_->getNumberOfIterations()) + " iterations\n");
	finish_();
}

MDSimulationThread::MDSimulationThread()
	: SimulationThread(),
		md_(0),
		save_images_(false)
{
}

MDSimulationThread::~MDSimulationThread()
{
	if (md_ != 0)
	{
		delete md_;
	}
}

void MDSimulationThread::setMolecularDynamics(MolecularDynamics* md)
{
	if (md_ != 0)
	{
		delete md_;
	}

	md_ = md;
}

}
#endif //Thread support
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// transaction_test.cpp
//
// Identification: tests/concurrency/transaction_test.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "harness.h"
#include "concurrency/transaction_tests_util.h"

namespace peloton {

namespace test {

//===--------------------------------------------------------------------===//
// Transaction Tests
//===--------------------------------------------------------------------===//

class TransactionTests : public PelotonTest {};

static std::vector<ConcurrencyType> TEST_TYPES = {CONCURRENCY_TYPE_OCC,
                                                  CONCURRENCY_TYPE_2PL};

void TransactionTest(concurrency::TransactionManager *txn_manager) {
  uint64_t thread_id = TestingHarness::GetInstance().GetThreadId();

  for (oid_t txn_itr = 1; txn_itr <= 50; txn_itr++) {
    txn_manager->BeginTransaction();
    if (thread_id % 2 == 0) {
      std::chrono::microseconds sleep_time(1);
      std::this_thread::sleep_for(sleep_time);
    }

    if (txn_itr % 25 != 0) {
      txn_manager->CommitTransaction();
    } else {
      txn_manager->AbortTransaction();
    }
  }
}

TEST_F(TransactionTests, TransactionTest) {
  for (auto test_type : TEST_TYPES) {
    concurrency::TransactionManagerFactory::Configure(test_type);
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

    LaunchParallelTest(8, TransactionTest, &txn_manager);

    std::cout << "next Commit Id :: " << txn_manager.GetNextCommitId() << "\n";
  }
}

TEST_F(TransactionTests, AbortTest) {
  for (auto test_type : TEST_TYPES) {
    concurrency::TransactionManagerFactory::Configure(test_type);
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    std::unique_ptr<storage::DataTable> table(
        TransactionTestsUtil::CreateTable());
    {
      TransactionScheduler scheduler(2, table.get(), &txn_manager);
      scheduler.Txn(0).Update(0, 100);
      scheduler.Txn(0).Abort();
      scheduler.Txn(1).Read(0);
      scheduler.Txn(1).Commit();

      scheduler.Run();

      EXPECT_EQ(RESULT_ABORTED, scheduler.schedules[0].txn_result);
      EXPECT_EQ(RESULT_SUCCESS, scheduler.schedules[1].txn_result);
      EXPECT_EQ(0, scheduler.schedules[1].results[0]);
    }

    {
      TransactionScheduler scheduler(2, table.get(), &txn_manager);
      // scheduler.AddInsert(0, 100, 0);
      scheduler.Txn(0).Abort();
      scheduler.Txn(1).Read(1);
      scheduler.Txn(1).Commit();

      scheduler.Run();
      EXPECT_EQ(RESULT_ABORTED, scheduler.schedules[0].txn_result);
      EXPECT_EQ(RESULT_SUCCESS, scheduler.schedules[1].txn_result);
      EXPECT_EQ(-1, scheduler.schedules[1].results[0]);
    }
  }
}

}  // End test namespace
}  // End peloton namespace
<commit_msg>fix abort test<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// transaction_test.cpp
//
// Identification: tests/concurrency/transaction_test.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "harness.h"
#include "concurrency/transaction_tests_util.h"

namespace peloton {

namespace test {

//===--------------------------------------------------------------------===//
// Transaction Tests
//===--------------------------------------------------------------------===//

class TransactionTests : public PelotonTest {};

static std::vector<ConcurrencyType> TEST_TYPES = {CONCURRENCY_TYPE_OCC,
                                                  CONCURRENCY_TYPE_2PL};

void TransactionTest(concurrency::TransactionManager *txn_manager) {
  uint64_t thread_id = TestingHarness::GetInstance().GetThreadId();

  for (oid_t txn_itr = 1; txn_itr <= 50; txn_itr++) {
    txn_manager->BeginTransaction();
    if (thread_id % 2 == 0) {
      std::chrono::microseconds sleep_time(1);
      std::this_thread::sleep_for(sleep_time);
    }

    if (txn_itr % 25 != 0) {
      txn_manager->CommitTransaction();
    } else {
      txn_manager->AbortTransaction();
    }
  }
}

TEST_F(TransactionTests, TransactionTest) {
  for (auto test_type : TEST_TYPES) {
    concurrency::TransactionManagerFactory::Configure(test_type);
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

    LaunchParallelTest(8, TransactionTest, &txn_manager);

    std::cout << "next Commit Id :: " << txn_manager.GetNextCommitId() << "\n";
  }
}

TEST_F(TransactionTests, SingleTransactionTest) {
  for (auto test_type : TEST_TYPES) {
    concurrency::TransactionManagerFactory::Configure(test_type);
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    std::unique_ptr<storage::DataTable> table(
        TransactionTestsUtil::CreateTable());
    // read, read, read, read
    {
      TransactionScheduler scheduler(1, table.get(), &txn_manager);
      scheduler.Txn(0).Read(0);
      scheduler.Txn(0).Read(0);
      scheduler.Txn(0).Read(0);
      scheduler.Txn(0).Read(0);
      scheduler.Txn(0).Commit();

      scheduler.Run();

      EXPECT_EQ(RESULT_SUCCESS, scheduler.schedules[0].txn_result);
      EXPECT_EQ(0, scheduler.schedules[0].results[0]);
      EXPECT_EQ(0, scheduler.schedules[0].results[1]);
      EXPECT_EQ(0, scheduler.schedules[0].results[2]);
      EXPECT_EQ(0, scheduler.schedules[0].results[3]);
    }

  }
}

TEST_F(TransactionTests, AbortTest) {
  for (auto test_type : TEST_TYPES) {
    concurrency::TransactionManagerFactory::Configure(test_type);
    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    std::unique_ptr<storage::DataTable> table(
        TransactionTestsUtil::CreateTable());
    {
      TransactionScheduler scheduler(2, table.get(), &txn_manager);
      scheduler.Txn(0).Update(0, 100);
      scheduler.Txn(0).Abort();
      scheduler.Txn(1).Read(0);
      scheduler.Txn(1).Commit();

      scheduler.Run();

      EXPECT_EQ(RESULT_ABORTED, scheduler.schedules[0].txn_result);
      EXPECT_EQ(RESULT_SUCCESS, scheduler.schedules[1].txn_result);
      EXPECT_EQ(0, scheduler.schedules[1].results[0]);
    }

    {
      TransactionScheduler scheduler(2, table.get(), &txn_manager);
      scheduler.Txn(0).Insert(100, 0);
      scheduler.Txn(0).Abort();
      scheduler.Txn(1).Read(100);
      scheduler.Txn(1).Commit();

      scheduler.Run();
      EXPECT_EQ(RESULT_ABORTED, scheduler.schedules[0].txn_result);
      EXPECT_EQ(RESULT_SUCCESS, scheduler.schedules[1].txn_result);
      EXPECT_EQ(-1, scheduler.schedules[1].results[0]);
    }
  }
}

}  // End test namespace
}  // End peloton namespace
<|endoftext|>


<commit_before>/*
 * Chrome Token Signing Native Host
 *
 * 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 "PKCS11Path.h"
#include "BinaryUtils.h"
#include "Logger.h"

#ifdef _WIN32
#undef UNICODE
#include <Shlobj.h>
#include <Shlwapi.h>
#include <Knownfolders.h>
#include <winscard.h>
#elif defined __APPLE__
#include <PCSC/winscard.h>
#include <PCSC/wintypes.h>
#include <unistd.h>
#else
#include <winscard.h>
#include <unistd.h>
#endif

#include <cstring>
#include <map>

std::vector<std::string> PKCS11Path::atrList() {
	SCARDCONTEXT hContext = 0;
	std::vector<std::string> result;
	LONG err = SCardEstablishContext(SCARD_SCOPE_USER, nullptr, nullptr, &hContext);
	if (err != SCARD_S_SUCCESS) {
		_log("SCardEstablishContext ERROR: %x", err);
		return result;
	}

	DWORD size = 0;
	err = SCardListReaders(hContext, nullptr, nullptr, &size);
	if (err != SCARD_S_SUCCESS || !size) {
		_log("SCardListReaders || !size ERROR: %x", err);
		SCardReleaseContext(hContext);
		return result;
	}

	std::string readers(size, 0);
	err = SCardListReaders(hContext, nullptr, &readers[0], &size);
	readers.resize(size);
	if (err != SCARD_S_SUCCESS) {
		_log("SCardListReaders ERROR: %x", err);
		SCardReleaseContext(hContext);
		return result;
	}

    std::vector<SCARD_READERSTATE> list;
    for (const char *name = readers.c_str(); *name; name += strlen(name) + 1) {
        _log("found reader: %s", name);
        list.push_back({ name, nullptr, 0, 0, 0, {} });
    }

    err = SCardGetStatusChange(hContext, 0, list.data(), DWORD(list.size()));
    if (err != SCARD_S_SUCCESS)
        _log("SCardGetStatusChange ERROR: %x", err);
    for(const SCARD_READERSTATE &state: list)
    {
        if (state.dwEventState & SCARD_STATE_PRESENT)
        {
            std::string atr = BinaryUtils::bin2hex(state.rgbAtr, state.cbAtr);
            result.push_back(atr);
            _log("Set ATR = %s for reader %s", atr.c_str(), state.szReader);
        }
    }

    SCardReleaseContext(hContext);
    return result;
}

PKCS11Path::Params PKCS11Path::getPkcs11ModulePath() {
#ifdef _WIN32
    // Use PKCS11 driver on windows to avoid PIN buffering
    static const std::string litPath = [] {
        PWSTR programFilesX86 = 0;
        SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, 0, nullptr, &programFilesX86);
        std::wstring path = programFilesX86;
        CoTaskMemFree(programFilesX86);
        if (PathFileExistsW((path + L"\\PWPW\\pwpw-card-pkcs11.dll").c_str()))
            path += L"\\PWPW\\pwpw-card-pkcs11.dll";
        else
            path += L"\\CryptoTech\\CryptoCard\\CCPkiP11.dll";
        int size = WideCharToMultiByte(CP_UTF8, 0, path.c_str(), DWORD(path.size()), nullptr, 0, nullptr, nullptr);
        std::string result(size, 0);
        WideCharToMultiByte(CP_UTF8, 0, path.c_str(), DWORD(path.size()), &result[0], size, nullptr, nullptr);
        return result;
    }();
#elif defined __APPLE__
    static const std::string openscPath("/Library/OpenSC/lib/opensc-pkcs11.so");
    static const std::string estPath = openscPath;
    static const std::string latPath("/Library/latvia-eid/lib/otlv-pkcs11.so");
    static const std::string finPath("/Library/mPolluxDigiSign/libcryptoki.dylib");
    static const std::string lit1Path("/Library/Security/tokend/CCSuite.tokend/Contents/Frameworks/libccpkip11.dylib");
    static const std::string lit2Path("/Library/PWPW-Card/pwpw-card-pkcs11.so");
    static const std::string litPath = access(lit1Path.c_str(), F_OK) == 0 ? lit1Path : lit2Path;
    static const std::string belPath("/usr/local/lib/beid-pkcs11.bundle/Contents/MacOS/libbeidpkcs11.dylib");
    static const std::string eTokenPath("/Library/Frameworks/eToken.framework/Versions/Current/libeToken.dylib");
    static const std::string ocsPath("/Library/AWP/lib/libOcsCryptoki.dylib");
#else
    static const std::string openscPath("opensc-pkcs11.so");
    static const std::string estPath = openscPath;
    static const std::string latPath("otlv-pkcs11.so");
    static const std::string finPath("libcryptoki.so");
    static const std::string lit1Path("/usr/lib/ccs/libccpkip11.so");
    static const std::string lit2Path("pwpw-card-pkcs11.so");
    static const std::string litPath = access(lit1Path.c_str(), F_OK) == 0 ? lit1Path : lit2Path;
    static const std::string belPath("libbeidpkcs11.so.0");
    static const std::string eTokenPath("/usr/local/lib/libeTPkcs11.so");
    static const std::string ocsPath("/usr/local/AWP/lib/libOcsCryptoki.so");
#endif
    static const std::map<std::string, Params> m = {
#ifdef _WIN32
        {"3BFD1800008031FE4553434536302D43443134352D46CD", {"C:\\Windows\\System32\\aetpkss1.dll", "PIN", "PIN"}},
#else
        {"3BFE1800008031FE454573744549442076657220312E30A8", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3_COLD_DEV1_ATR
        {"3BFE1800008031FE45803180664090A4561B168301900086", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3_WARM_DEV1_ATR
        {"3BFE1800008031FE45803180664090A4162A0083019000E1", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3_WARM_DEV2_ATR
        {"3BFE1800008031FE45803180664090A4162A00830F9000EF", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3_WARM_DEV3_ATR
        {"3BFA1800008031FE45FE654944202F20504B4903", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3.5_COLD_ATR

        {"3BDD18008131FE45904C41545649412D65494490008C", {latPath, "PIN1", "PIN2"}},

        {"3B7B940000806212515646696E454944", {finPath, "PIN1", "PIN2"}},
        {"3B7F9600008031B865B0850300EF1200F6829000", {finPath, "PIN1", "PIN2"}},

        {"3B9813400AA503010101AD1311", {belPath, "PIN", "PIN"}},

        {"3BD5180081313A7D8073C8211030", {eTokenPath, "PIN", "PIN"}},
        {"3BD518008131FE7D8073C82110F4", {eTokenPath, "PIN", "PIN"}},

        {"3BDB960080B1FE451F830012233F536549440F9000F1", {ocsPath, "PIN1", "PIN2"}},
#endif
        {"3BF81300008131FE45536D617274417070F8", {litPath, "PIN", "PIN"}},
        {"3B7D94000080318065B08311C0A983009000", {litPath, "PIN", "PIN"}},
        {"3B7D94000080318065B0831100C883009000", {litPath, "PIN", "PIN"}},
        {"3B9F9681B1FE451F070064051EB20031B0739621DB00900050", {litPath, "PIN", "PIN"}},
        {"3B9F90801FC30068104405014649534531C800000000", {litPath, "PIN", "PIN"}},
    };

    const std::vector<std::string> list = atrList();
    for (const std::string &atr : list) {
        auto it = m.find(atr);
        if (it != m.end())
            return it->second;
    }
#ifdef _WIN32
    return Params();
#else
    if (!list.empty())
        _log("Unknown ATR '%s' using default module '%s'", list[0].c_str(), openscPath.c_str());
    return {openscPath, "PIN", "PIN"};
#endif
}
<commit_msg>Fix linux module path (#129) (#130)<commit_after>/*
 * Chrome Token Signing Native Host
 *
 * 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 "PKCS11Path.h"
#include "BinaryUtils.h"
#include "Logger.h"

#ifdef _WIN32
#undef UNICODE
#include <Shlobj.h>
#include <Shlwapi.h>
#include <Knownfolders.h>
#include <winscard.h>
#elif defined __APPLE__
#include <PCSC/winscard.h>
#include <PCSC/wintypes.h>
#include <unistd.h>
#else
#include <winscard.h>
#include <unistd.h>
#endif

#include <cstring>
#include <map>

std::vector<std::string> PKCS11Path::atrList() {
	SCARDCONTEXT hContext = 0;
	std::vector<std::string> result;
	LONG err = SCardEstablishContext(SCARD_SCOPE_USER, nullptr, nullptr, &hContext);
	if (err != SCARD_S_SUCCESS) {
		_log("SCardEstablishContext ERROR: %x", err);
		return result;
	}

	DWORD size = 0;
	err = SCardListReaders(hContext, nullptr, nullptr, &size);
	if (err != SCARD_S_SUCCESS || !size) {
		_log("SCardListReaders || !size ERROR: %x", err);
		SCardReleaseContext(hContext);
		return result;
	}

	std::string readers(size, 0);
	err = SCardListReaders(hContext, nullptr, &readers[0], &size);
	readers.resize(size);
	if (err != SCARD_S_SUCCESS) {
		_log("SCardListReaders ERROR: %x", err);
		SCardReleaseContext(hContext);
		return result;
	}

    std::vector<SCARD_READERSTATE> list;
    for (const char *name = readers.c_str(); *name; name += strlen(name) + 1) {
        _log("found reader: %s", name);
        list.push_back({ name, nullptr, 0, 0, 0, {} });
    }

    err = SCardGetStatusChange(hContext, 0, list.data(), DWORD(list.size()));
    if (err != SCARD_S_SUCCESS)
        _log("SCardGetStatusChange ERROR: %x", err);
    for(const SCARD_READERSTATE &state: list)
    {
        if (state.dwEventState & SCARD_STATE_PRESENT)
        {
            std::string atr = BinaryUtils::bin2hex(state.rgbAtr, state.cbAtr);
            result.push_back(atr);
            _log("Set ATR = %s for reader %s", atr.c_str(), state.szReader);
        }
    }

    SCardReleaseContext(hContext);
    return result;
}

PKCS11Path::Params PKCS11Path::getPkcs11ModulePath() {
#ifdef _WIN32
    // Use PKCS11 driver on windows to avoid PIN buffering
    static const std::string litPath = [] {
        PWSTR programFilesX86 = 0;
        SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, 0, nullptr, &programFilesX86);
        std::wstring path = programFilesX86;
        CoTaskMemFree(programFilesX86);
        if (PathFileExistsW((path + L"\\PWPW\\pwpw-card-pkcs11.dll").c_str()))
            path += L"\\PWPW\\pwpw-card-pkcs11.dll";
        else
            path += L"\\CryptoTech\\CryptoCard\\CCPkiP11.dll";
        int size = WideCharToMultiByte(CP_UTF8, 0, path.c_str(), DWORD(path.size()), nullptr, 0, nullptr, nullptr);
        std::string result(size, 0);
        WideCharToMultiByte(CP_UTF8, 0, path.c_str(), DWORD(path.size()), &result[0], size, nullptr, nullptr);
        return result;
    }();
#elif defined __APPLE__
    static const std::string openscPath("/Library/OpenSC/lib/opensc-pkcs11.so");
    static const std::string estPath = openscPath;
    static const std::string latPath("/Library/latvia-eid/lib/otlv-pkcs11.so");
    static const std::string finPath("/Library/mPolluxDigiSign/libcryptoki.dylib");
    static const std::string lit1Path("/Library/Security/tokend/CCSuite.tokend/Contents/Frameworks/libccpkip11.dylib");
    static const std::string lit2Path("/Library/PWPW-Card/pwpw-card-pkcs11.so");
    static const std::string litPath = access(lit1Path.c_str(), F_OK) == 0 ? lit1Path : lit2Path;
    static const std::string belPath("/usr/local/lib/beid-pkcs11.bundle/Contents/MacOS/libbeidpkcs11.dylib");
    static const std::string eTokenPath("/Library/Frameworks/eToken.framework/Versions/Current/libeToken.dylib");
    static const std::string ocsPath("/Library/AWP/lib/libOcsCryptoki.dylib");
#else
    static const std::string openscPath("opensc-pkcs11.so");
    static const std::string estPath = openscPath;
    static const std::string latPath("otlv-pkcs11.so");
    static const std::string finPath("libcryptoki.so");
    static const std::string lit1Path("/usr/lib/ccs/libccpkip11.so");
    static const std::string lit2Path("pwpw-card-pkcs11.so");
    static const std::string litPath = access(lit1Path.c_str(), F_OK) == 0 ? lit1Path : lit2Path;
    static const std::string belPath("libbeidpkcs11.so.0");
    static const std::string eTokenPath("/usr/lib/libeTPkcs11.so");
    static const std::string ocsPath("/usr/local/AWP/lib/libOcsCryptoki.so");
#endif
    static const std::map<std::string, Params> m = {
#ifdef _WIN32
        {"3BFD1800008031FE4553434536302D43443134352D46CD", {"C:\\Windows\\System32\\aetpkss1.dll", "PIN", "PIN"}},
#else
        {"3BFE1800008031FE454573744549442076657220312E30A8", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3_COLD_DEV1_ATR
        {"3BFE1800008031FE45803180664090A4561B168301900086", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3_WARM_DEV1_ATR
        {"3BFE1800008031FE45803180664090A4162A0083019000E1", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3_WARM_DEV2_ATR
        {"3BFE1800008031FE45803180664090A4162A00830F9000EF", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3_WARM_DEV3_ATR
        {"3BFA1800008031FE45FE654944202F20504B4903", {estPath, "PIN1", "PIN2"}}, //ESTEID_V3.5_COLD_ATR

        {"3BDD18008131FE45904C41545649412D65494490008C", {latPath, "PIN1", "PIN2"}},

        {"3B7B940000806212515646696E454944", {finPath, "PIN1", "PIN2"}},
        {"3B7F9600008031B865B0850300EF1200F6829000", {finPath, "PIN1", "PIN2"}},

        {"3B9813400AA503010101AD1311", {belPath, "PIN", "PIN"}},

        {"3BD5180081313A7D8073C8211030", {eTokenPath, "PIN", "PIN"}},
        {"3BD518008131FE7D8073C82110F4", {eTokenPath, "PIN", "PIN"}},

        {"3BDB960080B1FE451F830012233F536549440F9000F1", {ocsPath, "PIN1", "PIN2"}},
#endif
        {"3BF81300008131FE45536D617274417070F8", {litPath, "PIN", "PIN"}},
        {"3B7D94000080318065B08311C0A983009000", {litPath, "PIN", "PIN"}},
        {"3B7D94000080318065B0831100C883009000", {litPath, "PIN", "PIN"}},
        {"3B9F9681B1FE451F070064051EB20031B0739621DB00900050", {litPath, "PIN", "PIN"}},
        {"3B9F90801FC30068104405014649534531C800000000", {litPath, "PIN", "PIN"}},
    };

    const std::vector<std::string> list = atrList();
    for (const std::string &atr : list) {
        auto it = m.find(atr);
        if (it != m.end())
            return it->second;
    }
#ifdef _WIN32
    return Params();
#else
    if (!list.empty())
        _log("Unknown ATR '%s' using default module '%s'", list[0].c_str(), openscPath.c_str());
    return {openscPath, "PIN", "PIN"};
#endif
}
<|endoftext|>