<commit_before>#ifndef IO_HELPERS_HPP_
#define IO_HELPERS_HPP_

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkTransformFileReader.h"
#include "itkTransformFileWriter.h"

#include "PathHelpers.hpp"

using namespace std;

// Reader helpers
itk::TransformBase::Pointer readTransform(const string& fileName)
{
  typedef itk::TransformFileReader ReaderType;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( fileName.c_str() );

  try
  {
    reader->Update();
  }
  catch( itk::ExceptionObject & err )
  {
    std::cerr << "ExceptionObject caught while reading transform." << std::endl;
    cerr << err << endl;
		exit(EXIT_FAILURE);
  }

  return *(reader->GetTransformList()->begin());
}

template<typename ImageType>
typename ImageType::Pointer readImage(const string& fileName)
{
  typedef itk::ImageFileReader< ImageType > ReaderType;
  typename ReaderType::Pointer reader = ReaderType::New();

  reader->SetFileName( fileName.c_str() );

  try {
  	reader->Update();
  }
	catch( itk::ExceptionObject & err ) {
    cerr << "ExceptionObject caught while reading image." << endl;
    cerr << err << endl;
		exit(EXIT_FAILURE);
	}

  return reader->GetOutput();
}

template <typename ImageType>
vector< typename ImageType::Pointer > readImages(vector< string > fileNames)
{
  vector< typename ImageType::Pointer > originalImages;

	for(unsigned int i=0; i<fileNames.size(); i++)
	{
	  if( fileExists(fileNames[i]) )
	  {
      originalImages.push_back( readImage< ImageType >(fileNames[i]) );
	  }
	  else
	  {
	    // create a new image of zero size
      originalImages.push_back( ImageType::New() );
	  }
	}

  return originalImages;
}

// Writer helpers
// const Data
template<typename WriterType, typename DataType>
void writeData(const typename DataType::ConstPointer data, const string& fileName)
{
  typename WriterType::Pointer writer = WriterType::New();

	writer->SetInput( data );
  // writer->AddTransform( anotherTransform ); // only applies to writing transforms

  writer->SetFileName( fileName.c_str() );

  try {
  	writer->Update();
  }
	catch( itk::ExceptionObject & err ) {
    cerr << "ExceptionObject caught while writing." << endl;
    cerr << err << endl;
		exit(EXIT_FAILURE);
	}
}

// Data
template<typename WriterType, typename DataType>
void writeData(const typename DataType::Pointer data, const string& fileName)
{
  writeData< WriterType, DataType >( (typename DataType::ConstPointer) data, fileName);
}

// Const Image
template<typename ImageType>
void writeImage(const typename ImageType::ConstPointer image, const string& fileName)
{
  writeData< itk::ImageFileWriter< ImageType >, ImageType >( image, fileName );
}

// Image
template<typename ImageType>
void writeImage(const typename ImageType::Pointer image, const string& fileName)
{
  writeData< itk::ImageFileWriter< ImageType >, ImageType >( image, fileName );
}

// Transform
void writeTransform(const itk::TransformBase *transform, const string& fileName)
{
  itk::TransformBase::ConstPointer transformConstPointer(transform);
  writeData< itk::TransformFileWriter, itk::TransformBase >( transformConstPointer, fileName );
}

bool fileExists(const string& strFilename)
{
  struct stat stFileInfo;
  bool blnReturn;
  int intStat;

  // Attempt to get the file attributes
  intStat = stat(strFilename.c_str(),&stFileInfo);
  if(intStat == 0) {
    // We were able to get the file attributes
    // so the file obviously exists.
    blnReturn = true;
  } else {
    blnReturn = false;
  }

  return(blnReturn);
}

#endif
<commit_msg>Moved fileExists.<commit_after>#ifndef IO_HELPERS_HPP_
#define IO_HELPERS_HPP_

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkTransformFileReader.h"
#include "itkTransformFileWriter.h"

#include "PathHelpers.hpp"

using namespace std;

bool fileExists(const string& strFilename)
{
  struct stat stFileInfo;
  bool blnReturn;
  int intStat;

  // Attempt to get the file attributes
  intStat = stat(strFilename.c_str(),&stFileInfo);
  if(intStat == 0) {
    // We were able to get the file attributes
    // so the file obviously exists.
    blnReturn = true;
  } else {
    blnReturn = false;
  }

  return(blnReturn);
}

// Reader helpers
itk::TransformBase::Pointer readTransform(const string& fileName)
{
  typedef itk::TransformFileReader ReaderType;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( fileName.c_str() );

  try
  {
    reader->Update();
  }
  catch( itk::ExceptionObject & err )
  {
    std::cerr << "ExceptionObject caught while reading transform." << std::endl;
    cerr << err << endl;
		exit(EXIT_FAILURE);
  }

  return *(reader->GetTransformList()->begin());
}

template<typename ImageType>
typename ImageType::Pointer readImage(const string& fileName)
{
  typedef itk::ImageFileReader< ImageType > ReaderType;
  typename ReaderType::Pointer reader = ReaderType::New();

  reader->SetFileName( fileName.c_str() );

  try {
  	reader->Update();
  }
	catch( itk::ExceptionObject & err ) {
    cerr << "ExceptionObject caught while reading image." << endl;
    cerr << err << endl;
		exit(EXIT_FAILURE);
	}

  return reader->GetOutput();
}

template <typename ImageType>
vector< typename ImageType::Pointer > readImages(vector< string > fileNames)
{
  vector< typename ImageType::Pointer > originalImages;

	for(unsigned int i=0; i<fileNames.size(); i++)
	{
	  if( fileExists(fileNames[i]) )
	  {
      originalImages.push_back( readImage< ImageType >(fileNames[i]) );
	  }
	  else
	  {
	    // create a new image of zero size
      originalImages.push_back( ImageType::New() );
	  }
	}

  return originalImages;
}

// Writer helpers
// const Data
template<typename WriterType, typename DataType>
void writeData(const typename DataType::ConstPointer data, const string& fileName)
{
  typename WriterType::Pointer writer = WriterType::New();

	writer->SetInput( data );
  // writer->AddTransform( anotherTransform ); // only applies to writing transforms

  writer->SetFileName( fileName.c_str() );

  try {
  	writer->Update();
  }
	catch( itk::ExceptionObject & err ) {
    cerr << "ExceptionObject caught while writing." << endl;
    cerr << err << endl;
		exit(EXIT_FAILURE);
	}
}

// Data
template<typename WriterType, typename DataType>
void writeData(const typename DataType::Pointer data, const string& fileName)
{
  writeData< WriterType, DataType >( (typename DataType::ConstPointer) data, fileName);
}

// Const Image
template<typename ImageType>
void writeImage(const typename ImageType::ConstPointer image, const string& fileName)
{
  writeData< itk::ImageFileWriter< ImageType >, ImageType >( image, fileName );
}

// Image
template<typename ImageType>
void writeImage(const typename ImageType::Pointer image, const string& fileName)
{
  writeData< itk::ImageFileWriter< ImageType >, ImageType >( image, fileName );
}

// Transform
void writeTransform(const itk::TransformBase *transform, const string& fileName)
{
  itk::TransformBase::ConstPointer transformConstPointer(transform);
  writeData< itk::TransformFileWriter, itk::TransformBase >( transformConstPointer, fileName );
}

#endif
<|endoftext|>


