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

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2008-02-25 17:27:17 +0100 (Mo, 25 Feb 2008) $
Version:   $Revision: 7837 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

//Poco headers
#include "Poco/Path.h"

#include <mitkNavigationToolStorageSerializer.h>
#include <mitkNavigationToolStorageDeserializer.h>
#include <mitkCommon.h>
#include <mitkTestingMacros.h>
#include <mitkStandaloneDataStorage.h>
#include <mitkStandardFileLocations.h>
#include <mitkSTLFileReader.h>

#include "mitkNavigationToolStorage.h"

class NavigationToolStorageSerializerAndDeserializerTestClass
  {
  public:

    static void TestInstantiationSerializer()
    {
    // let's create objects of our classes
    mitk::NavigationToolStorageSerializer::Pointer testSerializer = mitk::NavigationToolStorageSerializer::New();
    MITK_TEST_CONDITION_REQUIRED(testSerializer.IsNotNull(),"Testing instantiation of NavigationToolStorageSerializer");
    }

    static void TestInstantiationDeserializer()
    {
    mitk::DataStorage::Pointer tempStorage = dynamic_cast<mitk::DataStorage*>(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer!
    mitk::NavigationToolStorageDeserializer::Pointer testDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage);
    MITK_TEST_CONDITION_REQUIRED(testDeserializer.IsNotNull(),"Testing instantiation of NavigationToolStorageDeserializer")
    }

    static void TestWriteSimpleToolStorage()
    {
    //create Tool Storage
    mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New();
    //first tool
    mitk::NavigationTool::Pointer myTool1 = mitk::NavigationTool::New();
    myTool1->SetIdentifier("001");
    myStorage->AddTool(myTool1);
    //second tool
    mitk::NavigationTool::Pointer myTool2 = mitk::NavigationTool::New();
    myTool2->SetIdentifier("002");
    myStorage->AddTool(myTool2);
    //third tool
    mitk::NavigationTool::Pointer myTool3 = mitk::NavigationTool::New();
    myTool3->SetIdentifier("003");
    myStorage->AddTool(myTool3);

    //create Serializer
    mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage";

    //test serialization
    bool success = mySerializer->Serialize(filename,myStorage);
    MITK_TEST_CONDITION_REQUIRED(success,"Testing serialization of simple tool storage");
    }

    static void TestReadSimpleToolStorage()
    {
    mitk::DataStorage::Pointer tempStorage = dynamic_cast<mitk::DataStorage*>(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer!
    mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage);
    mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize(mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage");
    MITK_TEST_CONDITION_REQUIRED(readStorage.IsNotNull(),"Testing deserialization of simple tool storage");
    MITK_TEST_CONDITION_REQUIRED(readStorage->GetToolCount()==3," ..Testing number of tools in storage");
    //TODO: why is the order of tools changed is save/load process??
    bool foundtool1 = false;
    bool foundtool2 = false;
    bool foundtool3 = false;
    for(int i=0; i<3; i++)
      {
      if ((readStorage->GetTool(i)->GetIdentifier()=="001")) foundtool1 = true;
      else if ((readStorage->GetTool(i)->GetIdentifier()=="002")) foundtool2 = true;
      else if ((readStorage->GetTool(i)->GetIdentifier()=="003")) foundtool3 = true;
      }
    MITK_TEST_CONDITION_REQUIRED(foundtool1&&foundtool2&&foundtool3," ..Testing if identifiers of tools where saved / loaded successfully");
    }

    static void CleanUp()
    {
    std::remove((mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage").c_str());
    std::remove((mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage2.storage").c_str());
    }

    static void TestWriteComplexToolStorage()
    {

    //create first tool
    mitk::Surface::Pointer testSurface;
    std::string toolFileName = mitk::StandardFileLocations::GetInstance()->FindFile("ClaronTool", "Modules/IGT/Testing/Data");
    MITK_TEST_CONDITION(toolFileName.empty() == false, "Check if tool calibration of claron tool file exists");
    mitk::NavigationTool::Pointer myNavigationTool = mitk::NavigationTool::New();
    myNavigationTool->SetCalibrationFile(toolFileName);

    mitk::DataNode::Pointer myNode = mitk::DataNode::New();
    myNode->SetName("ClaronTool");

    //load an stl File
    mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New();
    try
      {
      stlReader->SetFileName( mitk::StandardFileLocations::GetInstance()->FindFile("ClaronTool.stl", "Testing/Data/").c_str() );
      stlReader->Update();
      }
    catch (...)
      {
      MITK_TEST_FAILED_MSG(<<"Cannot read stl file.");
      }

    if ( stlReader->GetOutput() == NULL )
      {
      MITK_TEST_FAILED_MSG(<<"Cannot read stl file.");
      }
    else
      {
      testSurface = stlReader->GetOutput();
      myNode->SetData(testSurface);
      }

    myNavigationTool->SetDataNode(myNode);
    myNavigationTool->SetIdentifier("ClaronTool#1");
    myNavigationTool->SetSerialNumber("0815");
    myNavigationTool->SetTrackingDeviceType(mitk::ClaronMicron);
    myNavigationTool->SetType(mitk::NavigationTool::Fiducial);

    //create second tool
    mitk::NavigationTool::Pointer myNavigationTool2 = mitk::NavigationTool::New();
    mitk::Surface::Pointer testSurface2;

    mitk::DataNode::Pointer myNode2 = mitk::DataNode::New();
    myNode2->SetName("AuroraTool");

    //load an stl File
    try
      {
      stlReader->SetFileName( mitk::StandardFileLocations::GetInstance()->FindFile("EMTool.stl", "Testing/Data/").c_str() );
      stlReader->Update();
      }
    catch (...)
      {
      MITK_TEST_FAILED_MSG(<<"Cannot read stl file.");
      }

    if ( stlReader->GetOutput() == NULL )
      {
      MITK_TEST_FAILED_MSG(<<"Cannot read stl file.");
      }
    else
      {
      testSurface2 = stlReader->GetOutput();
      myNode2->SetData(testSurface2);
      }

    myNavigationTool2->SetDataNode(myNode2);
    myNavigationTool2->SetIdentifier("AuroraTool#1");
    myNavigationTool2->SetSerialNumber("0816");
    myNavigationTool2->SetTrackingDeviceType(mitk::NDIAurora);
    myNavigationTool2->SetType(mitk::NavigationTool::Instrument);

    //create navigation tool storage
    mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New();
    myStorage->AddTool(myNavigationTool);
    myStorage->AddTool(myNavigationTool2);

    //create Serializer
    mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage2.storage";

    //test serialization
    bool success = mySerializer->Serialize(filename,myStorage);
    MITK_TEST_CONDITION_REQUIRED(success,"Testing serialization of complex tool storage");

    }

    static void TestReadComplexToolStorage()
    {
    mitk::DataStorage::Pointer tempStorage = dynamic_cast<mitk::DataStorage*>(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer!
    mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage);
    mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize(mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage2.storage");
    MITK_TEST_CONDITION_REQUIRED(readStorage.IsNotNull(),"Testing deserialization of complex tool storage");
    MITK_TEST_CONDITION_REQUIRED(readStorage->GetToolCount()==2," ..Testing number of tools in storage");
    }

    static void TestReadInvalidStorage()
    {
    mitk::DataStorage::Pointer tempStorage = dynamic_cast<mitk::DataStorage*>(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer!
    mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage);
    mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize("noStorage.tfl");
    MITK_TEST_CONDITION_REQUIRED(readStorage->isEmpty(),"Testing deserialization of invalid data storage.");
    MITK_TEST_CONDITION_REQUIRED(myDeserializer->GetErrorMessage() == "Cannot open 'noStorage.tfl' for reading", "Checking Error Message");
    }

    static void TestWriteStorageToInvalidFile()
    {
     //create Tool Storage
    mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New();
    //first tool
    mitk::NavigationTool::Pointer myTool1 = mitk::NavigationTool::New();
    myTool1->SetIdentifier("001");
    myStorage->AddTool(myTool1);
    //second tool
    mitk::NavigationTool::Pointer myTool2 = mitk::NavigationTool::New();
    myTool2->SetIdentifier("002");
    myStorage->AddTool(myTool2);
    //third tool
    mitk::NavigationTool::Pointer myTool3 = mitk::NavigationTool::New();
    myTool3->SetIdentifier("003");
    myStorage->AddTool(myTool3);

    //create Serializer
    mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New();

    //create filename
    std::string filename = "dsfdsf:$$342INVALIDFILE.storage";

    //test serialization
    bool success = mySerializer->Serialize(filename,myStorage);
    MITK_TEST_CONDITION_REQUIRED(!success,"Testing serialization into invalid file.");
    }

  };

/** This function is testing the TrackingVolume class. */
int mitkNavigationToolStorageSerializerAndDeserializerTest(int /* argc */, char* /*argv*/[])
{
  MITK_TEST_BEGIN("NavigationToolStorageSerializerAndDeserializer");

  //NavigationToolStorageSerializerAndDeserializerTestClass::TestInstantiationSerializer();
  //NavigationToolStorageSerializerAndDeserializerTestClass::TestInstantiationDeserializer();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteSimpleToolStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestReadSimpleToolStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteComplexToolStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestReadComplexToolStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestReadInvalidStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteStorageToInvalidFile();
  NavigationToolStorageSerializerAndDeserializerTestClass::CleanUp();

  MITK_TEST_END();
}
<commit_msg>COMP (#8896): made filename invalid for linux<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2008-02-25 17:27:17 +0100 (Mo, 25 Feb 2008) $
Version:   $Revision: 7837 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

//Poco headers
#include "Poco/Path.h"

#include <mitkNavigationToolStorageSerializer.h>
#include <mitkNavigationToolStorageDeserializer.h>
#include <mitkCommon.h>
#include <mitkTestingMacros.h>
#include <mitkStandaloneDataStorage.h>
#include <mitkStandardFileLocations.h>
#include <mitkSTLFileReader.h>

#include "mitkNavigationToolStorage.h"

class NavigationToolStorageSerializerAndDeserializerTestClass
  {
  public:

    static void TestInstantiationSerializer()
    {
    // let's create objects of our classes
    mitk::NavigationToolStorageSerializer::Pointer testSerializer = mitk::NavigationToolStorageSerializer::New();
    MITK_TEST_CONDITION_REQUIRED(testSerializer.IsNotNull(),"Testing instantiation of NavigationToolStorageSerializer");
    }

    static void TestInstantiationDeserializer()
    {
    mitk::DataStorage::Pointer tempStorage = dynamic_cast<mitk::DataStorage*>(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer!
    mitk::NavigationToolStorageDeserializer::Pointer testDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage);
    MITK_TEST_CONDITION_REQUIRED(testDeserializer.IsNotNull(),"Testing instantiation of NavigationToolStorageDeserializer")
    }

    static void TestWriteSimpleToolStorage()
    {
    //create Tool Storage
    mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New();
    //first tool
    mitk::NavigationTool::Pointer myTool1 = mitk::NavigationTool::New();
    myTool1->SetIdentifier("001");
    myStorage->AddTool(myTool1);
    //second tool
    mitk::NavigationTool::Pointer myTool2 = mitk::NavigationTool::New();
    myTool2->SetIdentifier("002");
    myStorage->AddTool(myTool2);
    //third tool
    mitk::NavigationTool::Pointer myTool3 = mitk::NavigationTool::New();
    myTool3->SetIdentifier("003");
    myStorage->AddTool(myTool3);

    //create Serializer
    mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage";

    //test serialization
    bool success = mySerializer->Serialize(filename,myStorage);
    MITK_TEST_CONDITION_REQUIRED(success,"Testing serialization of simple tool storage");
    }

    static void TestReadSimpleToolStorage()
    {
    mitk::DataStorage::Pointer tempStorage = dynamic_cast<mitk::DataStorage*>(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer!
    mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage);
    mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize(mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage");
    MITK_TEST_CONDITION_REQUIRED(readStorage.IsNotNull(),"Testing deserialization of simple tool storage");
    MITK_TEST_CONDITION_REQUIRED(readStorage->GetToolCount()==3," ..Testing number of tools in storage");
    //TODO: why is the order of tools changed is save/load process??
    bool foundtool1 = false;
    bool foundtool2 = false;
    bool foundtool3 = false;
    for(int i=0; i<3; i++)
      {
      if ((readStorage->GetTool(i)->GetIdentifier()=="001")) foundtool1 = true;
      else if ((readStorage->GetTool(i)->GetIdentifier()=="002")) foundtool2 = true;
      else if ((readStorage->GetTool(i)->GetIdentifier()=="003")) foundtool3 = true;
      }
    MITK_TEST_CONDITION_REQUIRED(foundtool1&&foundtool2&&foundtool3," ..Testing if identifiers of tools where saved / loaded successfully");
    }

    static void CleanUp()
    {
    std::remove((mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage").c_str());
    std::remove((mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage2.storage").c_str());
    }

    static void TestWriteComplexToolStorage()
    {

    //create first tool
    mitk::Surface::Pointer testSurface;
    std::string toolFileName = mitk::StandardFileLocations::GetInstance()->FindFile("ClaronTool", "Modules/IGT/Testing/Data");
    MITK_TEST_CONDITION(toolFileName.empty() == false, "Check if tool calibration of claron tool file exists");
    mitk::NavigationTool::Pointer myNavigationTool = mitk::NavigationTool::New();
    myNavigationTool->SetCalibrationFile(toolFileName);

    mitk::DataNode::Pointer myNode = mitk::DataNode::New();
    myNode->SetName("ClaronTool");

    //load an stl File
    mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New();
    try
      {
      stlReader->SetFileName( mitk::StandardFileLocations::GetInstance()->FindFile("ClaronTool.stl", "Testing/Data/").c_str() );
      stlReader->Update();
      }
    catch (...)
      {
      MITK_TEST_FAILED_MSG(<<"Cannot read stl file.");
      }

    if ( stlReader->GetOutput() == NULL )
      {
      MITK_TEST_FAILED_MSG(<<"Cannot read stl file.");
      }
    else
      {
      testSurface = stlReader->GetOutput();
      myNode->SetData(testSurface);
      }

    myNavigationTool->SetDataNode(myNode);
    myNavigationTool->SetIdentifier("ClaronTool#1");
    myNavigationTool->SetSerialNumber("0815");
    myNavigationTool->SetTrackingDeviceType(mitk::ClaronMicron);
    myNavigationTool->SetType(mitk::NavigationTool::Fiducial);

    //create second tool
    mitk::NavigationTool::Pointer myNavigationTool2 = mitk::NavigationTool::New();
    mitk::Surface::Pointer testSurface2;

    mitk::DataNode::Pointer myNode2 = mitk::DataNode::New();
    myNode2->SetName("AuroraTool");

    //load an stl File
    try
      {
      stlReader->SetFileName( mitk::StandardFileLocations::GetInstance()->FindFile("EMTool.stl", "Testing/Data/").c_str() );
      stlReader->Update();
      }
    catch (...)
      {
      MITK_TEST_FAILED_MSG(<<"Cannot read stl file.");
      }

    if ( stlReader->GetOutput() == NULL )
      {
      MITK_TEST_FAILED_MSG(<<"Cannot read stl file.");
      }
    else
      {
      testSurface2 = stlReader->GetOutput();
      myNode2->SetData(testSurface2);
      }

    myNavigationTool2->SetDataNode(myNode2);
    myNavigationTool2->SetIdentifier("AuroraTool#1");
    myNavigationTool2->SetSerialNumber("0816");
    myNavigationTool2->SetTrackingDeviceType(mitk::NDIAurora);
    myNavigationTool2->SetType(mitk::NavigationTool::Instrument);

    //create navigation tool storage
    mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New();
    myStorage->AddTool(myNavigationTool);
    myStorage->AddTool(myNavigationTool2);

    //create Serializer
    mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage2.storage";

    //test serialization
    bool success = mySerializer->Serialize(filename,myStorage);
    MITK_TEST_CONDITION_REQUIRED(success,"Testing serialization of complex tool storage");

    }

    static void TestReadComplexToolStorage()
    {
    mitk::DataStorage::Pointer tempStorage = dynamic_cast<mitk::DataStorage*>(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer!
    mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage);
    mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize(mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage2.storage");
    MITK_TEST_CONDITION_REQUIRED(readStorage.IsNotNull(),"Testing deserialization of complex tool storage");
    MITK_TEST_CONDITION_REQUIRED(readStorage->GetToolCount()==2," ..Testing number of tools in storage");
    }

    static void TestReadInvalidStorage()
    {
    mitk::DataStorage::Pointer tempStorage = dynamic_cast<mitk::DataStorage*>(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer!
    mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage);
    mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize("noStorage.tfl");
    MITK_TEST_CONDITION_REQUIRED(readStorage->isEmpty(),"Testing deserialization of invalid data storage.");
    MITK_TEST_CONDITION_REQUIRED(myDeserializer->GetErrorMessage() == "Cannot open 'noStorage.tfl' for reading", "Checking Error Message");
    }

    static void TestWriteStorageToInvalidFile()
    {
     //create Tool Storage
    mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New();
    //first tool
    mitk::NavigationTool::Pointer myTool1 = mitk::NavigationTool::New();
    myTool1->SetIdentifier("001");
    myStorage->AddTool(myTool1);
    //second tool
    mitk::NavigationTool::Pointer myTool2 = mitk::NavigationTool::New();
    myTool2->SetIdentifier("002");
    myStorage->AddTool(myTool2);
    //third tool
    mitk::NavigationTool::Pointer myTool3 = mitk::NavigationTool::New();
    myTool3->SetIdentifier("003");
    myStorage->AddTool(myTool3);

    //create Serializer
    mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New();

    //create filename
    std::string filename = "/dsfdsf:$$342INVALIDFILE.storage";

    //test serialization
    bool success = mySerializer->Serialize(filename,myStorage);
    MITK_TEST_CONDITION_REQUIRED(!success,"Testing serialization into invalid file.");
    }

  };

/** This function is testing the TrackingVolume class. */
int mitkNavigationToolStorageSerializerAndDeserializerTest(int /* argc */, char* /*argv*/[])
{
  MITK_TEST_BEGIN("NavigationToolStorageSerializerAndDeserializer");

  //NavigationToolStorageSerializerAndDeserializerTestClass::TestInstantiationSerializer();
  //NavigationToolStorageSerializerAndDeserializerTestClass::TestInstantiationDeserializer();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteSimpleToolStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestReadSimpleToolStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteComplexToolStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestReadComplexToolStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestReadInvalidStorage();
  NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteStorageToInvalidFile();
  NavigationToolStorageSerializerAndDeserializerTestClass::CleanUp();

  MITK_TEST_END();
}<|endoftext|>


<commit_before>#include "SnepMessenger.h"
#include <vector>

#include "ILlcpSocket.h"
#include "NfcDebug.h"

/**
 * The Simple NDEF Exchange Protocol (SNEP) is a request/response protocol.
 * A SNEP client sends a request to a SNEP server in the form of a protocol
 * version, a request method, the length of an information field in octets,
 * and an information field.
 */
SnepMessenger::SnepMessenger(bool isClient, ILlcpSocket* socket, uint32_t fragmentLength)
 : mSocket(socket)
 , mFragmentLength(fragmentLength)
 , mIsClient(isClient)
{
}

SnepMessenger::~SnepMessenger()
{
  close();
}

void SnepMessenger::sendMessage(SnepMessage& msg)
{
  ALOGD("%s: enter", FUNC);

  uint8_t remoteContinue;
  if (mIsClient) {
    remoteContinue = SnepMessage::RESPONSE_CONTINUE;
  } else {
    remoteContinue = SnepMessage::REQUEST_CONTINUE;
  }

  std::vector<uint8_t> buf;
  msg.toByteArray(buf);
  uint32_t length = buf.size() <  mFragmentLength ? buf.size() : mFragmentLength;

  mSocket->send(buf);

  if (length == buf.size()) {
    ALOGD("%s: exit", FUNC);
    return;
  }

  // Fragmented SNEP message handling.
  // Look for Continue or Reject from peer.
  uint32_t offset = length;
  std::vector<uint8_t> responseBytes;
  mSocket->receive(responseBytes);

  SnepMessage* snepResponse = SnepMessage::fromByteArray(responseBytes);
  if (!snepResponse) {
    ALOGE("%s: invalid SNEP message", FUNC);
    return;
  }

  if (snepResponse->getField() != remoteContinue) {
    ALOGE("%s: invalid response from server (%d)", FUNC, snepResponse->getField());
    delete snepResponse;
    return;
  }

  // Send remaining fragments.
  while (offset < buf.size()) {
    std::vector<uint8_t> tmpBuf;
    length = buf.size() - offset < mFragmentLength ? buf.size() - offset : mFragmentLength;
    // TODO : Need check here
    for(uint32_t i = offset; i < offset + length; i++)
      tmpBuf.push_back(buf[i]);
    mSocket->send(tmpBuf);
    offset += length;
  }

  ALOGD("%s: exit", FUNC);
}

/**
 * Get Snep message from remote side.
 */
SnepMessage* SnepMessenger::getMessage()
{
  ALOGD("%s: enter", FUNC);

  std::vector<uint8_t> partial;
  std::vector<uint8_t> buffer;

  uint8_t fieldContinue = 0;
  uint8_t fieldReject = 0;

  if (mIsClient) {
    /**
     * Request Codes : CONTINUE
     * The client requests that the server send the remaining fragments
     * of a fragmented SNEP response message.
     *
     * Request Codes : REJECT
     * The client is unable to receive remaining fragments of a fragmented
     * SNEP response message.
     */
    fieldContinue = SnepMessage::REQUEST_CONTINUE;
    fieldReject = SnepMessage::REQUEST_REJECT;
  } else {
    /**
     * Response Codes : CONTINUE
     * The server received the first fragment of a fragmented SNEP request
     * message and is able to receive the remaining fragments.
     *
     * Response Codes : REJECT
     * The server is unable to receive remaining fragments of a fragmented
     * SNEP request message.
     */
    fieldContinue = SnepMessage::RESPONSE_CONTINUE;
    fieldReject = SnepMessage::RESPONSE_REJECT;
  }

  uint32_t readSize = 0;
  int size = mSocket->receive(partial);
  if (size < 0 || size < HEADER_LENGTH) {
    if (!socketSend(fieldReject)) {
      ALOGE("%s: snep message send fail", FUNC);
      return NULL;
    }
  } else {
    readSize = size - HEADER_LENGTH;
    buffer.insert(buffer.end(), partial.begin(), partial.end());
  }

  const uint8_t requestVersion = partial[0];
  const uint8_t requestField = partial[1];
  const uint32_t requestSize = ((uint32_t)partial[2] << 24) |
                               ((uint32_t)partial[3] << 16) |
                               ((uint32_t)partial[4] <<  8) |
                               ((uint32_t)partial[5]);

  if (((requestVersion & 0xF0) >> 4) != SnepMessage::VERSION_MAJOR) {
    // Invalid protocol version; treat message as complete.
    ALOGE("%s: invalid protocol version %d != %d",
       FUNC, ((requestVersion & 0xF0) >> 4), SnepMessage::VERSION_MAJOR);
    return new SnepMessage(requestVersion, requestField, 0, 0, NULL);
  }

  bool doneReading = false;
  if (requestSize > readSize) {
    if (!socketSend(fieldContinue)) {
      ALOGE("%s: snep message send fail", FUNC);
      return NULL;
    }
  } else {
    doneReading = true;
  }

  // Fragmented SNEP message handling.
  // Remaining fragments.
  while (!doneReading) {
    partial.clear();
    size = mSocket->receive(partial);
    if (size < 0) {
      if (!socketSend(fieldReject)) {
        ALOGE("%s: snep message send fail", FUNC);
        return NULL;
      }
    } else {
      readSize += size;
      buffer.insert(buffer.end(), partial.begin(), partial.end());
      if (readSize == requestSize) {
        doneReading = true;
      }
    }
  }

  SnepMessage* snep = SnepMessage::fromByteArray(buffer);
  if (!snep)
    ALOGE("%s: nadly formatted NDEF message, ignoring", FUNC);

  ALOGD("%s: exit", FUNC);
  return snep;
}

void SnepMessenger::close()
{
  if (mSocket) {
    mSocket->close();
    mSocket = NULL;
  }
}

bool SnepMessenger::socketSend(uint8_t field)
{
  bool status = false;
  std::vector<uint8_t> data;
  SnepMessage* msg = SnepMessage::getMessage(field);
  msg->toByteArray(data);
  status = mSocket->send(data);
  delete msg;
  return status;
}
<commit_msg>Bug 947055 - B2G NFC: NFC Daemon doesn't handle SNEP correctly<commit_after>#include "SnepMessenger.h"
#include <vector>

#include "ILlcpSocket.h"
#include "NfcDebug.h"

/**
 * The Simple NDEF Exchange Protocol (SNEP) is a request/response protocol.
 * A SNEP client sends a request to a SNEP server in the form of a protocol
 * version, a request method, the length of an information field in octets,
 * and an information field.
 */
SnepMessenger::SnepMessenger(bool isClient, ILlcpSocket* socket, uint32_t fragmentLength)
 : mSocket(socket)
 , mFragmentLength(fragmentLength)
 , mIsClient(isClient)
{
}

SnepMessenger::~SnepMessenger()
{
  close();
}

void SnepMessenger::sendMessage(SnepMessage& msg)
{
  ALOGD("%s: enter", FUNC);

  uint8_t remoteContinue;
  if (mIsClient) {
    remoteContinue = SnepMessage::RESPONSE_CONTINUE;
  } else {
    remoteContinue = SnepMessage::REQUEST_CONTINUE;
  }

  std::vector<uint8_t> buf;
  msg.toByteArray(buf);
  uint32_t length = -1;

  if (buf.size() <  mFragmentLength) {
    length = buf.size();
    mSocket->send(buf);
  } else {
    length = mFragmentLength;
    std::vector<uint8_t> tmpBuf;
    for (uint32_t i = 0; i < mFragmentLength; i++)
      tmpBuf.push_back(buf[i]);
    mSocket->send(tmpBuf);
  }

  if (length == buf.size()) {
    ALOGD("%s: exit", FUNC);
    return;
  }

  // Fragmented SNEP message handling.
  // Look for Continue or Reject from peer.
  uint32_t offset = length;
  std::vector<uint8_t> responseBytes;
  mSocket->receive(responseBytes);

  SnepMessage* snepResponse = SnepMessage::fromByteArray(responseBytes);
  if (!snepResponse) {
    ALOGE("%s: invalid SNEP message", FUNC);
    return;
  }

  if (snepResponse->getField() != remoteContinue) {
    ALOGE("%s: invalid response from server (%d)", FUNC, snepResponse->getField());
    delete snepResponse;
    return;
  }

  // Send remaining fragments.
  while (offset < buf.size()) {
    std::vector<uint8_t> tmpBuf;
    length = buf.size() - offset < mFragmentLength ? buf.size() - offset : mFragmentLength;
    // TODO : Need check here
    for(uint32_t i = offset; i < offset + length; i++)
      tmpBuf.push_back(buf[i]);
    mSocket->send(tmpBuf);
    offset += length;
  }

  ALOGD("%s: exit", FUNC);
}

/**
 * Get Snep message from remote side.
 */
SnepMessage* SnepMessenger::getMessage()
{
  ALOGD("%s: enter", FUNC);

  std::vector<uint8_t> partial;
  std::vector<uint8_t> buffer;

  uint8_t fieldContinue = 0;
  uint8_t fieldReject = 0;

  if (mIsClient) {
    /**
     * Request Codes : CONTINUE
     * The client requests that the server send the remaining fragments
     * of a fragmented SNEP response message.
     *
     * Request Codes : REJECT
     * The client is unable to receive remaining fragments of a fragmented
     * SNEP response message.
     */
    fieldContinue = SnepMessage::REQUEST_CONTINUE;
    fieldReject = SnepMessage::REQUEST_REJECT;
  } else {
    /**
     * Response Codes : CONTINUE
     * The server received the first fragment of a fragmented SNEP request
     * message and is able to receive the remaining fragments.
     *
     * Response Codes : REJECT
     * The server is unable to receive remaining fragments of a fragmented
     * SNEP request message.
     */
    fieldContinue = SnepMessage::RESPONSE_CONTINUE;
    fieldReject = SnepMessage::RESPONSE_REJECT;
  }

  uint32_t readSize = 0;
  int size = mSocket->receive(partial);
  if (size < 0 || size < HEADER_LENGTH) {
    if (!socketSend(fieldReject)) {
      ALOGE("%s: snep message send fail", FUNC);
      return NULL;
    }
  } else {
    readSize = size - HEADER_LENGTH;
    buffer.insert(buffer.end(), partial.begin(), partial.end());
  }

  const uint8_t requestVersion = partial[0];
  const uint8_t requestField = partial[1];
  const uint32_t requestSize = ((uint32_t)partial[2] << 24) |
                               ((uint32_t)partial[3] << 16) |
                               ((uint32_t)partial[4] <<  8) |
                               ((uint32_t)partial[5]);

  if (((requestVersion & 0xF0) >> 4) != SnepMessage::VERSION_MAJOR) {
    // Invalid protocol version; treat message as complete.
    ALOGE("%s: invalid protocol version %d != %d",
       FUNC, ((requestVersion & 0xF0) >> 4), SnepMessage::VERSION_MAJOR);
    return new SnepMessage(requestVersion, requestField, 0, 0, NULL);
  }

  bool doneReading = false;
  if (requestSize > readSize) {
    if (!socketSend(fieldContinue)) {
      ALOGE("%s: snep message send fail", FUNC);
      return NULL;
    }
  } else {
    doneReading = true;
  }

  // Fragmented SNEP message handling.
  // Remaining fragments.
  while (!doneReading) {
    partial.clear();
    size = mSocket->receive(partial);
    if (size < 0) {
      if (!socketSend(fieldReject)) {
        ALOGE("%s: snep message send fail", FUNC);
        return NULL;
      }
    } else {
      readSize += size;
      buffer.insert(buffer.end(), partial.begin(), partial.end());
      if (readSize == requestSize) {
        doneReading = true;
      }
    }
  }

  SnepMessage* snep = SnepMessage::fromByteArray(buffer);
  if (!snep)
    ALOGE("%s: nadly formatted NDEF message, ignoring", FUNC);

  ALOGD("%s: exit", FUNC);
  return snep;
}

void SnepMessenger::close()
{
  if (mSocket) {
    mSocket->close();
    mSocket = NULL;
  }
}

bool SnepMessenger::socketSend(uint8_t field)
{
  bool status = false;
  std::vector<uint8_t> data;
  SnepMessage* msg = SnepMessage::getMessage(field);
  msg->toByteArray(data);
  status = mSocket->send(data);
  delete msg;
  return status;
}
<|endoftext|>


<commit_before>#include "derivations.hh"
#include "parsed-derivations.hh"
#include "globals.hh"
#include "local-store.hh"
#include "store-api.hh"
#include "thread-pool.hh"
#include "topo-sort.hh"
#include "callback.hh"
#include "closure.hh"

namespace nix {

void Store::computeFSClosure(const StorePathSet & startPaths,
    StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers)
{
    std::function<std::set<StorePath>(const StorePath & path, std::future<ref<const ValidPathInfo>> &)> queryDeps;
    if (flipDirection)
        queryDeps = [&](const StorePath& path,
                        std::future<ref<const ValidPathInfo>> & fut) {
            StorePathSet res;
            StorePathSet referrers;
            queryReferrers(path, referrers);
            for (auto& ref : referrers)
                if (ref != path)
                    res.insert(ref);

            if (includeOutputs)
                for (auto& i : queryValidDerivers(path))
                    res.insert(i);

            if (includeDerivers && path.isDerivation())
                for (auto& [_, maybeOutPath] : queryPartialDerivationOutputMap(path))
                    if (maybeOutPath && isValidPath(*maybeOutPath) && queryPathInfo(*maybeOutPath)->deriver == path)
                        res.insert(*maybeOutPath);
            return res;
        };
    else
        queryDeps = [&](const StorePath& path,
                        std::future<ref<const ValidPathInfo>> & fut) {
            StorePathSet res;
            auto info = fut.get();
            for (auto& ref : info->references)
                if (ref != path)
                    res.insert(ref);

            if (includeOutputs && path.isDerivation())
                for (auto& [_, maybeOutPath] : queryPartialDerivationOutputMap(path))
                    if (maybeOutPath && isValidPath(*maybeOutPath))
                        res.insert(*maybeOutPath);

            if (includeDerivers && info->deriver && isValidPath(*info->deriver))
                res.insert(*info->deriver);
            return res;
        };

    computeClosure<StorePath>(
        startPaths, paths_,
        [&](const StorePath& path,
            std::function<void(std::promise<std::set<StorePath>>&)>
                processEdges) {
            std::promise<std::set<StorePath>> promise;
            std::function<void(std::future<ref<const ValidPathInfo>>)>
                getDependencies =
                    [&](std::future<ref<const ValidPathInfo>> fut) {
                        try {
                            promise.set_value(queryDeps(path, fut));
                        } catch (...) {
                            promise.set_exception(std::current_exception());
                        }
                    };
            queryPathInfo(path, getDependencies);
            processEdges(promise);
        });
}

void Store::computeFSClosure(const StorePath & startPath,
    StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers)
{
    StorePathSet paths;
    paths.insert(startPath);
    computeFSClosure(paths, paths_, flipDirection, includeOutputs, includeDerivers);
}

std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv)
{
    auto out = drv.outputs.find("out");
    if (out != drv.outputs.end()) {
        if (auto v = std::get_if<DerivationOutputCAFixed>(&out->second.output))
            return v->hash;
    }
    return std::nullopt;
}

void Store::queryMissing(const std::vector<DerivedPath> & targets,
    StorePathSet & willBuild_, StorePathSet & willSubstitute_, StorePathSet & unknown_,
    uint64_t & downloadSize_, uint64_t & narSize_)
{
    Activity act(*logger, lvlDebug, actUnknown, "querying info about missing paths");

    downloadSize_ = narSize_ = 0;

    ThreadPool pool;

    struct State
    {
        std::unordered_set<std::string> done;
        StorePathSet & unknown, & willSubstitute, & willBuild;
        uint64_t & downloadSize;
        uint64_t & narSize;
    };

    struct DrvState
    {
        size_t left;
        bool done = false;
        StorePathSet outPaths;
        DrvState(size_t left) : left(left) { }
    };

    Sync<State> state_(State{{}, unknown_, willSubstitute_, willBuild_, downloadSize_, narSize_});

    std::function<void(DerivedPath)> doPath;

    auto mustBuildDrv = [&](const StorePath & drvPath, const Derivation & drv) {
        {
            auto state(state_.lock());
            state->willBuild.insert(drvPath);
        }

        for (auto & i : drv.inputDrvs)
            pool.enqueue(std::bind(doPath, DerivedPath::Built { i.first, i.second }));
    };

    auto checkOutput = [&](
        const StorePath & drvPath, ref<Derivation> drv, const StorePath & outPath, ref<Sync<DrvState>> drvState_)
    {
        if (drvState_->lock()->done) return;

        SubstitutablePathInfos infos;
        querySubstitutablePathInfos({{outPath, getDerivationCA(*drv)}}, infos);

        if (infos.empty()) {
            drvState_->lock()->done = true;
            mustBuildDrv(drvPath, *drv);
        } else {
            {
                auto drvState(drvState_->lock());
                if (drvState->done) return;
                assert(drvState->left);
                drvState->left--;
                drvState->outPaths.insert(outPath);
                if (!drvState->left) {
                    for (auto & path : drvState->outPaths)
                        pool.enqueue(std::bind(doPath, DerivedPath::Opaque { path } ));
                }
            }
        }
    };

    doPath = [&](const DerivedPath & req) {

        {
            auto state(state_.lock());
            if (!state->done.insert(req.to_string(*this)).second) return;
        }

        std::visit(overloaded {
          [&](DerivedPath::Built bfd) {
            if (!isValidPath(bfd.drvPath)) {
                // FIXME: we could try to substitute the derivation.
                auto state(state_.lock());
                state->unknown.insert(bfd.drvPath);
                return;
            }

            StorePathSet invalid;
            /* true for regular derivations, and CA derivations for which we
               have a trust mapping for all wanted outputs. */
            auto knownOutputPaths = true;
            for (auto & [outputName, pathOpt] : queryPartialDerivationOutputMap(bfd.drvPath)) {
                if (!pathOpt) {
                    knownOutputPaths = false;
                    break;
                }
                if (wantOutput(outputName, bfd.outputs) && !isValidPath(*pathOpt))
                    invalid.insert(*pathOpt);
            }
            if (knownOutputPaths && invalid.empty()) return;

            auto drv = make_ref<Derivation>(derivationFromPath(bfd.drvPath));
            ParsedDerivation parsedDrv(StorePath(bfd.drvPath), *drv);

            if (knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) {
                auto drvState = make_ref<Sync<DrvState>>(DrvState(invalid.size()));
                for (auto & output : invalid)
                    pool.enqueue(std::bind(checkOutput, bfd.drvPath, drv, output, drvState));
            } else
                mustBuildDrv(bfd.drvPath, *drv);

          },
          [&](DerivedPath::Opaque bo) {

            if (isValidPath(bo.path)) return;

            SubstitutablePathInfos infos;
            querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos);

            if (infos.empty()) {
                auto state(state_.lock());
                state->unknown.insert(bo.path);
                return;
            }

            auto info = infos.find(bo.path);
            assert(info != infos.end());

            {
                auto state(state_.lock());
                state->willSubstitute.insert(bo.path);
                state->downloadSize += info->second.downloadSize;
                state->narSize += info->second.narSize;
            }

            for (auto & ref : info->second.references)
                pool.enqueue(std::bind(doPath, DerivedPath::Opaque { ref }));
          },
        }, req.raw());
    };

    for (auto & path : targets)
        pool.enqueue(std::bind(doPath, path));

    pool.process();
}

StorePaths Store::topoSortPaths(const StorePathSet & paths)
{
    return topoSort(paths,
        {[&](const StorePath & path) {
            StorePathSet references;
            try {
                references = queryPathInfo(path)->references;
            } catch (InvalidPath &) {
            }
            return references;
        }},
        {[&](const StorePath & path, const StorePath & parent) {
            return BuildError(
                "cycle detected in the references of '%s' from '%s'",
                printStorePath(path),
                printStorePath(parent));
        }});
}

}
<commit_msg>Don’t check the `deriver` field on computeFSClosure<commit_after>#include "derivations.hh"
#include "parsed-derivations.hh"
#include "globals.hh"
#include "local-store.hh"
#include "store-api.hh"
#include "thread-pool.hh"
#include "topo-sort.hh"
#include "callback.hh"
#include "closure.hh"

namespace nix {

void Store::computeFSClosure(const StorePathSet & startPaths,
    StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers)
{
    std::function<std::set<StorePath>(const StorePath & path, std::future<ref<const ValidPathInfo>> &)> queryDeps;
    if (flipDirection)
        queryDeps = [&](const StorePath& path,
                        std::future<ref<const ValidPathInfo>> & fut) {
            StorePathSet res;
            StorePathSet referrers;
            queryReferrers(path, referrers);
            for (auto& ref : referrers)
                if (ref != path)
                    res.insert(ref);

            if (includeOutputs)
                for (auto& i : queryValidDerivers(path))
                    res.insert(i);

            if (includeDerivers && path.isDerivation())
                for (auto& [_, maybeOutPath] : queryPartialDerivationOutputMap(path))
                    if (maybeOutPath && isValidPath(*maybeOutPath))
                        res.insert(*maybeOutPath);
            return res;
        };
    else
        queryDeps = [&](const StorePath& path,
                        std::future<ref<const ValidPathInfo>> & fut) {
            StorePathSet res;
            auto info = fut.get();
            for (auto& ref : info->references)
                if (ref != path)
                    res.insert(ref);

            if (includeOutputs && path.isDerivation())
                for (auto& [_, maybeOutPath] : queryPartialDerivationOutputMap(path))
                    if (maybeOutPath && isValidPath(*maybeOutPath))
                        res.insert(*maybeOutPath);

            if (includeDerivers && info->deriver && isValidPath(*info->deriver))
                res.insert(*info->deriver);
            return res;
        };

    computeClosure<StorePath>(
        startPaths, paths_,
        [&](const StorePath& path,
            std::function<void(std::promise<std::set<StorePath>>&)>
                processEdges) {
            std::promise<std::set<StorePath>> promise;
            std::function<void(std::future<ref<const ValidPathInfo>>)>
                getDependencies =
                    [&](std::future<ref<const ValidPathInfo>> fut) {
                        try {
                            promise.set_value(queryDeps(path, fut));
                        } catch (...) {
                            promise.set_exception(std::current_exception());
                        }
                    };
            queryPathInfo(path, getDependencies);
            processEdges(promise);
        });
}

void Store::computeFSClosure(const StorePath & startPath,
    StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers)
{
    StorePathSet paths;
    paths.insert(startPath);
    computeFSClosure(paths, paths_, flipDirection, includeOutputs, includeDerivers);
}

std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv)
{
    auto out = drv.outputs.find("out");
    if (out != drv.outputs.end()) {
        if (auto v = std::get_if<DerivationOutputCAFixed>(&out->second.output))
            return v->hash;
    }
    return std::nullopt;
}

void Store::queryMissing(const std::vector<DerivedPath> & targets,
    StorePathSet & willBuild_, StorePathSet & willSubstitute_, StorePathSet & unknown_,
    uint64_t & downloadSize_, uint64_t & narSize_)
{
    Activity act(*logger, lvlDebug, actUnknown, "querying info about missing paths");

    downloadSize_ = narSize_ = 0;

    ThreadPool pool;

    struct State
    {
        std::unordered_set<std::string> done;
        StorePathSet & unknown, & willSubstitute, & willBuild;
        uint64_t & downloadSize;
        uint64_t & narSize;
    };

    struct DrvState
    {
        size_t left;
        bool done = false;
        StorePathSet outPaths;
        DrvState(size_t left) : left(left) { }
    };

    Sync<State> state_(State{{}, unknown_, willSubstitute_, willBuild_, downloadSize_, narSize_});

    std::function<void(DerivedPath)> doPath;

    auto mustBuildDrv = [&](const StorePath & drvPath, const Derivation & drv) {
        {
            auto state(state_.lock());
            state->willBuild.insert(drvPath);
        }

        for (auto & i : drv.inputDrvs)
            pool.enqueue(std::bind(doPath, DerivedPath::Built { i.first, i.second }));
    };

    auto checkOutput = [&](
        const StorePath & drvPath, ref<Derivation> drv, const StorePath & outPath, ref<Sync<DrvState>> drvState_)
    {
        if (drvState_->lock()->done) return;

        SubstitutablePathInfos infos;
        querySubstitutablePathInfos({{outPath, getDerivationCA(*drv)}}, infos);

        if (infos.empty()) {
            drvState_->lock()->done = true;
            mustBuildDrv(drvPath, *drv);
        } else {
            {
                auto drvState(drvState_->lock());
                if (drvState->done) return;
                assert(drvState->left);
                drvState->left--;
                drvState->outPaths.insert(outPath);
                if (!drvState->left) {
                    for (auto & path : drvState->outPaths)
                        pool.enqueue(std::bind(doPath, DerivedPath::Opaque { path } ));
                }
            }
        }
    };

    doPath = [&](const DerivedPath & req) {

        {
            auto state(state_.lock());
            if (!state->done.insert(req.to_string(*this)).second) return;
        }

        std::visit(overloaded {
          [&](DerivedPath::Built bfd) {
            if (!isValidPath(bfd.drvPath)) {
                // FIXME: we could try to substitute the derivation.
                auto state(state_.lock());
                state->unknown.insert(bfd.drvPath);
                return;
            }

            StorePathSet invalid;
            /* true for regular derivations, and CA derivations for which we
               have a trust mapping for all wanted outputs. */
            auto knownOutputPaths = true;
            for (auto & [outputName, pathOpt] : queryPartialDerivationOutputMap(bfd.drvPath)) {
                if (!pathOpt) {
                    knownOutputPaths = false;
                    break;
                }
                if (wantOutput(outputName, bfd.outputs) && !isValidPath(*pathOpt))
                    invalid.insert(*pathOpt);
            }
            if (knownOutputPaths && invalid.empty()) return;

            auto drv = make_ref<Derivation>(derivationFromPath(bfd.drvPath));
            ParsedDerivation parsedDrv(StorePath(bfd.drvPath), *drv);

            if (knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) {
                auto drvState = make_ref<Sync<DrvState>>(DrvState(invalid.size()));
                for (auto & output : invalid)
                    pool.enqueue(std::bind(checkOutput, bfd.drvPath, drv, output, drvState));
            } else
                mustBuildDrv(bfd.drvPath, *drv);

          },
          [&](DerivedPath::Opaque bo) {

            if (isValidPath(bo.path)) return;

            SubstitutablePathInfos infos;
            querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos);

            if (infos.empty()) {
                auto state(state_.lock());
                state->unknown.insert(bo.path);
                return;
            }

            auto info = infos.find(bo.path);
            assert(info != infos.end());

            {
                auto state(state_.lock());
                state->willSubstitute.insert(bo.path);
                state->downloadSize += info->second.downloadSize;
                state->narSize += info->second.narSize;
            }

            for (auto & ref : info->second.references)
                pool.enqueue(std::bind(doPath, DerivedPath::Opaque { ref }));
          },
        }, req.raw());
    };

    for (auto & path : targets)
        pool.enqueue(std::bind(doPath, path));

    pool.process();
}

StorePaths Store::topoSortPaths(const StorePathSet & paths)
{
    return topoSort(paths,
        {[&](const StorePath & path) {
            StorePathSet references;
            try {
                references = queryPathInfo(path)->references;
            } catch (InvalidPath &) {
            }
            return references;
        }},
        {[&](const StorePath & path, const StorePath & parent) {
            return BuildError(
                "cycle detected in the references of '%s' from '%s'",
                printStorePath(path),
                printStorePath(parent));
        }});
}

}
<|endoftext|>


<commit_before>//---------------------------------------------------------
// Copyright 2018 Ontario Institute for Cancer Research
// Written by Joanna Pineda (joanna.pineda@oicr.on.ca)
//---------------------------------------------------------
//
// preqclr.hpp
// calculates basic QC statistics

#include <map>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include "sequence.hpp"

#include "readpaf/paf.h"

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"

using namespace std;
using namespace rapidjson;

typedef PrettyWriter<StringBuffer> JSONWriter;

double calculate_est_cov_and_est_genome_size( map<string, sequence> paf, JSONWriter* writer );
void calculate_read_length( vector <pair <double, int>> fq, JSONWriter* writer);
void calculate_GC_content( vector <pair <double, int>> fq, JSONWriter* writer);
void calculate_tot_bases( map<string, sequence> paf, JSONWriter* writer);
void calculate_ngx( vector<double> contig_lengths, double genome_size_est, JSONWriter* writer);
void calculate_total_num_bases_vs_min_cov( map<double, long long int, greater<double>> per_cov_total_num_bases, JSONWriter* writer);

int getopt( int argc, char* const* argv[], const char *optstring);
enum { OPT_VERSION, OPT_KEEP_LOW_COV, OPT_KEEP_HIGH_COV, OPT_KEEP_DUPS, OPT_REMOVE_INT_MATCHES, OPT_MAX_OVERHANG, OPT_MAX_OVERHANG_RATIO, OPT_REMOVE_CONTAINED, OPT_PRINT_READ_COV, OPT_KEEP_SELF_OVERLAPS, OPT_PRINT_GSE_STAT, OPT_PRINT_NEW_PAF };
void parse_args( int argc, char *argv[]);
map<string, sequence> parse_paf();
vector<double> parse_gfa();
vector<pair<double,int>> parse_fq( string readsFile );
<commit_msg>update h file<commit_after>//---------------------------------------------------------
// Copyright 2018 Ontario Institute for Cancer Research
// Written by Joanna Pineda (joanna.pineda@oicr.on.ca)
//---------------------------------------------------------
//
// preqclr.hpp
// calculates basic QC statistics

#include <map>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include "sequence.hpp"
#include "contig.hpp"

#include "readpaf/paf.h"

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"

using namespace std;
using namespace rapidjson;

typedef PrettyWriter<StringBuffer> JSONWriter;

double calculate_est_cov_and_est_genome_size( map<string, sequence> paf, JSONWriter* writer );
void calculate_read_length( vector <pair <double, int>> fq, JSONWriter* writer);
void calculate_GC_content( vector <pair <double, int>> fq, JSONWriter* writer);
void calculate_tot_bases( map<string, sequence> paf, JSONWriter* writer);
void calculate_ngx( map<string, contig> contigs, double genome_size_est, JSONWriter* writer);
void calculate_total_num_bases_vs_min_cov( map<double, long long int, greater<double>> per_cov_total_num_bases, JSONWriter* writer);
void calculate_repetitivity(map<string, contig> ctg, double g, int n, JSONWriter* writer );
map<string, contig> calculate_ctgs();

int getopt( int argc, char* const* argv[], const char *optstring);
enum { OPT_VERSION, OPT_KEEP_LOW_COV, OPT_KEEP_HIGH_COV, OPT_KEEP_DUPS, OPT_REMOVE_INT_MATCHES, OPT_MAX_OVERHANG, OPT_MAX_OVERHANG_RATIO, OPT_REMOVE_CONTAINED, OPT_PRINT_READ_COV, OPT_KEEP_SELF_OVERLAPS, OPT_PRINT_GSE_STAT, OPT_PRINT_NEW_PAF };
void parse_args( int argc, char *argv[]);
map<string, sequence> parse_paf();
void parse_gfa(map<string, contig> ctgs);
vector<pair<double,int>> parse_fq( string readsFile );
<|endoftext|>


<commit_before>/*
TidyEngine
Copyright (C) 2016 Jakob Sinclair

This program 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 3 of the License, or
(at your option) any later version.

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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Contact the author at: jakob.sinclair99@gmail.com
*/

#pragma once

#include <exception>
#include <string>
#include <FreeImage.h>

class Error : public std::exception {
public:
	Error()
	{
		;
	}
	Error(std::string s)
	{
		text = s;
	}

	virtual const char *what()
	{
		return text.c_str();
	}
private:
	std::string text = "";
};

void FreeImageError(FREE_IMAGE_FORMAT fif, const char *message);
<commit_msg>libTidyEngine: Fixed exception handling<commit_after>/*
TidyEngine
Copyright (C) 2016 Jakob Sinclair

This program 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 3 of the License, or
(at your option) any later version.

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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Contact the author at: jakob.sinclair99@gmail.com
*/

#pragma once

#include <exception>
#include <string>
#include <FreeImage.h>

class Error : public std::exception {
public:
	Error()
	{
		;
	}
	Error(std::string s)
	{
		text = s;
	}

	virtual const char *what() const
        {
		return text.c_str();
	}
private:
	std::string text = "";
};

void FreeImageError(FREE_IMAGE_FORMAT fif, const char *message);
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// GalleryWatchManager implementation.

#include "chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.h"

#include <list>
#include <set>

#include "base/bind.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/files/file_path_watcher.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/time.h"
#include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h"
#include "content/public/browser/browser_thread.h"

namespace extensions {

namespace {

using content::BrowserThread;

// Map to keep track of profile specific GalleryWatchManager objects.
// Key: Profile identifier.
// Value: GalleryWatchManager*.
// This map owns the GalleryWatchManager object.
typedef std::map<void*, extensions::GalleryWatchManager*> WatchManagerMap;
WatchManagerMap* g_gallery_watch_managers = NULL;

// Dispatches the gallery changed event on the UI thread.
void SendGalleryChangedEventOnUIThread(
    base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router,
    chrome::MediaGalleryPrefId gallery_id,
    const std::set<std::string>& extension_ids) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (event_router.get())
    event_router->OnGalleryChanged(gallery_id, extension_ids);
}

}  // namespace

///////////////////////////////////////////////////////////////////////////////
//            GalleryWatchManager::GalleryFilePathWatcher                    //
///////////////////////////////////////////////////////////////////////////////

// This class does a recursive watch on the gallery file path and holds a list
// of extensions that are watching the gallery. When there is a file system
// activity within the gallery, GalleryFilePathWatcher notifies the interested
// extensions. This class lives on the file thread.
class GalleryWatchManager::GalleryFilePathWatcher
    : public base::RefCounted<GalleryFilePathWatcher> {
 public:
  // |on_destroyed_callback| is called when the last GalleryFilePathWatcher
  // reference goes away.
  GalleryFilePathWatcher(
      base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router,
      chrome::MediaGalleryPrefId gallery_id,
      const FilePath& path,
      const std::string& extension_id,
      const base::Closure& on_destroyed_callback);

  // Adds the extension reference to the watched gallery.
  void AddExtension(const std::string& extension_id);

  // Removes the extension reference to the watched gallery.
  void RemoveExtension(const std::string& extension_id);

  // Handles the extension unloaded/uninstalled/destroyed event.
  void OnExtensionDestroyed(const std::string& extension_id);

  // Sets up the watch operation for the specified |gallery_path_|. On
  // success, returns true.
  bool SetupWatch();

  // Removes all the extension references when the browser profile is in
  // shutdown mode.
  void RemoveAllWatchReferences();

 private:
  friend class base::RefCounted<GalleryFilePathWatcher>;

  // Keeps track of extension watch details.
  struct ExtensionWatchInfo {
    ExtensionWatchInfo();

    // Number of watches in this extension, e.g "3"
    int watch_count;

    // Used to manage the gallery changed events.
    base::Time last_gallery_changed_event;
  };

  typedef std::map<std::string, ExtensionWatchInfo> ExtensionWatchInfoMap;

  // Private because GalleryFilePathWatcher is ref-counted.
  virtual ~GalleryFilePathWatcher();

  // FilePathWatcher callback.
  void OnFilePathChanged(const FilePath& path, bool error);

  // Remove the watch references for the extension specified by the
  // |extension_id|.
  void RemoveExtensionReferences(const std::string& extension_id);

  // Used to notify the interested extensions about the gallery changed event.
  base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router_;

  // The gallery identifier, e.g "1".
  chrome::MediaGalleryPrefId gallery_id_;

  // The gallery file path watcher.
  base::FilePathWatcher file_watcher_;

  // The gallery file path, e.g "C:\My Pictures".
  FilePath gallery_path_;

  // A callback to call when |this| object is destroyed.
  base::Closure on_destroyed_callback_;

  // Map to keep track of the extension and its corresponding watch count.
  // Key: Extension identifier, e.g "qoueruoweuroiwueroiwujkshdf".
  // Value: Watch information.
  ExtensionWatchInfoMap extension_watch_info_map_;

  // Used to provide a weak pointer to FilePathWatcher callback.
  base::WeakPtrFactory<GalleryFilePathWatcher> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(GalleryFilePathWatcher);
};

GalleryWatchManager::GalleryFilePathWatcher::GalleryFilePathWatcher(
    base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router,
    chrome::MediaGalleryPrefId gallery_id,
    const FilePath& path,
    const std::string& extension_id,
    const base::Closure& on_destroyed_callback)
    : event_router_(event_router),
      gallery_id_(gallery_id),
      on_destroyed_callback_(on_destroyed_callback),
      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  gallery_path_ = path;
  AddExtension(extension_id);
}

void GalleryWatchManager::GalleryFilePathWatcher::AddExtension(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  extension_watch_info_map_[extension_id].watch_count++;
  AddRef();
}

void GalleryWatchManager::GalleryFilePathWatcher::RemoveExtension(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  ExtensionWatchInfoMap::iterator it =
      extension_watch_info_map_.find(extension_id);
  if (it == extension_watch_info_map_.end())
    return;
  // If entry found - decrease it's count and remove if necessary
  it->second.watch_count--;
  if (0 == it->second.watch_count)
    extension_watch_info_map_.erase(it);
  Release();
}

void GalleryWatchManager::GalleryFilePathWatcher::OnExtensionDestroyed(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  RemoveExtensionReferences(extension_id);
}

bool GalleryWatchManager::GalleryFilePathWatcher::SetupWatch() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  return file_watcher_.Watch(
      gallery_path_, true,
      base::Bind(&GalleryFilePathWatcher::OnFilePathChanged,
                 weak_ptr_factory_.GetWeakPtr()));
}

void GalleryWatchManager::GalleryFilePathWatcher::RemoveAllWatchReferences() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  std::set<std::string> extension_ids;
  for (ExtensionWatchInfoMap::iterator iter = extension_watch_info_map_.begin();
       iter != extension_watch_info_map_.end(); ++iter)
    extension_ids.insert(iter->first);

  for (std::set<std::string>::const_iterator it = extension_ids.begin();
       it != extension_ids.end(); ++it)
    RemoveExtensionReferences(*it);
}

GalleryWatchManager::GalleryFilePathWatcher::~GalleryFilePathWatcher() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  on_destroyed_callback_.Run();
}

GalleryWatchManager::GalleryFilePathWatcher::ExtensionWatchInfo::
ExtensionWatchInfo()
    : watch_count(0) {
}

void GalleryWatchManager::GalleryFilePathWatcher::OnFilePathChanged(
    const FilePath& path,
    bool error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  if (error || (path != gallery_path_))
    return;

  std::set<std::string> extension_ids;
  for (ExtensionWatchInfoMap::iterator iter = extension_watch_info_map_.begin();
       iter != extension_watch_info_map_.end(); ++iter) {
    if (!iter->second.last_gallery_changed_event.is_null()) {
      // Ignore gallery change event if it is received too frequently.
      // For example, when an user copies/deletes 1000 media files from a
      // gallery, this callback is called 1000 times within a span of 10ms.
      // GalleryWatchManager should not send 1000 gallery changed events to
      // the watching extension.
      const int kMinSecondsToIgnoreGalleryChangedEvent = 3;
      base::TimeDelta diff =
          base::Time::Now() - iter->second.last_gallery_changed_event;
      if (diff.InSeconds() < kMinSecondsToIgnoreGalleryChangedEvent)
        continue;
    }
    iter->second.last_gallery_changed_event = base::Time::Now();
    extension_ids.insert(iter->first);
  }
  if (!extension_ids.empty()) {
    content::BrowserThread::PostTask(
        content::BrowserThread::UI, FROM_HERE,
        base::Bind(SendGalleryChangedEventOnUIThread, event_router_,
                   gallery_id_, extension_ids));
  }
}

void GalleryWatchManager::GalleryFilePathWatcher::RemoveExtensionReferences(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  ExtensionWatchInfoMap::iterator it =
      extension_watch_info_map_.find(extension_id);
  if (it == extension_watch_info_map_.end())
    return;
  int watch_count = it->second.watch_count;
  extension_watch_info_map_.erase(it);
  for (int i = 0; i < watch_count; ++i)
    Release();
}

///////////////////////////////////////////////////////////////////////////////
//                       GalleryWatchManager                                 //
///////////////////////////////////////////////////////////////////////////////

// static
GalleryWatchManager* GalleryWatchManager::GetForProfile(
    void* profile_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DCHECK(profile_id);
  bool has_watch_manager = (g_gallery_watch_managers &&
                            GalleryWatchManager::HasForProfile(profile_id));
  if (!g_gallery_watch_managers)
    g_gallery_watch_managers = new WatchManagerMap;
  if (!has_watch_manager)
    (*g_gallery_watch_managers)[profile_id] = new GalleryWatchManager;
  return (*g_gallery_watch_managers)[profile_id];
}

// static
bool GalleryWatchManager::HasForProfile(void* profile_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DCHECK(profile_id);
  if (!g_gallery_watch_managers)
    return false;
  WatchManagerMap::const_iterator it =
      g_gallery_watch_managers->find(profile_id);
  return (it != g_gallery_watch_managers->end());
}

// static
void GalleryWatchManager::OnProfileShutdown(void* profile_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DCHECK(profile_id);
  if (!g_gallery_watch_managers || g_gallery_watch_managers->empty())
    return;
  WatchManagerMap::iterator it = g_gallery_watch_managers->find(profile_id);
  if (it == g_gallery_watch_managers->end())
    return;
  delete it->second;
  g_gallery_watch_managers->erase(it);
  if (g_gallery_watch_managers->empty())
    delete g_gallery_watch_managers;
}

GalleryWatchManager::~GalleryWatchManager() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DeleteAllWatchers();
}

bool GalleryWatchManager::StartGalleryWatch(
    chrome::MediaGalleryPrefId gallery_id,
    const FilePath& watch_path,
    const std::string& extension_id,
    base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  WatcherMap::const_iterator iter = gallery_watchers_.find(watch_path);
  if (iter != gallery_watchers_.end()) {
    // Already watched.
    iter->second->AddExtension(extension_id);
    return true;
  }

  // Need to add a new watcher.
  scoped_refptr<GalleryFilePathWatcher> watch(
      new GalleryFilePathWatcher(
          event_router, gallery_id, watch_path, extension_id,
          base::Bind(&GalleryWatchManager::RemoveGalleryFilePathWatcherEntry,
                     base::Unretained(this),
                     watch_path)));
  if (!watch->SetupWatch())
    return false;
  gallery_watchers_[watch_path] = watch.get();
  return true;
}

void GalleryWatchManager::StopGalleryWatch(
    const FilePath& watch_path,
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  WatcherMap::iterator iter = gallery_watchers_.find(watch_path);
  if (iter == gallery_watchers_.end())
    return;
  // Remove the renderer process for this watch.
  iter->second->RemoveExtension(extension_id);
}

void GalleryWatchManager::OnExtensionDestroyed(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  std::list<FilePath> watchers_to_notify;
  for (WatcherMap::iterator iter = gallery_watchers_.begin();
       iter != gallery_watchers_.end(); ++iter)
    watchers_to_notify.push_back(iter->first);

  for (std::list<FilePath>::const_iterator path = watchers_to_notify.begin();
       path != watchers_to_notify.end(); ++path) {
     WatcherMap::iterator iter = gallery_watchers_.find(*path);
     if (iter == gallery_watchers_.end())
       continue;
     iter->second->OnExtensionDestroyed(extension_id);
  }
}

GalleryWatchManager::GalleryWatchManager() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
}

void GalleryWatchManager::DeleteAllWatchers() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  if (gallery_watchers_.empty())
    return;

  for (WatcherMap::iterator iter = gallery_watchers_.begin();
       iter != gallery_watchers_.end(); ++iter)
    iter->second->RemoveAllWatchReferences();
}

void GalleryWatchManager::RemoveGalleryFilePathWatcherEntry(
    const FilePath& watch_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  gallery_watchers_.erase(watch_path);
}

}  // namespace extensions
<commit_msg>[Media Gallery] Remove extension gallery watch count details from GalleryFilePathWatcher.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// GalleryWatchManager implementation.

#include "chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.h"

#include <list>
#include <set>

#include "base/bind.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/files/file_path_watcher.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
#include "base/time.h"
#include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h"
#include "content/public/browser/browser_thread.h"

namespace extensions {

namespace {

using content::BrowserThread;

// Map to keep track of profile specific GalleryWatchManager objects.
// Key: Profile identifier.
// Value: GalleryWatchManager*.
// This map owns the GalleryWatchManager object.
typedef std::map<void*, extensions::GalleryWatchManager*> WatchManagerMap;
WatchManagerMap* g_gallery_watch_managers = NULL;

// Dispatches the gallery changed event on the UI thread.
void SendGalleryChangedEventOnUIThread(
    base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router,
    chrome::MediaGalleryPrefId gallery_id,
    const std::set<std::string>& extension_ids) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (event_router.get())
    event_router->OnGalleryChanged(gallery_id, extension_ids);
}

}  // namespace

///////////////////////////////////////////////////////////////////////////////
//            GalleryWatchManager::GalleryFilePathWatcher                    //
///////////////////////////////////////////////////////////////////////////////

// This class does a recursive watch on the gallery file path and holds a list
// of extensions that are watching the gallery. When there is a file system
// activity within the gallery, GalleryFilePathWatcher notifies the interested
// extensions. This class lives on the file thread.
class GalleryWatchManager::GalleryFilePathWatcher
    : public base::RefCounted<GalleryFilePathWatcher> {
 public:
  // |on_destroyed_callback| is called when the last GalleryFilePathWatcher
  // reference goes away.
  GalleryFilePathWatcher(
      base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router,
      chrome::MediaGalleryPrefId gallery_id,
      const FilePath& path,
      const std::string& extension_id,
      const base::Closure& on_destroyed_callback);

  // Adds the extension reference to the watched gallery.
  void AddExtension(const std::string& extension_id);

  // Removes the extension reference to the watched gallery.
  void RemoveExtension(const std::string& extension_id);

  // Handles the extension unloaded/uninstalled/destroyed event.
  void OnExtensionDestroyed(const std::string& extension_id);

  // Sets up the watch operation for the specified |gallery_path_|. On
  // success, returns true.
  bool SetupWatch();

  // Removes all the extension references when the browser profile is in
  // shutdown mode.
  void RemoveAllWatchReferences();

 private:
  friend class base::RefCounted<GalleryFilePathWatcher>;

  // Key: Extension identifier, e.g "qoueruoweuroiwueroiwujkshdf".
  // Value: Time at which the last gallery changed event is dispatched.
  //        Initialized to null Time value.
  typedef std::map<std::string, base::Time> ExtensionWatchInfoMap;

  // Private because GalleryFilePathWatcher is ref-counted.
  virtual ~GalleryFilePathWatcher();

  // FilePathWatcher callback.
  void OnFilePathChanged(const FilePath& path, bool error);

  // Remove the watch references for the extension specified by the
  // |extension_id|.
  void RemoveExtensionReferences(const std::string& extension_id);

  // Used to notify the interested extensions about the gallery changed event.
  base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router_;

  // The gallery identifier, e.g "1".
  chrome::MediaGalleryPrefId gallery_id_;

  // The gallery file path watcher.
  base::FilePathWatcher file_watcher_;

  // The gallery file path, e.g "C:\My Pictures".
  FilePath gallery_path_;

  // A callback to call when |this| object is destroyed.
  base::Closure on_destroyed_callback_;

  // Map to keep track of the extension and its corresponding watch count.
  ExtensionWatchInfoMap extension_watch_info_map_;

  // Used to provide a weak pointer to FilePathWatcher callback.
  base::WeakPtrFactory<GalleryFilePathWatcher> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(GalleryFilePathWatcher);
};

GalleryWatchManager::GalleryFilePathWatcher::GalleryFilePathWatcher(
    base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router,
    chrome::MediaGalleryPrefId gallery_id,
    const FilePath& path,
    const std::string& extension_id,
    const base::Closure& on_destroyed_callback)
    : event_router_(event_router),
      gallery_id_(gallery_id),
      on_destroyed_callback_(on_destroyed_callback),
      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  gallery_path_ = path;
  AddExtension(extension_id);
}

void GalleryWatchManager::GalleryFilePathWatcher::AddExtension(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  if (ContainsKey(extension_watch_info_map_, extension_id))
    return;
  extension_watch_info_map_[extension_id] = base::Time();
  AddRef();
}

void GalleryWatchManager::GalleryFilePathWatcher::RemoveExtension(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  if (extension_watch_info_map_.erase(extension_id) == 1)
    Release();
}

void GalleryWatchManager::GalleryFilePathWatcher::OnExtensionDestroyed(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  RemoveExtensionReferences(extension_id);
}

bool GalleryWatchManager::GalleryFilePathWatcher::SetupWatch() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  return file_watcher_.Watch(
      gallery_path_, true,
      base::Bind(&GalleryFilePathWatcher::OnFilePathChanged,
                 weak_ptr_factory_.GetWeakPtr()));
}

void GalleryWatchManager::GalleryFilePathWatcher::RemoveAllWatchReferences() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  std::set<std::string> extension_ids;
  for (ExtensionWatchInfoMap::iterator iter = extension_watch_info_map_.begin();
       iter != extension_watch_info_map_.end(); ++iter)
    extension_ids.insert(iter->first);

  for (std::set<std::string>::const_iterator it = extension_ids.begin();
       it != extension_ids.end(); ++it)
    RemoveExtensionReferences(*it);
}