<commit_before>/*
  Copyright 2008 Google Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "js_native_wrapper.h"
#include "converter.h"
#include "js_function_slot.h"
#include "js_script_context.h"

namespace ggadget {
namespace smjs {

// This JSClass is used to create the reference tracker JSObjects.
JSClass JSNativeWrapper::js_reference_tracker_class_ = {
  "JSReferenceTracker",
  // Use the private slot to store the wrapper.
  JSCLASS_HAS_PRIVATE,
  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, FinalizeTracker,
  JSCLASS_NO_OPTIONAL_MEMBERS
};

static const char *kTrackerReferenceName = "[[[TrackerReference]]]";

JSNativeWrapper::JSNativeWrapper(JSContext *js_context, JSObject *js_object)
    : js_context_(js_context),
      js_object_(js_object),
      name_(PrintJSValue(js_context, OBJECT_TO_JSVAL(js_object))),
      call_self_slot_(NULL) {
  // Wrap this object again into a JS object, and add this object as a property
  // of the original object, to make it possible to auto detach this object
  // when the original object is finalized.
  JSObject *js_reference_tracker = JS_NewObject(js_context,
                                                &js_reference_tracker_class_,
                                                NULL, NULL);
  JS_DefineProperty(js_context, js_object, kTrackerReferenceName,
                    OBJECT_TO_JSVAL(js_reference_tracker),
                    NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT);
  JS_SetPrivate(js_context, js_reference_tracker, this);
  // Count the current JavaScript reference.
  Ref();
  ASSERT(GetRefCount() == 1);

  if (JS_TypeOfValue(js_context, OBJECT_TO_JSVAL(js_object)) ==
          JSTYPE_FUNCTION) {
    // This object can be called as a function.
    call_self_slot_ = new JSFunctionSlot(NULL, js_context, NULL, js_object);
  }
}

JSNativeWrapper::~JSNativeWrapper() {
  delete call_self_slot_;
  if (CheckContext())
    JSScriptContext::FinalizeJSNativeWrapper(js_context_, this);
}

bool JSNativeWrapper::CheckContext() const {
  if (!js_context_) {
    LOG("The context of a native wrapped JS object has already been "
        "destroyed.");
    return false;
  }
  return true;
}

void JSNativeWrapper::Ref() const {
  ScriptableHelperDefault::Ref();
  if (CheckContext() && GetRefCount() == 2) {
    // There must be a new native reference, let JavaScript know it by adding
    // the object to root.
    JS_AddNamedRootRT(JS_GetRuntime(js_context_),
                      const_cast<JSObject **>(&js_object_), name_.c_str());
  }
}

void JSNativeWrapper::Unref(bool transient) const {
  if (CheckContext() && GetRefCount() == 2) {
    // The last native reference is about to be released, let JavaScript know
    // it by removing the root reference.
    JS_RemoveRootRT(JS_GetRuntime(js_context_),
                    const_cast<JSObject **>(&js_object_));
  }
  ScriptableHelperDefault::Unref(transient);
}

ScriptableInterface::PropertyType JSNativeWrapper::GetPropertyInfo(
    const char *name, Variant *prototype) {
  if (!*name && call_self_slot_) {
    *prototype = Variant(&call_self_slot_);
    return ScriptableInterface::PROPERTY_METHOD;
  }
  return ScriptableInterface::PROPERTY_DYNAMIC;
}

bool JSNativeWrapper::EnumerateProperties(
    EnumeratePropertiesCallback *callback) {
  ASSERT(callback);
  if (!CheckContext()) {
    delete callback;
    return false;
  }
  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  bool result = true;
  JSIdArray *id_array = JS_Enumerate(js_context_, js_object_);
  if (id_array) {
    for (int i = 0; i < id_array->length; i++) {
      jsid id = id_array->vector[i];
      jsval key = JSVAL_VOID;
      JS_IdToValue(js_context_, id, &key);
      if (JSVAL_IS_STRING(key)) {
        char *name = JS_GetStringBytes(JSVAL_TO_STRING(key));
        if (name &&
            !(*callback)(name, ScriptableInterface::PROPERTY_DYNAMIC,
                         GetProperty(name).v())) {
          result = false;
          break;
        }
      }
      // Otherwise, ignore the property.
    }
  }
  JS_DestroyIdArray(js_context_, id_array);
  delete callback;
  return result;
}

bool JSNativeWrapper::EnumerateElements(EnumerateElementsCallback *callback) {
  ASSERT(callback);
  if (!CheckContext()) {
    delete callback;
    return false;
  }
  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  bool result = true;
  JSIdArray *id_array = JS_Enumerate(js_context_, js_object_);
  if (id_array) {
    for (int i = 0; i < id_array->length; i++) {
      jsid id = id_array->vector[i];
      jsval key = JSVAL_VOID;
      JS_IdToValue(js_context_, id, &key);
      if (JSVAL_IS_INT(key)) {
        int index = JSVAL_TO_INT(key);
        if (!(*callback)(index, GetPropertyByIndex(index).v())) {
          result = false;
          break;
        }
      }
      // Otherwise, ignore the property.
    }
  }
  JS_DestroyIdArray(js_context_, id_array);
  delete callback;
  return result;
}

ResultVariant JSNativeWrapper::GetProperty(const char *name) {
  Variant result;
  if (!CheckContext())
    return ResultVariant(result);

  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  if (!*name && call_self_slot_) {
    // Get the default method used to call this object as a function.
    return ResultVariant(Variant(call_self_slot_));
  }

  UTF16String utf16;
  ConvertStringUTF8ToUTF16(name, strlen(name), &utf16);
  jsval rval;
  if (JS_GetUCProperty(js_context_, js_object_, utf16.c_str(), utf16.size(),
                       &rval) &&
      !ConvertJSToNativeVariant(js_context_, rval, &result)) {
    RaiseException(js_context_,
                   "Failed to convert JS property %s value(%s) to native.",
                   name, PrintJSValue(js_context_, rval).c_str());
  }
  return ResultVariant(result);
}

bool JSNativeWrapper::SetProperty(const char *name, const Variant &value) {
  if (!CheckContext())
    return false;

  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  jsval js_val;
  if (!ConvertNativeToJS(js_context_, value, &js_val)) {
    RaiseException(js_context_,
                   "Failed to convert native property %s value(%s) to jsval.",
                   name, value.Print().c_str());
    return false;
  }
  UTF16String utf16;
  ConvertStringUTF8ToUTF16(name, strlen(name), &utf16);
  return JS_SetUCProperty(js_context_, js_object_, utf16.c_str(), utf16.size(),
                          &js_val);
}

ResultVariant JSNativeWrapper::GetPropertyByIndex(int index) {
  Variant result;
  if (!CheckContext())
    return ResultVariant(result);

  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  jsval rval;
  if (JS_GetElement(js_context_, js_object_, index, &rval) &&
      !ConvertJSToNativeVariant(js_context_, rval, &result)) {
    RaiseException(js_context_,
                   "Failed to convert JS property %d value(%s) to native.",
                   index, PrintJSValue(js_context_, rval).c_str());
  }
  return ResultVariant(result);
}

bool JSNativeWrapper::SetPropertyByIndex(int index, const Variant &value) {
  if (!CheckContext())
    return false;

  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  jsval js_val;
  if (!ConvertNativeToJS(js_context_, value, &js_val)) {
    JS_ReportError(js_context_,
                   "Failed to convert native property %d value(%s) to jsval.",
                   index, value.Print().c_str());
    return false;
  }
  return JS_SetElement(js_context_, js_object_, index, &js_val);
}

void JSNativeWrapper::FinalizeTracker(JSContext *cx, JSObject *obj) {
  if (obj) {
    JSClass *cls = JS_GET_CLASS(cx, obj);
    if (cls && cls->finalize == js_reference_tracker_class_.finalize) {
      JSNativeWrapper *wrapper =
          reinterpret_cast<JSNativeWrapper *>(JS_GetPrivate(cx, obj));
      if (wrapper)
        wrapper->Unref();
    }
  }
}

void JSNativeWrapper::OnContextDestroy() {
  JS_RemoveRootRT(JS_GetRuntime(js_context_),
                  const_cast<JSObject **>(&js_object_));
  delete call_self_slot_;
  call_self_slot_ = NULL;
  js_context_ = NULL;
}

} // namespace smjs
} // namespace ggadget
<commit_msg> r1237@wangxianzhu:  wangxianzhu | 2009-03-13 12:40:52 +0800  Fixed a bug in JSNativeWrapper which causes loss of slot prototype.<commit_after>/*
  Copyright 2008 Google Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "js_native_wrapper.h"
#include "converter.h"
#include "js_function_slot.h"
#include "js_script_context.h"

namespace ggadget {
namespace smjs {

// This JSClass is used to create the reference tracker JSObjects.
JSClass JSNativeWrapper::js_reference_tracker_class_ = {
  "JSReferenceTracker",
  // Use the private slot to store the wrapper.
  JSCLASS_HAS_PRIVATE,
  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, FinalizeTracker,
  JSCLASS_NO_OPTIONAL_MEMBERS
};

static const char *kTrackerReferenceName = "[[[TrackerReference]]]";

JSNativeWrapper::JSNativeWrapper(JSContext *js_context, JSObject *js_object)
    : js_context_(js_context),
      js_object_(js_object),
      name_(PrintJSValue(js_context, OBJECT_TO_JSVAL(js_object))),
      call_self_slot_(NULL) {
  // Wrap this object again into a JS object, and add this object as a property
  // of the original object, to make it possible to auto detach this object
  // when the original object is finalized.
  JSObject *js_reference_tracker = JS_NewObject(js_context,
                                                &js_reference_tracker_class_,
                                                NULL, NULL);
  JS_DefineProperty(js_context, js_object, kTrackerReferenceName,
                    OBJECT_TO_JSVAL(js_reference_tracker),
                    NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT);
  JS_SetPrivate(js_context, js_reference_tracker, this);
  // Count the current JavaScript reference.
  Ref();
  ASSERT(GetRefCount() == 1);

  if (JS_TypeOfValue(js_context, OBJECT_TO_JSVAL(js_object)) ==
          JSTYPE_FUNCTION) {
    // This object can be called as a function.
    call_self_slot_ = new JSFunctionSlot(NULL, js_context, NULL, js_object);
  }
}

JSNativeWrapper::~JSNativeWrapper() {
  delete call_self_slot_;
  if (CheckContext())
    JSScriptContext::FinalizeJSNativeWrapper(js_context_, this);
}

bool JSNativeWrapper::CheckContext() const {
  if (!js_context_) {
    LOG("The context of a native wrapped JS object has already been "
        "destroyed.");
    return false;
  }
  return true;
}

void JSNativeWrapper::Ref() const {
  ScriptableHelperDefault::Ref();
  if (CheckContext() && GetRefCount() == 2) {
    // There must be a new native reference, let JavaScript know it by adding
    // the object to root.
    JS_AddNamedRootRT(JS_GetRuntime(js_context_),
                      const_cast<JSObject **>(&js_object_), name_.c_str());
  }
}

void JSNativeWrapper::Unref(bool transient) const {
  if (CheckContext() && GetRefCount() == 2) {
    // The last native reference is about to be released, let JavaScript know
    // it by removing the root reference.
    JS_RemoveRootRT(JS_GetRuntime(js_context_),
                    const_cast<JSObject **>(&js_object_));
  }
  ScriptableHelperDefault::Unref(transient);
}

ScriptableInterface::PropertyType JSNativeWrapper::GetPropertyInfo(
    const char *name, Variant *prototype) {
  if (!*name && call_self_slot_) {
    *prototype = Variant(call_self_slot_);
    return ScriptableInterface::PROPERTY_METHOD;
  }
  return ScriptableInterface::PROPERTY_DYNAMIC;
}

bool JSNativeWrapper::EnumerateProperties(
    EnumeratePropertiesCallback *callback) {
  ASSERT(callback);
  if (!CheckContext()) {
    delete callback;
    return false;
  }
  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  bool result = true;
  JSIdArray *id_array = JS_Enumerate(js_context_, js_object_);
  if (id_array) {
    for (int i = 0; i < id_array->length; i++) {
      jsid id = id_array->vector[i];
      jsval key = JSVAL_VOID;
      JS_IdToValue(js_context_, id, &key);
      if (JSVAL_IS_STRING(key)) {
        char *name = JS_GetStringBytes(JSVAL_TO_STRING(key));
        if (name &&
            !(*callback)(name, ScriptableInterface::PROPERTY_DYNAMIC,
                         GetProperty(name).v())) {
          result = false;
          break;
        }
      }
      // Otherwise, ignore the property.
    }
  }
  JS_DestroyIdArray(js_context_, id_array);
  delete callback;
  return result;
}

bool JSNativeWrapper::EnumerateElements(EnumerateElementsCallback *callback) {
  ASSERT(callback);
  if (!CheckContext()) {
    delete callback;
    return false;
  }
  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  bool result = true;
  JSIdArray *id_array = JS_Enumerate(js_context_, js_object_);
  if (id_array) {
    for (int i = 0; i < id_array->length; i++) {
      jsid id = id_array->vector[i];
      jsval key = JSVAL_VOID;
      JS_IdToValue(js_context_, id, &key);
      if (JSVAL_IS_INT(key)) {
        int index = JSVAL_TO_INT(key);
        if (!(*callback)(index, GetPropertyByIndex(index).v())) {
          result = false;
          break;
        }
      }
      // Otherwise, ignore the property.
    }
  }
  JS_DestroyIdArray(js_context_, id_array);
  delete callback;
  return result;
}

ResultVariant JSNativeWrapper::GetProperty(const char *name) {
  Variant result;
  if (!CheckContext())
    return ResultVariant(result);

  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  if (!*name && call_self_slot_) {
    // Get the default method used to call this object as a function.
    return ResultVariant(Variant(call_self_slot_));
  }

  UTF16String utf16;
  ConvertStringUTF8ToUTF16(name, strlen(name), &utf16);
  jsval rval;
  if (JS_GetUCProperty(js_context_, js_object_, utf16.c_str(), utf16.size(),
                       &rval) &&
      !ConvertJSToNativeVariant(js_context_, rval, &result)) {
    RaiseException(js_context_,
                   "Failed to convert JS property %s value(%s) to native.",
                   name, PrintJSValue(js_context_, rval).c_str());
  }
  return ResultVariant(result);
}

bool JSNativeWrapper::SetProperty(const char *name, const Variant &value) {
  if (!CheckContext())
    return false;

  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  jsval js_val;
  if (!ConvertNativeToJS(js_context_, value, &js_val)) {
    RaiseException(js_context_,
                   "Failed to convert native property %s value(%s) to jsval.",
                   name, value.Print().c_str());
    return false;
  }
  UTF16String utf16;
  ConvertStringUTF8ToUTF16(name, strlen(name), &utf16);
  return JS_SetUCProperty(js_context_, js_object_, utf16.c_str(), utf16.size(),
                          &js_val);
}

ResultVariant JSNativeWrapper::GetPropertyByIndex(int index) {
  Variant result;
  if (!CheckContext())
    return ResultVariant(result);

  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  jsval rval;
  if (JS_GetElement(js_context_, js_object_, index, &rval) &&
      !ConvertJSToNativeVariant(js_context_, rval, &result)) {
    RaiseException(js_context_,
                   "Failed to convert JS property %d value(%s) to native.",
                   index, PrintJSValue(js_context_, rval).c_str());
  }
  return ResultVariant(result);
}

bool JSNativeWrapper::SetPropertyByIndex(int index, const Variant &value) {
  if (!CheckContext())
    return false;

  ScopedLogContext log_context(GetJSScriptContext(js_context_));
  jsval js_val;
  if (!ConvertNativeToJS(js_context_, value, &js_val)) {
    JS_ReportError(js_context_,
                   "Failed to convert native property %d value(%s) to jsval.",
                   index, value.Print().c_str());
    return false;
  }
  return JS_SetElement(js_context_, js_object_, index, &js_val);
}

void JSNativeWrapper::FinalizeTracker(JSContext *cx, JSObject *obj) {
  if (obj) {
    JSClass *cls = JS_GET_CLASS(cx, obj);
    if (cls && cls->finalize == js_reference_tracker_class_.finalize) {
      JSNativeWrapper *wrapper =
          reinterpret_cast<JSNativeWrapper *>(JS_GetPrivate(cx, obj));
      if (wrapper)
        wrapper->Unref();
    }
  }
}

void JSNativeWrapper::OnContextDestroy() {
  JS_RemoveRootRT(JS_GetRuntime(js_context_),
                  const_cast<JSObject **>(&js_object_));
  delete call_self_slot_;
  call_self_slot_ = NULL;
  js_context_ = NULL;
}

} // namespace smjs
} // namespace ggadget
<|endoftext|>


<commit_before>#include "SPlaying.h"

#include <SFML/System/Clock.hpp>
#include <iostream>

#include "../World/Block/Block_Database.h"
#include "../Renderer/RMaster.h"
#include "../Camera.h"
#include "../Application.h"
#include "../Display.h"

void Frame_Time_Checker::update()
{
    m_frameCount++;

    if (m_updateTimer.getElapsedTime().asSeconds() >= 0.3)
    {
        m_fps = m_frameCount / m_timer.getElapsedTime().asMilliseconds();
        if (m_fps > 0)
        {
            m_frameTime = 1.0f / m_fps;
        }
        m_fps *= 1000;
        m_frameCount = 0;
        m_updateTimer.restart();
        m_timer.restart();
    }
}

const float& Frame_Time_Checker::getFrameTime()
{
    return m_frameTime;
}

const float& Frame_Time_Checker::getFPS()
{
    return m_fps;
}

namespace State
{
    namespace
    {
        uint32_t worldSize = 64;
    }

    Playing::Playing(Application& application)
    :   Game_State  (application)
    ,   m_world     (application.getCamera(), worldSize)
    ,   m_player    (application.getCamera())
    ,   m_quady     (Block::Database::get().textures)
    ,   m_pauseMenu (GUI::Layout::Center)
    {
        application.getCamera().hookEntity(m_player);
        initHUD();
        initPause();

        m_quady.position =
        {
            (worldSize * CHUNK_SIZE) / 2,
            CHUNK_SIZE * 3,
            (worldSize * CHUNK_SIZE) / 2
        };

        m_player.position =
        {
            (worldSize * CHUNK_SIZE) / 2,
            CHUNK_SIZE * 3,
            (worldSize * CHUNK_SIZE) / 2
        };
    }

    void Playing::input(sf::Event& e)
    {

        if (m_isPaused)
        {
            m_pauseMenu.input(e);
            Display::get().setMouseCursorVisible(true);
        }
        else
        {
            Display::get().setMouseCursorVisible(false);
        }

        switch(e.type)
        {
            case sf::Event::KeyPressed:
                if (e.key.code == sf::Keyboard::Escape)
                {
                    m_isPaused = !m_isPaused;
                }
            default:
                break;
        }
    }

    void Playing::input(Camera& camera)
    {
        if (!m_isPaused)
        {
            m_player.input();
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::R))
            {
                m_player.position =
                {
                    (worldSize * CHUNK_SIZE) / 2,
                    CHUNK_SIZE * 3,
                    (worldSize * CHUNK_SIZE) / 2
                };
            }
        }
    }

    void Playing::update(Camera& camera, float dt)
    {
        static sf::Clock c;
        m_quady.position.x += sin(c.getElapsedTime().asSeconds()) * dt * 0.8;
        m_quady.position.z += cos(c.getElapsedTime().asSeconds()) * dt * 0.8;

        if (m_isPaused)
        {
            m_pauseMenu.update();
        }
        m_player.update(dt);
        m_world.checkPlayerBounds(m_player);
        m_frameTimeChecker.update();
    }

    void Playing::draw(Renderer::Master& renderer)
    {
        if (m_isPaused)
        {
            m_pauseMenu.draw(renderer);
        }
        m_world.drawWorld(renderer, m_application->getCamera());
        renderer.draw(m_quady);

        m_hud.draw(renderer);
    }

    void Playing::initHUD()
    {
        float yPos = 0;

        auto getYPosition = [&yPos]()
        {
            float val = yPos;
            yPos += 27;
            return val;
        };

        m_hud.debug.addDebugSector("Frame Time: %fms",          {0, getYPosition()},  &m_frameTimeChecker.getFrameTime());
        m_hud.debug.addDebugSector("FPS: %.0f",                 {0, getYPosition()},  &m_frameTimeChecker.getFPS());
        m_hud.debug.addDebugSector("Faces drawn: %.0f",         {0, getYPosition()},  &m_world.m_facesDrawn);
        m_hud.debug.addDebugSector("Player Position: X: %.1f",  {0, getYPosition()},  &m_player.position.x);
        m_hud.debug.addDebugSector("Player Position: Y: %.1f",  {0, getYPosition()},  &m_player.position.y);
        m_hud.debug.addDebugSector("Player Position: Z: %.1f",  {0, getYPosition()},  &m_player.position.z);
    }

    void Playing::initPause()
    {
        m_pauseMenu.addComponent(std::make_unique<GUI::Image>("Logo", sf::Vector2f{800, 100}));
        m_pauseMenu.addPadding(200);
        m_pauseMenu.addComponent(std::make_unique<GUI::Button>("Resume", [&]()
        {
            m_isPaused = false;
        }));

        m_pauseMenu.addComponent(std::make_unique<GUI::Button>("Exit", [&]()
        {
            m_application->popState();
        }));
    }

}

<commit_msg>Decrease world size.<commit_after>#include "SPlaying.h"

#include <SFML/System/Clock.hpp>
#include <iostream>

#include "../World/Block/Block_Database.h"
#include "../Renderer/RMaster.h"
#include "../Camera.h"
#include "../Application.h"
#include "../Display.h"

void Frame_Time_Checker::update()
{
    m_frameCount++;

    if (m_updateTimer.getElapsedTime().asSeconds() >= 0.3)
    {
        m_fps = m_frameCount / m_timer.getElapsedTime().asMilliseconds();
        if (m_fps > 0)
        {
            m_frameTime = 1.0f / m_fps;
        }
        m_fps *= 1000;
        m_frameCount = 0;
        m_updateTimer.restart();
        m_timer.restart();
    }
}

const float& Frame_Time_Checker::getFrameTime()
{
    return m_frameTime;
}

const float& Frame_Time_Checker::getFPS()
{
    return m_fps;
}

namespace State
{
    namespace
    {
        uint32_t worldSize = 20;
    }

    Playing::Playing(Application& application)
    :   Game_State  (application)
    ,   m_world     (application.getCamera(), worldSize)
    ,   m_player    (application.getCamera())
    ,   m_quady     (Block::Database::get().textures)
    ,   m_pauseMenu (GUI::Layout::Center)
    {
        application.getCamera().hookEntity(m_player);
        initHUD();
        initPause();

        m_quady.position =
        {
            (worldSize * CHUNK_SIZE) / 2,
            CHUNK_SIZE * 3,
            (worldSize * CHUNK_SIZE) / 2
        };

        m_player.position =
        {
            (worldSize * CHUNK_SIZE) / 2,
            CHUNK_SIZE * 3,
            (worldSize * CHUNK_SIZE) / 2
        };
    }

    void Playing::input(sf::Event& e)
    {

        if (m_isPaused)
        {
            m_pauseMenu.input(e);
            Display::get().setMouseCursorVisible(true);
        }
        else
        {
            Display::get().setMouseCursorVisible(false);
        }

        switch(e.type)
        {
            case sf::Event::KeyPressed:
                if (e.key.code == sf::Keyboard::Escape)
                {
                    m_isPaused = !m_isPaused;
                }
            default:
                break;
        }
    }

    void Playing::input(Camera& camera)
    {
        if (!m_isPaused)
        {
            m_player.input();
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::R))
            {
                m_player.position =
                {
                    (worldSize * CHUNK_SIZE) / 2,
                    CHUNK_SIZE * 3,
                    (worldSize * CHUNK_SIZE) / 2
                };
            }
        }
    }

    void Playing::update(Camera& camera, float dt)
    {
        static sf::Clock c;
        m_quady.position.x += sin(c.getElapsedTime().asSeconds()) * dt * 0.8;
        m_quady.position.z += cos(c.getElapsedTime().asSeconds()) * dt * 0.8;

        if (m_isPaused)
        {
            m_pauseMenu.update();
        }
        m_player.update(dt);
        m_world.checkPlayerBounds(m_player);
        m_frameTimeChecker.update();
    }

    void Playing::draw(Renderer::Master& renderer)
    {
        if (m_isPaused)
        {
            m_pauseMenu.draw(renderer);
        }
        m_world.drawWorld(renderer, m_application->getCamera());
        renderer.draw(m_quady);

        m_hud.draw(renderer);
    }

    void Playing::initHUD()
    {
        float yPos = 0;

        auto getYPosition = [&yPos]()
        {
            float val = yPos;
            yPos += 27;
            return val;
        };

        m_hud.debug.addDebugSector("Frame Time: %fms",          {0, getYPosition()},  &m_frameTimeChecker.getFrameTime());
        m_hud.debug.addDebugSector("FPS: %.0f",                 {0, getYPosition()},  &m_frameTimeChecker.getFPS());
        m_hud.debug.addDebugSector("Faces drawn: %.0f",         {0, getYPosition()},  &m_world.m_facesDrawn);
        m_hud.debug.addDebugSector("Player Position: X: %.1f",  {0, getYPosition()},  &m_player.position.x);
        m_hud.debug.addDebugSector("Player Position: Y: %.1f",  {0, getYPosition()},  &m_player.position.y);
        m_hud.debug.addDebugSector("Player Position: Z: %.1f",  {0, getYPosition()},  &m_player.position.z);
    }

    void Playing::initPause()
    {
        m_pauseMenu.addComponent(std::make_unique<GUI::Image>("Logo", sf::Vector2f{800, 100}));
        m_pauseMenu.addPadding(200);
        m_pauseMenu.addComponent(std::make_unique<GUI::Button>("Resume", [&]()
        {
            m_isPaused = false;
        }));

        m_pauseMenu.addComponent(std::make_unique<GUI::Button>("Exit", [&]()
        {
            m_application->popState();
        }));
    }

}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef DEBUG_STOP_WATCH_H
#define DEBUG_STOP_WATCH_H

#include <string>
#include <iostream>

#include "StopWatch.hpp"

namespace eddic {

/*!
 * \class DebugStopWatch
 * \brief Simple stopwatch to keep track of elapsed time between instantiation and destruction.
 *
 * If debug template argument is set to false, this class transforms to a no-op.
 *
 * \see StopWatch
 */
template<bool Enabled>
class DebugStopWatch {
    private:
        StopWatch timer;
        std::string name;

    public:
        DebugStopWatch(const std::string& n) : name(n) {}

        ~DebugStopWatch(){
            std::cout << name << " took " << timer.elapsed() << "ms" << std::endl;
        }
};

template<>
struct DebugStopWatch<false> {
    DebugStopWatch(const std::string&) {}
};

} //end of eddic

#endif
<commit_msg>Remove unused class<commit_after><|endoftext|>


<commit_before>#include <iostream>

#include "demo/demo.h"

int main()
{
    // run demo
    demo::Demo demo;
    demo.startup();
    demo.run();
    demo.shutdown();

    return 0;
}<commit_msg>Clean up main.<commit_after>#include "demo/demo.h"

int main()
{
    // run demo
    demo::Demo demo;
    demo.startup();
    demo.run();
    demo.shutdown();

    return 0;
}<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * adiosMpiHandshake.cpp
 *
 *  Created on: Mar 1, 2020
 *      Author: Jason Wang
 */

#include "adiosMpiHandshake.h"
#include <chrono>
#include <cstdio>
#include <fstream>
#include <thread>
#include <unordered_set>
#include <vector>

namespace adios2
{
namespace helper
{

const std::vector<std::vector<int>> Handshake(const std::string &filename,
                                              const char mode,
                                              const int timeoutSeconds,
                                              MPI_Comm localComm)
{
    std::vector<std::vector<int>> ret(3);

    int localRank;
    int localSize;
    int worldRank;
    int worldSize;

    MPI_Comm_rank(localComm, &localRank);
    MPI_Comm_size(localComm, &localSize);

    MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);
    MPI_Comm_size(MPI_COMM_WORLD, &worldSize);