GalleryWatchManager::GalleryFilePathWatcher::~GalleryFilePathWatcher() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  on_destroyed_callback_.Run();
}

void GalleryWatchManager::GalleryFilePathWatcher::OnFilePathChanged(
    const FilePath& path,
    bool error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  if (error || (path != gallery_path_))
    return;

  std::set<std::string> extension_ids;
  for (ExtensionWatchInfoMap::iterator iter = extension_watch_info_map_.begin();
       iter != extension_watch_info_map_.end(); ++iter) {
    if (!iter->second.is_null()) {
      // Ignore gallery change event if it is received too frequently.
      // For example, when an user copies/deletes 1000 media files from a
      // gallery, this callback is called 1000 times within a span of 10ms.
      // GalleryWatchManager should not send 1000 gallery changed events to
      // the watching extension.
      const int kMinSecondsToIgnoreGalleryChangedEvent = 3;
      base::TimeDelta diff = base::Time::Now() - iter->second;
      if (diff.InSeconds() < kMinSecondsToIgnoreGalleryChangedEvent)
        continue;
    }
    iter->second = base::Time::Now();
    extension_ids.insert(iter->first);
  }
  if (!extension_ids.empty()) {
    content::BrowserThread::PostTask(
        content::BrowserThread::UI, FROM_HERE,
        base::Bind(SendGalleryChangedEventOnUIThread, event_router_,
                   gallery_id_, extension_ids));
  }
}