    std::vector<int> allLocalRanks(localSize);

    MPI_Gather(&worldRank, 1, MPI_INT, allLocalRanks.data(), 1, MPI_INT, 0,
               localComm);

    if (localRank == 0)
    {
        std::ofstream fs;
        fs.open(filename + "." + mode);
        for (auto rank : allLocalRanks)
        {
            fs << rank << std::endl;
        }
        fs.close();

        if (mode == 'r')
        {

            for (auto i : allLocalRanks)
            {
                ret[0].push_back(i);
                ret[2].push_back(i);
            }

            std::ofstream fsc;
            fsc.open(filename + ".r.c");
            fsc << "completed";
            fsc.close();

            while (true)
            {
                std::ifstream fs;
                try
                {
                    fs.open(filename + ".w.c");
                    std::string line;
                    std::getline(fs, line);
                    if (line != "completed")
                    {
                        continue;
                    }
                    fs.close();
                    remove((filename + ".w.c\0").c_str());
                    break;
                }
                catch (...)
                {
                    continue;
                }
            }

            std::ifstream fs;
            fs.open(filename + ".w");
            for (std::string line; std::getline(fs, line);)
            {
                ret[0].push_back(std::stoi(line));
                ret[1].push_back(std::stoi(line));
            }
            fs.close();
            remove((filename + ".w\0").c_str());
        }
        else if (mode == 'w')
        {
            for (auto i : allLocalRanks)
            {
                ret[0].push_back(i);
                ret[1].push_back(i);
            }

            std::ofstream fsc;
            fsc.open(filename + ".w.c");
            fsc << "completed";
            fsc.close();

            while (true)
            {
                std::ifstream fs;
                try
                {
                    fs.open(filename + ".r.c");
                    std::string line;
                    std::getline(fs, line);
                    if (line != "completed")
                    {
                        continue;
                    }
                    fs.close();
                    remove((filename + ".r.c\0").c_str());
                    break;
                }
                catch (...)
                {
                    continue;
                }
            }

            std::ifstream fs;
            fs.open(filename + ".r");
            for (std::string line; std::getline(fs, line);)
            {
                ret[0].push_back(std::stoi(line));
                ret[2].push_back(std::stoi(line));
            }
            fs.close();
            remove((filename + ".r\0").c_str());
        }
    }

    int dims[3];

    if (localRank == 0)
    {
        for (int i = 0; i < 3; ++i)
        {
            dims[i] = ret[i].size();
            std::sort(ret[i].begin(), ret[i].end());
        }
    }

    MPI_Bcast(dims, 3, MPI_INT, 0, localComm);

    if (localRank != 0)
    {
        for (int i = 0; i < 3; ++i)
        {
            ret[i].resize(dims[i]);
        }
    }

    for (int i = 0; i < 3; ++i)
    {
        MPI_Bcast(ret[i].data(), ret[i].size(), MPI_INT, 0, localComm);
    }

    return ret;
}

} // end namespace helper
} // end namespace adios2
<commit_msg>added algorithm.h<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * adiosMpiHandshake.cpp
 *
 *  Created on: Mar 1, 2020
 *      Author: Jason Wang
 */

#include "adiosMpiHandshake.h"
#include <algorithm>
#include <chrono>
#include <cstdio>
#include <fstream>
#include <thread>
#include <unordered_set>
#include <vector>

namespace adios2
{
namespace helper
{

const std::vector<std::vector<int>> Handshake(const std::string &filename,
                                              const char mode,
                                              const int timeoutSeconds,
                                              MPI_Comm localComm)
{
    std::vector<std::vector<int>> ret(3);

    int localRank;
    int localSize;
    int worldRank;
    int worldSize;

    MPI_Comm_rank(localComm, &localRank);
    MPI_Comm_size(localComm, &localSize);

    MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);
    MPI_Comm_size(MPI_COMM_WORLD, &worldSize);

    std::vector<int> allLocalRanks(localSize);

    MPI_Gather(&worldRank, 1, MPI_INT, allLocalRanks.data(), 1, MPI_INT, 0,
               localComm);

    if (localRank == 0)
    {
        std::ofstream fs;
        fs.open(filename + "." + mode);
        for (auto rank : allLocalRanks)
        {
            fs << rank << std::endl;
        }
        fs.close();

        if (mode == 'r')
        {

            for (auto i : allLocalRanks)
            {
                ret[0].push_back(i);
                ret[2].push_back(i);
            }

            std::ofstream fsc;
            fsc.open(filename + ".r.c");
            fsc << "completed";
            fsc.close();

            while (true)
            {
                std::ifstream fs;
                try
                {
                    fs.open(filename + ".w.c");
                    std::string line;
                    std::getline(fs, line);
                    if (line != "completed")
                    {
                        continue;
                    }
                    fs.close();
                    remove((filename + ".w.c\0").c_str());
                    break;
                }
                catch (...)
                {
                    continue;
                }
            }

            std::ifstream fs;
            fs.open(filename + ".w");
            for (std::string line; std::getline(fs, line);)
            {
                ret[0].push_back(std::stoi(line));
                ret[1].push_back(std::stoi(line));
            }
            fs.close();
            remove((filename + ".w\0").c_str());
        }
        else if (mode == 'w')
        {
            for (auto i : allLocalRanks)
            {
                ret[0].push_back(i);
                ret[1].push_back(i);
            }

            std::ofstream fsc;
            fsc.open(filename + ".w.c");
            fsc << "completed";
            fsc.close();

            while (true)
            {
                std::ifstream fs;
                try
                {
                    fs.open(filename + ".r.c");
                    std::string line;
                    std::getline(fs, line);
                    if (line != "completed")
                    {
                        continue;
                    }
                    fs.close();
                    remove((filename + ".r.c\0").c_str());
                    break;
                }
                catch (...)
                {
                    continue;
                }
            }

            std::ifstream fs;
            fs.open(filename + ".r");
            for (std::string line; std::getline(fs, line);)
            {
                ret[0].push_back(std::stoi(line));
                ret[2].push_back(std::stoi(line));
            }
            fs.close();
            remove((filename + ".r\0").c_str());
        }
    }

    int dims[3];

    if (localRank == 0)
    {
        for (int i = 0; i < 3; ++i)
        {
            dims[i] = ret[i].size();
            std::sort(ret[i].begin(), ret[i].end());
        }
    }

    MPI_Bcast(dims, 3, MPI_INT, 0, localComm);

    if (localRank != 0)
    {
        for (int i = 0; i < 3; ++i)
        {
            ret[i].resize(dims[i]);
        }
    }

    for (int i = 0; i < 3; ++i)
    {
        MPI_Bcast(ret[i].data(), ret[i].size(), MPI_INT, 0, localComm);
    }

    return ret;
}

} // end namespace helper
} // end namespace adios2
<|endoftext|>


<commit_before>// Each task is composed of a computing unit, which performs the desired
// computation, and the arguments provided by the user. This file defines how
// the computing units are created.
//
// Each computing unit is identified by an id that should be unique, so that
// the class used to compute can be identified. Currently the id is given by the
// name provided by to the constructor. The class BaseComputingUnit is used only
// to provide abstract pointers to units and thus should NEVER be used directly.
//
// To create a new computing unit, inherit from ComputingUnit<T> like this:
// class MyUnit: public ComputingUnit<MyUnit>
// and provide the following inside the class:
// 1) the constructor should call ComputingUnit<MyUnit> with the desired unit's
// name as argument;
// 1) a method operator() that performs the computation desired.
//
// Caveats:
// 1) Only the return of operator() is considered as the result, so any changes
// to the argument are ignored;
// 2) All arguments and the return of operator() must be serializable through
// boost;
// 3) operator() must be declared as const, to ensure no modifications are
// performed.
//
// Besides these requirements, the user has control over the following options:
// 1) whether the object must run on the master node, chosen through the method
// "run_locally()". This should be used in case there is some restriction, like
// file requirements or the operator() method is so fast that the communication
// overhead isn't worth. The node is allowed to run anywhere by default;
// 2) whether the result should be saved to disk, through the method
// "should_save()". For very simple units, it may not be necessary or even
// desidered to save the result of the computation. The default is to save.
//
// For an example of how to implement an unit, check the IdentityComputingUnit
// below.

#ifndef __TASK_DISTRIBUTION__COMPUTING_UNIT_HPP__
#define __TASK_DISTRIBUTION__COMPUTING_UNIT_HPP__

#include "object_archive.hpp"

#include <tuple>
#include <type_traits>
#include <unordered_map>

#include "compile_utils.hpp"
#include "computing_unit_manager.hpp"
#include "key.hpp"
#include "task_entry.hpp"

namespace TaskDistribution {
  // Abstract class to allow us to have pointers to units. Shouldn't be used
  // directly!
  class BaseComputingUnit {
    public:
      // Must the object be called on the master node? Defaults to false.
      virtual bool run_locally() const {
        return false;
      }

      // Should the computing results be saved? Defaults to true.
      virtual bool should_save() const {
        return true;
      }

      // Static method to fetch the correct kind of unit for an id. Returns NULL
      // if not found.
      static BaseComputingUnit const* get_by_id(std::string const& id);

      // Static method to fetch the correct kind of unit for a key. Returns NULL
      // if not found.
      static BaseComputingUnit const* get_by_key(Key const& key);

      // Binds a given id with a key. Multiple keys may be bound to the same id.
      // Returns true if the id was found.
      static bool bind_key(std::string const& id, Key const& key);

      // Gets the id associated with this kind of unit.
      std::string const& get_id() const {
        return *id_;
      }

      // Provides an invalid unit id.
      static std::string get_invalid_id() {
        return "";
      }

      // Callables need to be serializable. The default behavior is to transmit
      // nothing and may be overloaded.
      template<class Archive>
      void serialize(Archive& ar, const unsigned int version) { }

      // Loads the computing unit and arguments and stores the result in the
      // archive. Assumes every Key provided is valid.
      virtual void execute(ObjectArchive<Key>& archive,
          TaskEntry const& task, ComputingUnitManager& manager) const = 0;

    protected:
      // Expands the tuple and calls the functor
      template <class F, class Tuple, size_t... S>
      static typename function_traits<F>::return_type
      apply(F&& f, Tuple&& args, seq<S...>) {
        return std::forward<F>(f)(std::get<S>(std::forward<Tuple>(args))...);
      }

      // Allows access to id_
      template <class> friend class ComputingUnit;

      std::string const* id_;

      // Map between ids and units.
      static std::unordered_map<std::string,BaseComputingUnit const*> id_map_;
      // Map between keys and units.
      static std::unordered_map<Key,BaseComputingUnit const*> key_map_;
  };

  // Class that should be inherited by the user's units. For an example on how
  // to do this, check the top of the file or the IdentityComputingUnit example.
  // Each kind of ComputingUnit used must be instantiated at least once and may
  // be destroyed before running the tasks.
  template <class T>
  class ComputingUnit: public BaseComputingUnit {
    public:
      // Registers the unit by placing a new copy into the units' map.
      explicit ComputingUnit(std::string const& name);

      virtual void execute(ObjectArchive<Key>& archive,
          TaskEntry const& task, ComputingUnitManager& manager) const;

    private:
      // Internal constructor to avoid deadlock during unit register.
      ComputingUnit() { }
  };

  // Example ComputingUnit that just returns its argument. Check that it
  // satisfies all the requirements for a valid unit.
  template <class T>
  class IdentityComputingUnit: public ComputingUnit<IdentityComputingUnit<T>> {
    public:
      IdentityComputingUnit():
        ComputingUnit<IdentityComputingUnit<T>>("identity") { }

      virtual bool run_locally() const {
        return true;
      }

      virtual bool should_save() const {
        return false;
      }

      T operator()(T const& arg) const {
        return arg;
      }
  };

  template <class From, class To>
  class ConvertComputingUnit:
    public ComputingUnit<ConvertComputingUnit<From, To>> {
    public:
      ConvertComputingUnit():
        ComputingUnit<ConvertComputingUnit<From, To>>("convert") {
        static_assert(std::is_convertible<From,To>::value,
            "Invalid ConvertComputingUnit as types aren't convertible!");
        static_assert(!std::is_same<From,To>::value,
            "Invalid ConvertComputingUnit as types are the same!");
      }

      virtual bool run_locally() const {
        return true;
      }

      virtual bool should_save() const {
        return false;
      }

      To operator()(From const& arg) const {
        return arg;
      }
  };
};

#include "computing_unit_impl.hpp"

#endif
<commit_msg>Updated documentation for computing unit.<commit_after>// Each task is composed of a computing unit, which performs the desired
// computation, and the arguments provided by the user. This file defines how
// the computing units are created.
//
// Each computing unit is identified by an id that should be unique, so that
// the class used to compute can be identified. Currently the id is given by the
// name provided by to the constructor. The class BaseComputingUnit is used only
// to provide abstract pointers to units and thus should NEVER be used directly.
//
// To create a new computing unit, inherit from ComputingUnit<T> like this:
// class MyUnit: public ComputingUnit<MyUnit>
// and provide the following inside the class:
// 1) a constructor without arguments must be provided;
// 2) the constructor must call ComputingUnit<MyUnit> with the desired unit's
// name as argument;
// 3) a const method operator() that performs the computation desired;
// 4) if the object has any internal parameters, they user must create the
// method serialize.
//
// Caveats:
// 1) Only the return of operator() is considered as the result, so any changes
// to the argument are ignored;
// 2) All arguments and the return of operator() must be serializable through
// boost;
// 3) operator() must be declared as const, to ensure no modifications are
// performed.
//
// Besides these requirements, the user has control over the following options:
// 1) whether the object must run on the master node, chosen through the method
// "run_locally()". This should be used in case there is some restriction, like
// file requirements or the operator() method is so fast that the communication
// overhead isn't worth. The node is allowed to run anywhere by default;
// 2) whether the result should be saved to disk, through the method
// "should_save()". For very simple units, it may not be necessary or even
// desidered to save the result of the computation. The default is to save.
//
// For an example of how to implement an unit, check the IdentityComputingUnit
// below.

#ifndef __TASK_DISTRIBUTION__COMPUTING_UNIT_HPP__
#define __TASK_DISTRIBUTION__COMPUTING_UNIT_HPP__

#include "object_archive.hpp"

#include <tuple>
#include <type_traits>
#include <unordered_map>

#include "compile_utils.hpp"
#include "computing_unit_manager.hpp"
#include "key.hpp"
#include "task_entry.hpp"

namespace TaskDistribution {
  // Abstract class to allow us to have pointers to units. Shouldn't be used
  // directly!
  class BaseComputingUnit {
    public:
      // Must the object be called on the master node? Defaults to false.
      virtual bool run_locally() const {
        return false;
      }

      // Should the computing results be saved? Defaults to true.
      virtual bool should_save() const {
        return true;
      }

      // Static method to fetch the correct kind of unit for an id. Returns NULL
      // if not found.
      static BaseComputingUnit const* get_by_id(std::string const& id);

      // Static method to fetch the correct kind of unit for a key. Returns NULL
      // if not found.
      static BaseComputingUnit const* get_by_key(Key const& key);