void GalleryWatchManager::GalleryFilePathWatcher::RemoveExtensionReferences(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  ExtensionWatchInfoMap::iterator it =
      extension_watch_info_map_.find(extension_id);
  if (it == extension_watch_info_map_.end())
    return;
  extension_watch_info_map_.erase(it);
  Release();
}

///////////////////////////////////////////////////////////////////////////////
//                       GalleryWatchManager                                 //
///////////////////////////////////////////////////////////////////////////////

// static
GalleryWatchManager* GalleryWatchManager::GetForProfile(
    void* profile_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DCHECK(profile_id);
  bool has_watch_manager = (g_gallery_watch_managers &&
                            GalleryWatchManager::HasForProfile(profile_id));
  if (!g_gallery_watch_managers)
    g_gallery_watch_managers = new WatchManagerMap;
  if (!has_watch_manager)
    (*g_gallery_watch_managers)[profile_id] = new GalleryWatchManager;
  return (*g_gallery_watch_managers)[profile_id];
}

// static
bool GalleryWatchManager::HasForProfile(void* profile_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DCHECK(profile_id);
  if (!g_gallery_watch_managers)
    return false;
  WatchManagerMap::const_iterator it =
      g_gallery_watch_managers->find(profile_id);
  return (it != g_gallery_watch_managers->end());
}