      // Binds a given id with a key. Multiple keys may be bound to the same id.
      // Returns true if the id was found.
      static bool bind_key(std::string const& id, Key const& key);

      // Gets the id associated with this kind of unit.
      std::string const& get_id() const {
        return *id_;
      }

      // Provides an invalid unit id.
      static std::string get_invalid_id() {
        return "";
      }

      // Callables need to be serializable. The default behavior is to transmit
      // nothing and may be overloaded.
      template<class Archive>
      void serialize(Archive& ar, const unsigned int version) { }

      // Loads the computing unit and arguments and stores the result in the
      // archive. Assumes every Key provided is valid.
      virtual void execute(ObjectArchive<Key>& archive,
          TaskEntry const& task, ComputingUnitManager& manager) const = 0;

    protected:
      // Expands the tuple and calls the functor
      template <class F, class Tuple, size_t... S>
      static typename function_traits<F>::return_type
      apply(F&& f, Tuple&& args, seq<S...>) {
        return std::forward<F>(f)(std::get<S>(std::forward<Tuple>(args))...);
      }

      // Name of the computing unit given at construction
      std::string const* id_;

      // Map between ids and units.
      static std::unordered_map<std::string,BaseComputingUnit const*> id_map_;
      // Map between keys and units.
      static std::unordered_map<Key,BaseComputingUnit const*> key_map_;
  };

  // Class that should be inherited by the user's units. For an example on how
  // to do this, check the top of the file or the IdentityComputingUnit example.
  // Each kind of ComputingUnit used must be instantiated at least once and may
  // be destroyed before running the tasks.
  template <class T>
  class ComputingUnit: public BaseComputingUnit {
    public:
      // Registers the unit by placing a new copy into the units' map.
      explicit ComputingUnit(std::string const& name);

      virtual void execute(ObjectArchive<Key>& archive,
          TaskEntry const& task, ComputingUnitManager& manager) const;

    private:
      // Internal constructor to avoid deadlock during unit register.
      ComputingUnit() { }
  };

  // Example ComputingUnit that just returns its argument. Check that it
  // satisfies all the requirements for a valid unit.
  template <class T>
  class IdentityComputingUnit: public ComputingUnit<IdentityComputingUnit<T>> {
    public:
      IdentityComputingUnit():
        ComputingUnit<IdentityComputingUnit<T>>("identity") { }

      virtual bool run_locally() const {
        return true;
      }

      virtual bool should_save() const {
        return false;
      }

      T operator()(T const& arg) const {
        return arg;
      }
  };

  template <class From, class To>
  class ConvertComputingUnit:
    public ComputingUnit<ConvertComputingUnit<From, To>> {
    public:
      ConvertComputingUnit():
        ComputingUnit<ConvertComputingUnit<From, To>>("convert") {
        static_assert(std::is_convertible<From,To>::value,
            "Invalid ConvertComputingUnit as types aren't convertible!");
        static_assert(!std::is_same<From,To>::value,
            "Invalid ConvertComputingUnit as types are the same!");
      }

      virtual bool run_locally() const {
        return true;
      }

      virtual bool should_save() const {
        return false;
      }

      To operator()(From const& arg) const {
        return arg;
      }
  };
};

#include "computing_unit_impl.hpp"

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2009 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.

#include "chrome/browser/extensions/extension_file_util.h"

#include "base/file_util.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace keys = extension_manifest_keys;

TEST(ExtensionFileUtil, MoveDirSafely) {
  // Create a test directory structure with some data in it.
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  FilePath src_path = temp.path().AppendASCII("src");
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  std::string data = "foobar";
  ASSERT_TRUE(file_util::WriteFile(src_path.AppendASCII("data"),
                                   data.c_str(), data.length()));

  // Move it to a path that doesn't exist yet.
  FilePath dest_path = temp.path().AppendASCII("dest").AppendASCII("dest");
  ASSERT_TRUE(extension_file_util::MoveDirSafely(src_path, dest_path));

  // The path should get created.
  ASSERT_TRUE(file_util::DirectoryExists(dest_path));

  // The data should match.
  std::string data_out;
  ASSERT_TRUE(file_util::ReadFileToString(dest_path.AppendASCII("data"),
                                          &data_out));
  ASSERT_EQ(data, data_out);

  // The src path should be gone.
  ASSERT_FALSE(file_util::PathExists(src_path));

  // Create some new test data.
  ASSERT_TRUE(file_util::CopyDirectory(dest_path, src_path,
                                       true));  // recursive
  data = "hotdog";
  ASSERT_TRUE(file_util::WriteFile(src_path.AppendASCII("data"),
                                   data.c_str(), data.length()));

  // Test again, overwriting the old path.
  ASSERT_TRUE(extension_file_util::MoveDirSafely(src_path, dest_path));
  ASSERT_TRUE(file_util::DirectoryExists(dest_path));

  data_out.clear();
  ASSERT_TRUE(file_util::ReadFileToString(dest_path.AppendASCII("data"),
                                          &data_out));
  ASSERT_EQ(data, data_out);
  ASSERT_FALSE(file_util::PathExists(src_path));
}

TEST(ExtensionFileUtil, CompareToInstalledVersion) {
  // Compare to an existing extension.
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("good")
      .AppendASCII("Extensions");

  const std::string kId = "behllobkkfkfnphdnhnkndlbkcpglgmj";
  const std::string kCurrentVersion = "1.0.0.0";

  FilePath version_dir;

  ASSERT_EQ(Extension::UPGRADE,
            extension_file_util::CompareToInstalledVersion(
                install_dir, kId, kCurrentVersion, "1.0.0.1", &version_dir));

  ASSERT_EQ(Extension::REINSTALL,
            extension_file_util::CompareToInstalledVersion(
                install_dir, kId, kCurrentVersion, "1.0.0.0", &version_dir));

  ASSERT_EQ(Extension::REINSTALL,
            extension_file_util::CompareToInstalledVersion(
                install_dir, kId, kCurrentVersion, "1.0.0", &version_dir));

  ASSERT_EQ(Extension::DOWNGRADE,
            extension_file_util::CompareToInstalledVersion(
                install_dir, kId, kCurrentVersion, "0.0.1.0", &version_dir));

  // Compare to an extension that is missing its manifest file.
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());
  FilePath src = install_dir.AppendASCII(kId).AppendASCII(kCurrentVersion);
  FilePath dest = temp.path().AppendASCII(kId).AppendASCII(kCurrentVersion);
  ASSERT_TRUE(file_util::CreateDirectory(dest.DirName()));
  ASSERT_TRUE(file_util::CopyDirectory(src, dest, true));
  ASSERT_TRUE(file_util::Delete(dest.AppendASCII("manifest.json"), false));

  ASSERT_EQ(Extension::NEW_INSTALL,
            extension_file_util::CompareToInstalledVersion(
                temp.path(), kId, kCurrentVersion, "1.0.0", &version_dir));

  // Compare to a non-existent extension.
  const std::string kMissingVersion = "";
  const std::string kBadId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  ASSERT_EQ(Extension::NEW_INSTALL,
            extension_file_util::CompareToInstalledVersion(
                temp.path(), kBadId, kMissingVersion, "1.0.0", &version_dir));
}

TEST(ExtensionFileUtil, LoadExtensionWithValidLocales) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("good")
      .AppendASCII("Extensions")
      .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
      .AppendASCII("1.0.0.0");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension != NULL);
  EXPECT_EQ("The first extension that I made.", extension->description());
}

TEST(ExtensionFileUtil, LoadExtensionWithoutLocalesFolder) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("good")
      .AppendASCII("Extensions")
      .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa")
      .AppendASCII("1.0");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_FALSE(extension == NULL);
  EXPECT_TRUE(error.empty());
}

TEST(ExtensionFileUtil, CheckIllegalFilenamesNoUnderscores) {
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  FilePath src_path = temp.path().AppendASCII("some_dir");
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  std::string data = "{ \"name\": { \"message\": \"foobar\" } }";
  ASSERT_TRUE(file_util::WriteFile(src_path.AppendASCII("some_file.txt"),
                                   data.c_str(), data.length()));
  std::string error;
  EXPECT_TRUE(extension_file_util::CheckForIllegalFilenames(temp.path(),
                                                            &error));
}

TEST(ExtensionFileUtil, CheckIllegalFilenamesOnlyReserved) {
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  FilePath src_path = temp.path().Append(Extension::kLocaleFolder);
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  std::string error;
  EXPECT_TRUE(extension_file_util::CheckForIllegalFilenames(temp.path(),
                                                            &error));
}

TEST(ExtensionFileUtil, CheckIllegalFilenamesReservedAndIllegal) {
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  FilePath src_path = temp.path().Append(Extension::kLocaleFolder);
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  src_path = temp.path().AppendASCII("_some_dir");
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  std::string error;
  EXPECT_FALSE(extension_file_util::CheckForIllegalFilenames(temp.path(),
                                                             &error));
}

TEST(ExtensionFileUtil, LoadExtensionGivesHelpfullErrorOnMissingManifest) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("bad")
      .AppendASCII("Extensions")
      .AppendASCII("dddddddddddddddddddddddddddddddd")
      .AppendASCII("1.0");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension == NULL);
  ASSERT_FALSE(error.empty());
  ASSERT_STREQ("Manifest file is missing or unreadable.", error.c_str());
}

TEST(ExtensionFileUtil, LoadExtensionGivesHelpfullErrorOnBadManifest) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("bad")
      .AppendASCII("Extensions")
      .AppendASCII("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
      .AppendASCII("1.0");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension == NULL);
  ASSERT_FALSE(error.empty());
  ASSERT_STREQ("Manifest is not valid JSON.  "
               "Line: 2, column: 16, Syntax error.", error.c_str());
}

TEST(ExtensionFileUtil, MissingPrivacyBlacklist) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("privacy_blacklists")
      .AppendASCII("missing_blacklist");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension == NULL);
  ASSERT_FALSE(error.empty());
  EXPECT_TRUE(MatchPatternASCII(error,
      "Could not load '*privacy_blacklist.pbl' for privacy blacklist: "
      "file does not exist.")) << error;
}