// static
void GalleryWatchManager::OnProfileShutdown(void* profile_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DCHECK(profile_id);
  if (!g_gallery_watch_managers || g_gallery_watch_managers->empty())
    return;
  WatchManagerMap::iterator it = g_gallery_watch_managers->find(profile_id);
  if (it == g_gallery_watch_managers->end())
    return;
  delete it->second;
  g_gallery_watch_managers->erase(it);
  if (g_gallery_watch_managers->empty())
    delete g_gallery_watch_managers;
}

GalleryWatchManager::~GalleryWatchManager() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DeleteAllWatchers();
}

bool GalleryWatchManager::StartGalleryWatch(
    chrome::MediaGalleryPrefId gallery_id,
    const FilePath& watch_path,
    const std::string& extension_id,
    base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  WatcherMap::const_iterator iter = gallery_watchers_.find(watch_path);
  if (iter != gallery_watchers_.end()) {
    // Already watched.
    iter->second->AddExtension(extension_id);
    return true;
  }

  // Need to add a new watcher.
  scoped_refptr<GalleryFilePathWatcher> watch(
      new GalleryFilePathWatcher(
          event_router, gallery_id, watch_path, extension_id,
          base::Bind(&GalleryWatchManager::RemoveGalleryFilePathWatcherEntry,
                     base::Unretained(this),
                     watch_path)));
  if (!watch->SetupWatch())
    return false;
  gallery_watchers_[watch_path] = watch.get();
  return true;
}