TEST(ExtensionFileUtil, InvalidPrivacyBlacklist) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("privacy_blacklists")
      .AppendASCII("invalid_blacklist");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension == NULL);
  ASSERT_FALSE(error.empty());
  EXPECT_TRUE(MatchPatternASCII(error,
      "Could not load '*privacy_blacklist.pbl' for privacy blacklist: "
      "Incorrect header.")) << error;
}

// TODO(aa): More tests as motivation allows. Maybe steal some from
// ExtensionsService? Many of them could probably be tested here without the
// MessageLoop shenanigans.
<commit_msg>add unit test for ExtensionURLToRelativeFilePath<commit_after>// Copyright (c) 2009 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.

#include "chrome/browser/extensions/extension_file_util.h"

#include "base/file_util.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace keys = extension_manifest_keys;

TEST(ExtensionFileUtil, MoveDirSafely) {
  // Create a test directory structure with some data in it.
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  FilePath src_path = temp.path().AppendASCII("src");
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  std::string data = "foobar";
  ASSERT_TRUE(file_util::WriteFile(src_path.AppendASCII("data"),
                                   data.c_str(), data.length()));

  // Move it to a path that doesn't exist yet.
  FilePath dest_path = temp.path().AppendASCII("dest").AppendASCII("dest");
  ASSERT_TRUE(extension_file_util::MoveDirSafely(src_path, dest_path));

  // The path should get created.
  ASSERT_TRUE(file_util::DirectoryExists(dest_path));

  // The data should match.
  std::string data_out;
  ASSERT_TRUE(file_util::ReadFileToString(dest_path.AppendASCII("data"),
                                          &data_out));
  ASSERT_EQ(data, data_out);

  // The src path should be gone.
  ASSERT_FALSE(file_util::PathExists(src_path));

  // Create some new test data.
  ASSERT_TRUE(file_util::CopyDirectory(dest_path, src_path,
                                       true));  // recursive
  data = "hotdog";
  ASSERT_TRUE(file_util::WriteFile(src_path.AppendASCII("data"),
                                   data.c_str(), data.length()));

  // Test again, overwriting the old path.
  ASSERT_TRUE(extension_file_util::MoveDirSafely(src_path, dest_path));
  ASSERT_TRUE(file_util::DirectoryExists(dest_path));

  data_out.clear();
  ASSERT_TRUE(file_util::ReadFileToString(dest_path.AppendASCII("data"),
                                          &data_out));
  ASSERT_EQ(data, data_out);
  ASSERT_FALSE(file_util::PathExists(src_path));
}

TEST(ExtensionFileUtil, CompareToInstalledVersion) {
  // Compare to an existing extension.
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("good")
      .AppendASCII("Extensions");

  const std::string kId = "behllobkkfkfnphdnhnkndlbkcpglgmj";
  const std::string kCurrentVersion = "1.0.0.0";

  FilePath version_dir;

  ASSERT_EQ(Extension::UPGRADE,
            extension_file_util::CompareToInstalledVersion(
                install_dir, kId, kCurrentVersion, "1.0.0.1", &version_dir));

  ASSERT_EQ(Extension::REINSTALL,
            extension_file_util::CompareToInstalledVersion(
                install_dir, kId, kCurrentVersion, "1.0.0.0", &version_dir));

  ASSERT_EQ(Extension::REINSTALL,
            extension_file_util::CompareToInstalledVersion(
                install_dir, kId, kCurrentVersion, "1.0.0", &version_dir));

  ASSERT_EQ(Extension::DOWNGRADE,
            extension_file_util::CompareToInstalledVersion(
                install_dir, kId, kCurrentVersion, "0.0.1.0", &version_dir));

  // Compare to an extension that is missing its manifest file.
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());
  FilePath src = install_dir.AppendASCII(kId).AppendASCII(kCurrentVersion);
  FilePath dest = temp.path().AppendASCII(kId).AppendASCII(kCurrentVersion);
  ASSERT_TRUE(file_util::CreateDirectory(dest.DirName()));
  ASSERT_TRUE(file_util::CopyDirectory(src, dest, true));
  ASSERT_TRUE(file_util::Delete(dest.AppendASCII("manifest.json"), false));

  ASSERT_EQ(Extension::NEW_INSTALL,
            extension_file_util::CompareToInstalledVersion(
                temp.path(), kId, kCurrentVersion, "1.0.0", &version_dir));

  // Compare to a non-existent extension.
  const std::string kMissingVersion = "";
  const std::string kBadId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  ASSERT_EQ(Extension::NEW_INSTALL,
            extension_file_util::CompareToInstalledVersion(
                temp.path(), kBadId, kMissingVersion, "1.0.0", &version_dir));
}

TEST(ExtensionFileUtil, LoadExtensionWithValidLocales) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("good")
      .AppendASCII("Extensions")
      .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
      .AppendASCII("1.0.0.0");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension != NULL);
  EXPECT_EQ("The first extension that I made.", extension->description());
}

TEST(ExtensionFileUtil, LoadExtensionWithoutLocalesFolder) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("good")
      .AppendASCII("Extensions")
      .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa")
      .AppendASCII("1.0");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_FALSE(extension == NULL);
  EXPECT_TRUE(error.empty());
}

TEST(ExtensionFileUtil, CheckIllegalFilenamesNoUnderscores) {
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  FilePath src_path = temp.path().AppendASCII("some_dir");
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  std::string data = "{ \"name\": { \"message\": \"foobar\" } }";
  ASSERT_TRUE(file_util::WriteFile(src_path.AppendASCII("some_file.txt"),
                                   data.c_str(), data.length()));
  std::string error;
  EXPECT_TRUE(extension_file_util::CheckForIllegalFilenames(temp.path(),
                                                            &error));
}

TEST(ExtensionFileUtil, CheckIllegalFilenamesOnlyReserved) {
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  FilePath src_path = temp.path().Append(Extension::kLocaleFolder);
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  std::string error;
  EXPECT_TRUE(extension_file_util::CheckForIllegalFilenames(temp.path(),
                                                            &error));
}

TEST(ExtensionFileUtil, CheckIllegalFilenamesReservedAndIllegal) {
  ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  FilePath src_path = temp.path().Append(Extension::kLocaleFolder);
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  src_path = temp.path().AppendASCII("_some_dir");
  ASSERT_TRUE(file_util::CreateDirectory(src_path));

  std::string error;
  EXPECT_FALSE(extension_file_util::CheckForIllegalFilenames(temp.path(),
                                                             &error));
}

TEST(ExtensionFileUtil, LoadExtensionGivesHelpfullErrorOnMissingManifest) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("bad")
      .AppendASCII("Extensions")
      .AppendASCII("dddddddddddddddddddddddddddddddd")
      .AppendASCII("1.0");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension == NULL);
  ASSERT_FALSE(error.empty());
  ASSERT_STREQ("Manifest file is missing or unreadable.", error.c_str());
}

TEST(ExtensionFileUtil, LoadExtensionGivesHelpfullErrorOnBadManifest) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("bad")
      .AppendASCII("Extensions")
      .AppendASCII("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
      .AppendASCII("1.0");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension == NULL);
  ASSERT_FALSE(error.empty());
  ASSERT_STREQ("Manifest is not valid JSON.  "
               "Line: 2, column: 16, Syntax error.", error.c_str());
}

TEST(ExtensionFileUtil, MissingPrivacyBlacklist) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("privacy_blacklists")
      .AppendASCII("missing_blacklist");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension == NULL);
  ASSERT_FALSE(error.empty());
  EXPECT_TRUE(MatchPatternASCII(error,
      "Could not load '*privacy_blacklist.pbl' for privacy blacklist: "
      "file does not exist.")) << error;
}

TEST(ExtensionFileUtil, InvalidPrivacyBlacklist) {
  FilePath install_dir;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
  install_dir = install_dir.AppendASCII("extensions")
      .AppendASCII("privacy_blacklists")
      .AppendASCII("invalid_blacklist");

  std::string error;
  scoped_ptr<Extension> extension(
      extension_file_util::LoadExtension(install_dir, false, &error));
  ASSERT_TRUE(extension == NULL);
  ASSERT_FALSE(error.empty());
  EXPECT_TRUE(MatchPatternASCII(error,
      "Could not load '*privacy_blacklist.pbl' for privacy blacklist: "
      "Incorrect header.")) << error;
}

#define URL_PREFIX "chrome-extension://extension-id/"

TEST(ExtensionFileUtil, ExtensionURLToRelativeFilePath) {
  struct TestCase {
    const char* url;
    const char* expected_relative_path;
  } test_cases[] = {
    { URL_PREFIX "simple.html",
      "simple.html" },
    { URL_PREFIX "directory/to/file.html",
      "directory/to/file.html" },
    { URL_PREFIX "escape%20spaces.html",
      "escape spaces.html" },
    { URL_PREFIX "%C3%9Cber.html",
      "\xC3\x9C" "ber.html" },
  };

  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
    GURL url(test_cases[i].url);
#if defined(OS_POSIX)
    FilePath expected_path(test_cases[i].expected_relative_path);
#elif defined(OS_WIN)
    FilePath expected_path(UTF8ToWide(test_cases[i].expected_relative_path));
#endif

    FilePath actual_path =
        extension_file_util::ExtensionURLToRelativeFilePath(url);
    EXPECT_FALSE(actual_path.IsAbsolute()) <<
      " For the path " << actual_path.value();
    EXPECT_EQ(expected_path.value(), actual_path.value());
  }
}

// TODO(aa): More tests as motivation allows. Maybe steal some from
// ExtensionsService? Many of them could probably be tested here without the
// MessageLoop shenanigans.
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), Trolltech ASA
    (or its successors, if any) and the KDE Free Qt Foundation, which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "globalconfig_p.h"

#include "factory_p.h"
#include "objectdescription.h"
#include "phonondefs_p.h"
#include "platformplugin.h"
#include "backendinterface.h"
#include "qsettingsgroup_p.h"
#include "phononnamespace_p.h"

#include <QtCore/QList>
#include <QtCore/QVariant>

QT_BEGIN_NAMESPACE

namespace Phonon
{

GlobalConfig::GlobalConfig(QObject *parent)
    : QObject(parent)
    , m_config(QLatin1String("kde.org"), QLatin1String("libphonon"))
{
}

GlobalConfig::~GlobalConfig()
{
}

enum WhatToFilter {
    FilterAdvancedDevices = 1,
    FilterHardwareDevices = 2
};

static void filter(ObjectDescriptionType type, BackendInterface *backendIface, QList<int> *list, int whatToFilter)
{
    QMutableListIterator<int> it(*list);
    while (it.hasNext()) {
        const QHash<QByteArray, QVariant> properties = backendIface->objectDescriptionProperties(type, it.next());
        QVariant var;
        if (whatToFilter & FilterAdvancedDevices) {
            var = properties.value("isAdvanced");
            if (var.isValid() && var.toBool()) {
                it.remove();
                continue;
            }
        }
        if (whatToFilter & FilterHardwareDevices) {
            var = properties.value("isHardwareDevice");
            if (var.isValid() && var.toBool()) {
                it.remove();
                continue;
            }
        }
    }
}

static QList<int> listSortedByConfig(const QSettingsGroup &backendConfig, Phonon::Category category, QList<int> &defaultList)
{
    if (defaultList.size() <= 1) {
        // nothing to sort
        return defaultList;
    } else {
        // make entries unique
        QSet<int> seen;
        QMutableListIterator<int> it(defaultList);
        while (it.hasNext()) {
            if (seen.contains(it.next())) {
                it.remove();
            } else {
                seen.insert(it.value());
            }
        }
    }

    QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category));
    if (!backendConfig.hasKey(categoryKey)) {
        // no list in config for the given category
        categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(Phonon::NoCategory));
        if (!backendConfig.hasKey(categoryKey)) {
            // no list in config for NoCategory
            return defaultList;
        }
    }

    //Now the list from m_config
    QList<int> deviceList = backendConfig.value(categoryKey, QList<int>());

    //if there are devices in m_config that the backend doesn't report, remove them from the list
    QMutableListIterator<int> i(deviceList);
    while (i.hasNext()) {
        if (0 == defaultList.removeAll(i.next())) {
            i.remove();
        }
    }

    //if the backend reports more devices that are not in m_config append them to the list
    deviceList += defaultList;

    return deviceList;
}

QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, HideAdvancedDevicesOverride override) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
    const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
    const bool hideAdvancedDevices = (override == FromSettings
            ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
            : static_cast<bool>(override));

    PlatformPlugin *platformPlugin = Factory::platformPlugin();
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());

    QList<int> defaultList;
    if (platformPlugin) {
        // the platform plugin lists the audio devices for the platform
        // this list already is in default order (as defined by the platform plugin)
        defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
        QMutableListIterator<int> it(defaultList);
        while (it.hasNext()) {
            AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next());
            const QVariant var = objDesc.property("isAdvanced");
            if (var.isValid() && var.toBool()) {
                it.remove();
            }
        }
    }

    // lookup the available devices directly from the backend (mostly for virtual devices)
    if (backendIface) {
        // this list already is in default order (as defined by the backend)
        QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
        if (hideAdvancedDevices || !defaultList.isEmpty()) {
            filter(AudioOutputDeviceType, backendIface, &list,
                    (hideAdvancedDevices ? FilterAdvancedDevices : 0)
                    // the platform plugin already provided the hardware devices
                    | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
                    );
        }
        defaultList += list;
    }

    return listSortedByConfig(backendConfig, category, defaultList);
}

int GlobalConfig::audioOutputDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioOutputDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

QList<int> GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, HideAdvancedDevicesOverride override) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
    const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
    const bool hideAdvancedDevices = (override == FromSettings
            ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
            : static_cast<bool>(override));

    PlatformPlugin *platformPlugin = Factory::platformPlugin();
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());

    QList<int> defaultList;
    if (platformPlugin) {
        // the platform plugin lists the audio devices for the platform
        // this list already is in default order (as defined by the platform plugin)
        defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
        QMutableListIterator<int> it(defaultList);
        while (it.hasNext()) {
            AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next());
            const QVariant var = objDesc.property("isAdvanced");
            if (var.isValid() && var.toBool()) {
                it.remove();
            }
        }
    }

    // lookup the available devices directly from the backend (mostly for virtual devices)
    if (backendIface) {
        // this list already is in default order (as defined by the backend)
        QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
        if (hideAdvancedDevices || !defaultList.isEmpty()) {
            filter(AudioCaptureDeviceType, backendIface, &list,
                    (hideAdvancedDevices ? FilterAdvancedDevices : 0)
                    // the platform plugin already provided the hardware devices
                    | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
                  );
        }
        defaultList += list;
    }

    return listSortedByConfig(backendConfig, category, defaultList);
}

int GlobalConfig::audioCaptureDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioCaptureDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

} // namespace Phonon

QT_END_NAMESPACE

#include "moc_globalconfig_p.cpp"

// vim: sw=4 ts=4
<commit_msg>unhide advanced devices from the platform plugin BUG: 166713<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), Trolltech ASA
    (or its successors, if any) and the KDE Free Qt Foundation, which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "globalconfig_p.h"

#include "factory_p.h"
#include "objectdescription.h"
#include "phonondefs_p.h"
#include "platformplugin.h"
#include "backendinterface.h"
#include "qsettingsgroup_p.h"
#include "phononnamespace_p.h"

#include <QtCore/QList>
#include <QtCore/QVariant>

QT_BEGIN_NAMESPACE

namespace Phonon
{

GlobalConfig::GlobalConfig(QObject *parent)
    : QObject(parent)
    , m_config(QLatin1String("kde.org"), QLatin1String("libphonon"))
{
}

GlobalConfig::~GlobalConfig()
{
}

enum WhatToFilter {
    FilterAdvancedDevices = 1,
    FilterHardwareDevices = 2
};

static void filter(ObjectDescriptionType type, BackendInterface *backendIface, QList<int> *list, int whatToFilter)
{
    QMutableListIterator<int> it(*list);
    while (it.hasNext()) {
        const QHash<QByteArray, QVariant> properties = backendIface->objectDescriptionProperties(type, it.next());
        QVariant var;
        if (whatToFilter & FilterAdvancedDevices) {
            var = properties.value("isAdvanced");
            if (var.isValid() && var.toBool()) {
                it.remove();
                continue;
            }
        }
        if (whatToFilter & FilterHardwareDevices) {
            var = properties.value("isHardwareDevice");
            if (var.isValid() && var.toBool()) {
                it.remove();
                continue;
            }
        }
    }
}

static QList<int> listSortedByConfig(const QSettingsGroup &backendConfig, Phonon::Category category, QList<int> &defaultList)
{
    if (defaultList.size() <= 1) {
        // nothing to sort
        return defaultList;
    } else {
        // make entries unique
        QSet<int> seen;
        QMutableListIterator<int> it(defaultList);
        while (it.hasNext()) {
            if (seen.contains(it.next())) {
                it.remove();
            } else {
                seen.insert(it.value());
            }
        }
    }

    QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category));
    if (!backendConfig.hasKey(categoryKey)) {
        // no list in config for the given category
        categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(Phonon::NoCategory));
        if (!backendConfig.hasKey(categoryKey)) {
            // no list in config for NoCategory
            return defaultList;
        }
    }

    //Now the list from m_config
    QList<int> deviceList = backendConfig.value(categoryKey, QList<int>());

    //if there are devices in m_config that the backend doesn't report, remove them from the list
    QMutableListIterator<int> i(deviceList);
    while (i.hasNext()) {
        if (0 == defaultList.removeAll(i.next())) {
            i.remove();
        }
    }

    //if the backend reports more devices that are not in m_config append them to the list
    deviceList += defaultList;

    return deviceList;
}

QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, HideAdvancedDevicesOverride override) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
    const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
    const bool hideAdvancedDevices = (override == FromSettings
            ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
            : static_cast<bool>(override));

    PlatformPlugin *platformPlugin = Factory::platformPlugin();
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());

    QList<int> defaultList;
    if (platformPlugin) {
        // the platform plugin lists the audio devices for the platform
        // this list already is in default order (as defined by the platform plugin)
        defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
        if (hideAdvancedDevices) {
            QMutableListIterator<int> it(defaultList);
            while (it.hasNext()) {
                AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next());
                const QVariant var = objDesc.property("isAdvanced");
                if (var.isValid() && var.toBool()) {
                    it.remove();
                }
            }
        }
    }

    // lookup the available devices directly from the backend (mostly for virtual devices)
    if (backendIface) {
        // this list already is in default order (as defined by the backend)
        QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
        if (hideAdvancedDevices || !defaultList.isEmpty()) {
            filter(AudioOutputDeviceType, backendIface, &list,
                    (hideAdvancedDevices ? FilterAdvancedDevices : 0)
                    // the platform plugin already provided the hardware devices
                    | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
                    );
        }
        defaultList += list;
    }

    return listSortedByConfig(backendConfig, category, defaultList);
}

int GlobalConfig::audioOutputDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioOutputDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

QList<int> GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, HideAdvancedDevicesOverride override) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
    const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
    const bool hideAdvancedDevices = (override == FromSettings
            ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
            : static_cast<bool>(override));

    PlatformPlugin *platformPlugin = Factory::platformPlugin();
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());

    QList<int> defaultList;
    if (platformPlugin) {
        // the platform plugin lists the audio devices for the platform
        // this list already is in default order (as defined by the platform plugin)
        defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
        if (hideAdvancedDevices) {
            QMutableListIterator<int> it(defaultList);
            while (it.hasNext()) {
                AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next());
                const QVariant var = objDesc.property("isAdvanced");
                if (var.isValid() && var.toBool()) {
                    it.remove();
                }
            }
        }
    }

    // lookup the available devices directly from the backend (mostly for virtual devices)
    if (backendIface) {
        // this list already is in default order (as defined by the backend)
        QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
        if (hideAdvancedDevices || !defaultList.isEmpty()) {
            filter(AudioCaptureDeviceType, backendIface, &list,
                    (hideAdvancedDevices ? FilterAdvancedDevices : 0)
                    // the platform plugin already provided the hardware devices
                    | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
                  );
        }
        defaultList += list;
    }

    return listSortedByConfig(backendConfig, category, defaultList);
}

int GlobalConfig::audioCaptureDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioCaptureDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

} // namespace Phonon

QT_END_NAMESPACE

#include "moc_globalconfig_p.cpp"

// vim: sw=4 ts=4
<|endoftext|>