void GalleryWatchManager::StopGalleryWatch(
    const FilePath& watch_path,
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  WatcherMap::iterator iter = gallery_watchers_.find(watch_path);
  if (iter == gallery_watchers_.end())
    return;
  // Remove the renderer process for this watch.
  iter->second->RemoveExtension(extension_id);
}

void GalleryWatchManager::OnExtensionDestroyed(
    const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  std::list<FilePath> watchers_to_notify;
  for (WatcherMap::iterator iter = gallery_watchers_.begin();
       iter != gallery_watchers_.end(); ++iter)
    watchers_to_notify.push_back(iter->first);

  for (std::list<FilePath>::const_iterator path = watchers_to_notify.begin();
       path != watchers_to_notify.end(); ++path) {
     WatcherMap::iterator iter = gallery_watchers_.find(*path);
     if (iter == gallery_watchers_.end())
       continue;
     iter->second->OnExtensionDestroyed(extension_id);
  }
}

GalleryWatchManager::GalleryWatchManager() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
}

void GalleryWatchManager::DeleteAllWatchers() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  if (gallery_watchers_.empty())
    return;

  for (WatcherMap::iterator iter = gallery_watchers_.begin();
       iter != gallery_watchers_.end(); ++iter)
    iter->second->RemoveAllWatchReferences();
}

void GalleryWatchManager::RemoveGalleryFilePathWatcherEntry(
    const FilePath& watch_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  gallery_watchers_.erase(watch_path);
}

}  // namespace extensions
<|endoftext|>


<commit_before>// -*- C++ -*-

// The MIT License (MIT)
//
// Copyright (c) 2017 Alexander Samoilov
//
// 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 <iostream>
#include <fstream>
#include <cmath>
#include "parameters.hpp"
#include "program_options.hpp"
#include "lin_alg_types.hpp"

int
body_ax_geo(program_options const& popt)
{
    if (popt.flow_type == to_underlying(FlowType::SPHERE)) {
        std::string fname = (popt.input_data == "") ? "sphere.dat" : popt.input_data;
        std::ifstream ifs(fname);
        if (ifs) {
        }
    } else if (popt.flow_type == to_underlying(FlowType::THORUS)) {
    }
} // body_ax_geo

<commit_msg>`split_string` implementation.<commit_after>// -*- C++ -*-

// The MIT License (MIT)
//
// Copyright (c) 2017 Alexander Samoilov
//
// 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 <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
#include <cmath>
#include "parameters.hpp"
#include "program_options.hpp"
#include "lin_alg_types.hpp"

std::vector<std::string>
split_string(std::string s)
{
    std::stringstream ss(s);
    std::istream_iterator<std::string> begin(ss);
    std::istream_iterator<std::string> end;
    std::vector<std::string> vstrings(begin, end);
    std::copy(vstrings.begin(), vstrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
    std::move(vstrings);
}

int
body_ax_geo(program_options const& popt)
{
    std::string line;
    if (popt.flow_type == to_underlying(FlowType::SPHERE)) {
        std::string fname = (popt.input_data == "") ? "sphere.dat" : popt.input_data;
        std::ifstream ifs(fname);
        if (ifs) {
            int ngl;
            std::getline(ifs, line); *split_string(line).begin();
        }
    } else if (popt.flow_type == to_underlying(FlowType::THORUS)) {
    }
} // body_ax_geo

<|endoftext|>


<commit_before>//
//  Copyright (C) 2013-2015 mogemimi.
//  Distributed under the MIT License. See LICENSE.md or
//  http://enginetrouble.net/pomdog/license for details.
//

#include "InGameEditor.hpp"
#include "detail/SpriteDrawingContext.hpp"
#include "Pomdog.Experimental/Graphics/EffectPassBuilder.hpp"
#include "Pomdog.Experimental/Graphics/SpriteBatch.hpp"
#include "Pomdog.Experimental/Graphics/SpriteFont.hpp"
#include "Pomdog.Experimental/Graphics/SpriteFontLoader.hpp"
#include "Pomdog.Experimental/UI/UIView.hpp"
#include "Pomdog/Graphics/detail/BuiltinShaderPool.hpp"

namespace Pomdog {
namespace SceneEditor {
namespace {

// Built-in shaders
#include "Pomdog.Experimental/Graphics/Shaders/GLSL.Embedded/SpriteBatch_VS.inc.h"
#include "Pomdog.Experimental/Graphics/Shaders/GLSL.Embedded/Sprite_DistanceField_PS.inc.h"

struct BuiltinEffectSpriteBatchDistanceFieldTrait {
	static std::shared_ptr<EffectPass> Create(GraphicsDevice & graphicsDevice)
	{
		using PositionTextureCoord = CustomVertex<Vector4>;
		using SpriteInfoVertex = CustomVertex<Vector4, Vector4, Vector4, Vector4>;

		auto declartation = PositionTextureCoord::Declaration();

		auto effectPass = EffectPassBuilder(graphicsDevice)
			.VertexShaderGLSL(Builtin_GLSL_SpriteBatch_VS, std::strlen(Builtin_GLSL_SpriteBatch_VS))
			.PixelShaderGLSL(Builtin_GLSL_Sprite_DistanceField_PS, std::strlen(Builtin_GLSL_Sprite_DistanceField_PS))
			.InputElements(std::initializer_list<VertexBufferBinding>{
				{declartation, 0, 0},
				{SpriteInfoVertex::Declaration(), declartation.StrideBytes(), 1}
			})
			.Create();
		return std::move(effectPass);
	}
};

}// unnamed namespace
//-----------------------------------------------------------------------
InGameEditor::InGameEditor(std::shared_ptr<GameHost> const& gameHostIn)
	: hierarchy(gameHostIn->Window())
	, gameHost(gameHostIn)
{
	auto graphicsContext = gameHost->GraphicsContext();
	auto graphicsDevice = gameHost->GraphicsDevice();
	auto assets = gameHost->AssetManager();
	auto window = gameHost->Window();

	{
		spriteBatch = std::make_unique<SpriteBatch>(graphicsContext, graphicsDevice);
		//spriteFont = SpriteFontLoader::Load(*assets, "BitmapFonts/UbuntuMono-Regular.fnt");
		spriteFont = SpriteFontLoader::Load(*assets, "BitmapFonts/Ubuntu-Regular.fnt");
		distanceFieldEffect = graphicsDevice->ShaderPool().Create<BuiltinEffectSpriteBatchDistanceFieldTrait>(*graphicsDevice);
		constantBuffers = std::make_shared<ConstantBufferBinding>(graphicsDevice, *distanceFieldEffect);
		spriteBatchDistanceField = std::make_unique<SpriteBatch>(graphicsContext, graphicsDevice,
			distanceFieldEffect, constantBuffers);
	}
	{
		blankTexture = std::make_shared<Texture2D>(graphicsDevice,
			1, 1, false, SurfaceFormat::R8G8B8A8_UNorm);
		std::array<std::uint32_t, 1> pixelData = {0xffffffff};
		blankTexture->SetData(pixelData.data());
	}
	{
		depthStencilState = DepthStencilState::CreateNone(graphicsDevice);
		blendState = BlendState::CreateNonPremultiplied(graphicsDevice);
	}

	clientSizeChangedConnection = window->ClientSizeChanged.Connect([this](int width, int height) {
		hierarchy.RenderSizeChanged(width, height);
	});
}
//-----------------------------------------------------------------------
InGameEditor::~InGameEditor() = default;
//-----------------------------------------------------------------------
void InGameEditor::AddView(std::shared_ptr<UI::UIView> const& view)
{
	POMDOG_ASSERT(view->Parent().expired());
	hierarchy.AddChild(view);
}
//-----------------------------------------------------------------------
void InGameEditor::Update()
{
	if (auto mouse = gameHost->Mouse()) {
		hierarchy.Touch(mouse->GetState());
	}

	auto clock = gameHost->Clock();
	hierarchy.UpdateAnimation(clock->FrameDuration());
}
//-----------------------------------------------------------------------
void InGameEditor::DrawGUI(GraphicsContext & graphicsContext)
{
	auto depthStencilStateOld = graphicsContext.GetDepthStencilState();
	graphicsContext.SetDepthStencilState(depthStencilState);

	auto blendStateOld = graphicsContext.GetBlendState();
	graphicsContext.SetBlendState(blendState);

	{
		POMDOG_ASSERT(spriteBatch);
		spriteBatch->Begin(SpriteSortMode::BackToFront);
		UI::SpriteDrawingContext drawingContext(*spriteBatch, *spriteBatchDistanceField, distanceFieldEffect, constantBuffers, *spriteFont, blankTexture);
		hierarchy.Draw(drawingContext);
		spriteBatch->End();
	}

	graphicsContext.SetDepthStencilState(depthStencilStateOld);
	graphicsContext.SetBlendState(blendStateOld);
}
//-----------------------------------------------------------------------
}// namespace SceneEditor
}// namespace Pomdog
<commit_msg>Add HLSL shader<commit_after>//
//  Copyright (C) 2013-2015 mogemimi.
//  Distributed under the MIT License. See LICENSE.md or
//  http://enginetrouble.net/pomdog/license for details.
//

#include "InGameEditor.hpp"
#include "detail/SpriteDrawingContext.hpp"
#include "Pomdog.Experimental/Graphics/EffectPassBuilder.hpp"
#include "Pomdog.Experimental/Graphics/SpriteBatch.hpp"
#include "Pomdog.Experimental/Graphics/SpriteFont.hpp"
#include "Pomdog.Experimental/Graphics/SpriteFontLoader.hpp"
#include "Pomdog.Experimental/UI/UIView.hpp"
#include "Pomdog/Graphics/detail/BuiltinShaderPool.hpp"

namespace Pomdog {
namespace SceneEditor {
namespace {

// Built-in shaders
#include "Pomdog.Experimental/Graphics/Shaders/GLSL.Embedded/SpriteBatch_VS.inc.h"
#include "Pomdog.Experimental/Graphics/Shaders/GLSL.Embedded/Sprite_DistanceField_PS.inc.h"
#include "Pomdog.Experimental/Graphics/Shaders/HLSL.Embedded/SpriteBatch_VS.inc.hpp"
#include "Pomdog.Experimental/Graphics/Shaders/HLSL.Embedded/SpriteDistanceField_PS.inc.hpp"

struct BuiltinEffectSpriteBatchDistanceFieldTrait {
	static std::shared_ptr<EffectPass> Create(GraphicsDevice & graphicsDevice)
	{
		using PositionTextureCoord = CustomVertex<Vector4>;
		using SpriteInfoVertex = CustomVertex<Vector4, Vector4, Vector4, Vector4>;

		auto declartation = PositionTextureCoord::Declaration();

		auto effectPass = EffectPassBuilder(graphicsDevice)
			.VertexShaderGLSL(Builtin_GLSL_SpriteBatch_VS, std::strlen(Builtin_GLSL_SpriteBatch_VS))
			.PixelShaderGLSL(Builtin_GLSL_Sprite_DistanceField_PS, std::strlen(Builtin_GLSL_Sprite_DistanceField_PS))
			.VertexShaderHLSLPrecompiled(BuiltinHLSL_SpriteBatch_VS, sizeof(BuiltinHLSL_SpriteBatch_VS))
			.PixelShaderHLSLPrecompiled(BuiltinHLSL_SpriteDistanceField_PS, sizeof(BuiltinHLSL_SpriteDistanceField_PS))
			.InputElements(std::initializer_list<VertexBufferBinding>{
				{declartation, 0, 0},
				{SpriteInfoVertex::Declaration(), declartation.StrideBytes(), 1}
			})
			.Create();
		return std::move(effectPass);
	}
};

}// unnamed namespace
//-----------------------------------------------------------------------
InGameEditor::InGameEditor(std::shared_ptr<GameHost> const& gameHostIn)
	: hierarchy(gameHostIn->Window())
	, gameHost(gameHostIn)
{
	auto graphicsContext = gameHost->GraphicsContext();
	auto graphicsDevice = gameHost->GraphicsDevice();
	auto assets = gameHost->AssetManager();
	auto window = gameHost->Window();

	{
		spriteBatch = std::make_unique<SpriteBatch>(graphicsContext, graphicsDevice);
		//spriteFont = SpriteFontLoader::Load(*assets, "BitmapFonts/UbuntuMono-Regular.fnt");
		spriteFont = SpriteFontLoader::Load(*assets, "BitmapFonts/Ubuntu-Regular.fnt");
		distanceFieldEffect = graphicsDevice->ShaderPool().Create<BuiltinEffectSpriteBatchDistanceFieldTrait>(*graphicsDevice);
		constantBuffers = std::make_shared<ConstantBufferBinding>(graphicsDevice, *distanceFieldEffect);
		spriteBatchDistanceField = std::make_unique<SpriteBatch>(graphicsContext, graphicsDevice,
			distanceFieldEffect, constantBuffers);
	}
	{
		blankTexture = std::make_shared<Texture2D>(graphicsDevice,
			1, 1, false, SurfaceFormat::R8G8B8A8_UNorm);
		std::array<std::uint32_t, 1> pixelData = {0xffffffff};
		blankTexture->SetData(pixelData.data());
	}
	{
		depthStencilState = DepthStencilState::CreateNone(graphicsDevice);
		blendState = BlendState::CreateNonPremultiplied(graphicsDevice);
	}

	clientSizeChangedConnection = window->ClientSizeChanged.Connect([this](int width, int height) {
		hierarchy.RenderSizeChanged(width, height);
	});
}
//-----------------------------------------------------------------------
InGameEditor::~InGameEditor() = default;
//-----------------------------------------------------------------------
void InGameEditor::AddView(std::shared_ptr<UI::UIView> const& view)
{
	POMDOG_ASSERT(view->Parent().expired());
	hierarchy.AddChild(view);
}
//-----------------------------------------------------------------------
void InGameEditor::Update()
{
	if (auto mouse = gameHost->Mouse()) {
		hierarchy.Touch(mouse->GetState());
	}

	auto clock = gameHost->Clock();
	hierarchy.UpdateAnimation(clock->FrameDuration());
}
//-----------------------------------------------------------------------
void InGameEditor::DrawGUI(GraphicsContext & graphicsContext)
{
	auto depthStencilStateOld = graphicsContext.GetDepthStencilState();
	graphicsContext.SetDepthStencilState(depthStencilState);

	auto blendStateOld = graphicsContext.GetBlendState();
	graphicsContext.SetBlendState(blendState);

	{
		POMDOG_ASSERT(spriteBatch);
		spriteBatch->Begin(SpriteSortMode::BackToFront);
		UI::SpriteDrawingContext drawingContext(*spriteBatch, *spriteBatchDistanceField, distanceFieldEffect, constantBuffers, *spriteFont, blankTexture);
		hierarchy.Draw(drawingContext);
		spriteBatch->End();
	}

	graphicsContext.SetDepthStencilState(depthStencilStateOld);
	graphicsContext.SetBlendState(blendStateOld);
}
//-----------------------------------------------------------------------
}// namespace SceneEditor
}// namespace Pomdog
<|endoftext|>