<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/

#include "nodeinstanceserverinterface.h"
#include <qmetatype.h>

#include "propertyabstractcontainer.h"
#include "propertyvaluecontainer.h"
#include "propertybindingcontainer.h"
#include "instancecontainer.h"
#include "createinstancescommand.h"
#include "createscenecommand.h"
#include "changevaluescommand.h"
#include "changebindingscommand.h"
#include "changeauxiliarycommand.h"
#include "changefileurlcommand.h"
#include "removeinstancescommand.h"
#include "clearscenecommand.h"
#include "removepropertiescommand.h"
#include "reparentinstancescommand.h"
#include "changeidscommand.h"
#include "changestatecommand.h"
#include "completecomponentcommand.h"
#include "addimportcontainer.h"
#include "changenodesourcecommand.h"

#include "informationchangedcommand.h"
#include "pixmapchangedcommand.h"
#include "valueschangedcommand.h"
#include "childrenchangedcommand.h"
#include "imagecontainer.h"
#include "statepreviewimagechangedcommand.h"
#include "componentcompletedcommand.h"
#include "synchronizecommand.h"
#include "tokencommand.h"
#include "removesharedmemorycommand.h"

namespace QmlDesigner {

static bool isRegistered=false;

NodeInstanceServerInterface::NodeInstanceServerInterface(QObject *parent) :
    QObject(parent)
{
    registerCommands();
}

void NodeInstanceServerInterface::registerCommands()
{
    if (isRegistered)
        return;

    isRegistered = true;

    qRegisterMetaType<CreateInstancesCommand>("CreateInstancesCommand");
    qRegisterMetaTypeStreamOperators<CreateInstancesCommand>("CreateInstancesCommand");

    qRegisterMetaType<ClearSceneCommand>("ClearSceneCommand");
    qRegisterMetaTypeStreamOperators<ClearSceneCommand>("ClearSceneCommand");

    qRegisterMetaType<CreateSceneCommand>("CreateSceneCommand");
    qRegisterMetaTypeStreamOperators<CreateSceneCommand>("CreateSceneCommand");

    qRegisterMetaType<ChangeBindingsCommand>("ChangeBindingsCommand");
    qRegisterMetaTypeStreamOperators<ChangeBindingsCommand>("ChangeBindingsCommand");

    qRegisterMetaType<ChangeValuesCommand>("ChangeValuesCommand");
    qRegisterMetaTypeStreamOperators<ChangeValuesCommand>("ChangeValuesCommand");

    qRegisterMetaType<ChangeFileUrlCommand>("ChangeFileUrlCommand");
    qRegisterMetaTypeStreamOperators<ChangeFileUrlCommand>("ChangeFileUrlCommand");

    qRegisterMetaType<ChangeStateCommand>("ChangeStateCommand");
    qRegisterMetaTypeStreamOperators<PropertyAbstractContainer>("ChangeStateCommand");

    qRegisterMetaType<RemoveInstancesCommand>("RemoveInstancesCommand");
    qRegisterMetaTypeStreamOperators<RemoveInstancesCommand>("RemoveInstancesCommand");

    qRegisterMetaType<RemovePropertiesCommand>("RemovePropertiesCommand");
    qRegisterMetaTypeStreamOperators<RemovePropertiesCommand>("RemovePropertiesCommand");

    qRegisterMetaType<ReparentInstancesCommand>("ReparentInstancesCommand");
    qRegisterMetaTypeStreamOperators<ReparentInstancesCommand>("ReparentInstancesCommand");

    qRegisterMetaType<ChangeIdsCommand>("ChangeIdsCommand");
    qRegisterMetaTypeStreamOperators<ChangeIdsCommand>("ChangeIdsCommand");

    qRegisterMetaType<ChangeStateCommand>("ChangeStateCommand");
    qRegisterMetaTypeStreamOperators<ChangeStateCommand>("ChangeStateCommand");

    qRegisterMetaType<InformationChangedCommand>("InformationChangedCommand");
    qRegisterMetaTypeStreamOperators<InformationChangedCommand>("InformationChangedCommand");

    qRegisterMetaType<ValuesChangedCommand>("ValuesChangedCommand");
    qRegisterMetaTypeStreamOperators<ValuesChangedCommand>("ValuesChangedCommand");

    qRegisterMetaType<PixmapChangedCommand>("PixmapChangedCommand");
    qRegisterMetaTypeStreamOperators<PixmapChangedCommand>("PixmapChangedCommand");

    qRegisterMetaType<InformationContainer>("InformationContainer");
    qRegisterMetaTypeStreamOperators<InformationContainer>("InformationContainer");

    qRegisterMetaType<PropertyValueContainer>("PropertyValueContainer");
    qRegisterMetaTypeStreamOperators<PropertyValueContainer>("PropertyValueContainer");

    qRegisterMetaType<PropertyBindingContainer>("PropertyBindingContainer");
    qRegisterMetaTypeStreamOperators<PropertyBindingContainer>("PropertyBindingContainer");

    qRegisterMetaType<PropertyAbstractContainer>("PropertyAbstractContainer");
    qRegisterMetaTypeStreamOperators<PropertyAbstractContainer>("PropertyAbstractContainer");

    qRegisterMetaType<InstanceContainer>("InstanceContainer");
    qRegisterMetaTypeStreamOperators<InstanceContainer>("InstanceContainer");

    qRegisterMetaType<IdContainer>("IdContainer");
    qRegisterMetaTypeStreamOperators<IdContainer>("IdContainer");

    qRegisterMetaType<ChildrenChangedCommand>("ChildrenChangedCommand");
    qRegisterMetaTypeStreamOperators<ChildrenChangedCommand>("ChildrenChangedCommand");

    qRegisterMetaType<ImageContainer>("ImageContainer");
    qRegisterMetaTypeStreamOperators<ImageContainer>("ImageContainer");

    qRegisterMetaType<StatePreviewImageChangedCommand>("StatePreviewImageChangedCommand");
    qRegisterMetaTypeStreamOperators<StatePreviewImageChangedCommand>("StatePreviewImageChangedCommand");

    qRegisterMetaType<CompleteComponentCommand>("CompleteComponentCommand");
    qRegisterMetaTypeStreamOperators<CompleteComponentCommand>("CompleteComponentCommand");

    qRegisterMetaType<ComponentCompletedCommand>("ComponentCompletedCommand");
    qRegisterMetaTypeStreamOperators<ComponentCompletedCommand>("ComponentCompletedCommand");

    qRegisterMetaType<AddImportContainer>("AddImportContainer");
    qRegisterMetaTypeStreamOperators<AddImportContainer>("AddImportContainer");

    qRegisterMetaType<SynchronizeCommand>("SynchronizeCommand");
    qRegisterMetaTypeStreamOperators<SynchronizeCommand>("SynchronizeCommand");

    qRegisterMetaType<ChangeNodeSourceCommand>("ChangeNodeSourceCommand");
    qRegisterMetaTypeStreamOperators<ChangeNodeSourceCommand>("ChangeNodeSourceCommand");

    qRegisterMetaType<ChangeAuxiliaryCommand>("ChangeAuxiliaryCommand");
    qRegisterMetaTypeStreamOperators<ChangeAuxiliaryCommand>("ChangeAuxiliaryCommand");

    qRegisterMetaType<TokenCommand>("TokenCommand");
    qRegisterMetaTypeStreamOperators<TokenCommand>("TokenCommand");

    qRegisterMetaType<RemoveSharedMemoryCommand>("RemoveSharedMemoryCommand");
    qRegisterMetaTypeStreamOperators<RemoveSharedMemoryCommand>("RemoveSharedMemoryCommand");
}

}
<commit_msg>QmlDesigner.Instances: Fix type registration<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/

#include "nodeinstanceserverinterface.h"
#include <qmetatype.h>

#include "propertyabstractcontainer.h"
#include "propertyvaluecontainer.h"
#include "propertybindingcontainer.h"
#include "instancecontainer.h"
#include "createinstancescommand.h"
#include "createscenecommand.h"
#include "changevaluescommand.h"
#include "changebindingscommand.h"
#include "changeauxiliarycommand.h"
#include "changefileurlcommand.h"
#include "removeinstancescommand.h"
#include "clearscenecommand.h"
#include "removepropertiescommand.h"
#include "reparentinstancescommand.h"
#include "changeidscommand.h"
#include "changestatecommand.h"
#include "completecomponentcommand.h"
#include "addimportcontainer.h"
#include "changenodesourcecommand.h"

#include "informationchangedcommand.h"
#include "pixmapchangedcommand.h"
#include "valueschangedcommand.h"
#include "childrenchangedcommand.h"
#include "imagecontainer.h"
#include "statepreviewimagechangedcommand.h"
#include "componentcompletedcommand.h"
#include "synchronizecommand.h"
#include "tokencommand.h"
#include "removesharedmemorycommand.h"

namespace QmlDesigner {

static bool isRegistered=false;

NodeInstanceServerInterface::NodeInstanceServerInterface(QObject *parent) :
    QObject(parent)
{
    registerCommands();
}

void NodeInstanceServerInterface::registerCommands()
{
    if (isRegistered)
        return;

    isRegistered = true;

    qRegisterMetaType<CreateInstancesCommand>("CreateInstancesCommand");
    qRegisterMetaTypeStreamOperators<CreateInstancesCommand>("CreateInstancesCommand");

    qRegisterMetaType<ClearSceneCommand>("ClearSceneCommand");
    qRegisterMetaTypeStreamOperators<ClearSceneCommand>("ClearSceneCommand");

    qRegisterMetaType<CreateSceneCommand>("CreateSceneCommand");
    qRegisterMetaTypeStreamOperators<CreateSceneCommand>("CreateSceneCommand");

    qRegisterMetaType<ChangeBindingsCommand>("ChangeBindingsCommand");
    qRegisterMetaTypeStreamOperators<ChangeBindingsCommand>("ChangeBindingsCommand");

    qRegisterMetaType<ChangeValuesCommand>("ChangeValuesCommand");
    qRegisterMetaTypeStreamOperators<ChangeValuesCommand>("ChangeValuesCommand");

    qRegisterMetaType<ChangeFileUrlCommand>("ChangeFileUrlCommand");
    qRegisterMetaTypeStreamOperators<ChangeFileUrlCommand>("ChangeFileUrlCommand");

    qRegisterMetaType<ChangeStateCommand>("ChangeStateCommand");
    qRegisterMetaTypeStreamOperators<ChangeStateCommand>("ChangeStateCommand");

    qRegisterMetaType<RemoveInstancesCommand>("RemoveInstancesCommand");
    qRegisterMetaTypeStreamOperators<RemoveInstancesCommand>("RemoveInstancesCommand");

    qRegisterMetaType<RemovePropertiesCommand>("RemovePropertiesCommand");
    qRegisterMetaTypeStreamOperators<RemovePropertiesCommand>("RemovePropertiesCommand");

    qRegisterMetaType<ReparentInstancesCommand>("ReparentInstancesCommand");
    qRegisterMetaTypeStreamOperators<ReparentInstancesCommand>("ReparentInstancesCommand");

    qRegisterMetaType<ChangeIdsCommand>("ChangeIdsCommand");
    qRegisterMetaTypeStreamOperators<ChangeIdsCommand>("ChangeIdsCommand");

    qRegisterMetaType<ChangeStateCommand>("ChangeStateCommand");
    qRegisterMetaTypeStreamOperators<ChangeStateCommand>("ChangeStateCommand");

    qRegisterMetaType<InformationChangedCommand>("InformationChangedCommand");
    qRegisterMetaTypeStreamOperators<InformationChangedCommand>("InformationChangedCommand");

    qRegisterMetaType<ValuesChangedCommand>("ValuesChangedCommand");
    qRegisterMetaTypeStreamOperators<ValuesChangedCommand>("ValuesChangedCommand");

    qRegisterMetaType<PixmapChangedCommand>("PixmapChangedCommand");
    qRegisterMetaTypeStreamOperators<PixmapChangedCommand>("PixmapChangedCommand");

    qRegisterMetaType<InformationContainer>("InformationContainer");
    qRegisterMetaTypeStreamOperators<InformationContainer>("InformationContainer");

    qRegisterMetaType<PropertyValueContainer>("PropertyValueContainer");
    qRegisterMetaTypeStreamOperators<PropertyValueContainer>("PropertyValueContainer");

    qRegisterMetaType<PropertyBindingContainer>("PropertyBindingContainer");
    qRegisterMetaTypeStreamOperators<PropertyBindingContainer>("PropertyBindingContainer");

    qRegisterMetaType<PropertyAbstractContainer>("PropertyAbstractContainer");
    qRegisterMetaTypeStreamOperators<PropertyAbstractContainer>("PropertyAbstractContainer");

    qRegisterMetaType<InstanceContainer>("InstanceContainer");
    qRegisterMetaTypeStreamOperators<InstanceContainer>("InstanceContainer");

    qRegisterMetaType<IdContainer>("IdContainer");
    qRegisterMetaTypeStreamOperators<IdContainer>("IdContainer");

    qRegisterMetaType<ChildrenChangedCommand>("ChildrenChangedCommand");
    qRegisterMetaTypeStreamOperators<ChildrenChangedCommand>("ChildrenChangedCommand");

    qRegisterMetaType<ImageContainer>("ImageContainer");
    qRegisterMetaTypeStreamOperators<ImageContainer>("ImageContainer");

    qRegisterMetaType<StatePreviewImageChangedCommand>("StatePreviewImageChangedCommand");
    qRegisterMetaTypeStreamOperators<StatePreviewImageChangedCommand>("StatePreviewImageChangedCommand");

    qRegisterMetaType<CompleteComponentCommand>("CompleteComponentCommand");
    qRegisterMetaTypeStreamOperators<CompleteComponentCommand>("CompleteComponentCommand");

    qRegisterMetaType<ComponentCompletedCommand>("ComponentCompletedCommand");
    qRegisterMetaTypeStreamOperators<ComponentCompletedCommand>("ComponentCompletedCommand");

    qRegisterMetaType<AddImportContainer>("AddImportContainer");
    qRegisterMetaTypeStreamOperators<AddImportContainer>("AddImportContainer");

    qRegisterMetaType<SynchronizeCommand>("SynchronizeCommand");
    qRegisterMetaTypeStreamOperators<SynchronizeCommand>("SynchronizeCommand");

    qRegisterMetaType<ChangeNodeSourceCommand>("ChangeNodeSourceCommand");
    qRegisterMetaTypeStreamOperators<ChangeNodeSourceCommand>("ChangeNodeSourceCommand");

    qRegisterMetaType<ChangeAuxiliaryCommand>("ChangeAuxiliaryCommand");
    qRegisterMetaTypeStreamOperators<ChangeAuxiliaryCommand>("ChangeAuxiliaryCommand");

    qRegisterMetaType<TokenCommand>("TokenCommand");
    qRegisterMetaTypeStreamOperators<TokenCommand>("TokenCommand");

    qRegisterMetaType<RemoveSharedMemoryCommand>("RemoveSharedMemoryCommand");
    qRegisterMetaTypeStreamOperators<RemoveSharedMemoryCommand>("RemoveSharedMemoryCommand");
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Chaobin Zhang. All rights reserved.
// Use of this source code is governed by the BSD license that can be
// found in the LICENSE file.

#include "slave/slave_main_runner.h"

#include <set>
#include <vector>

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/hash.h"
#include "base/md5.h"
#include "base/stl_util.h"
#include "base/threading/thread_restrictions.h"
#include "common/util.h"
#include "ninja/ninja_main.h"
#include "proto/slave_services.pb.h"
#include "slave/slave_file_thread.h"
#include "slave/slave_rpc.h"
#include "thread/ninja_thread.h"

namespace {

slave::RunCommandResponse::ExitStatus TransformExitStatus(ExitStatus status) {
  switch (status) {
  case ExitSuccess:
    return slave::RunCommandResponse::kExitSuccess;
  case ExitFailure:
    return slave::RunCommandResponse::kExitFailure;
  case ExitInterrupted:
    return slave::RunCommandResponse::kExitInterrupted;
  default:
    NOTREACHED();
    return slave::RunCommandResponse::kExitFailure;
  }
}

void FindAllEdges(Edge* e, std::set<Edge*>* seen, std::vector<Edge*>* edges) {
  if (e == NULL || seen->insert(e).second == false)
    return;

  for (size_t i = 0; i < e->inputs_.size(); ++i)
    FindAllEdges(e->inputs_[i]->in_edge(), seen, edges);

  edges->push_back(e);
}

}  // namespace

namespace slave {

SlaveMainRunner::SlaveMainRunner(const std::string& master, uint16 port)
    : master_(master),
      port_(port),
      command_executor_(new common::CommandExecutor()) {
  command_executor_->AddObserver(this);
}

SlaveMainRunner::~SlaveMainRunner() {
  command_executor_->RemoveObserver(this);
}

void SlaveMainRunner::OnCommandStarted(const std::string& command) {
}

void SlaveMainRunner::OnCommandFinished(const std::string& command,
                                        const CommandRunner::Result* result) {
  uint32 command_hash = base::Hash(command);
  DCHECK(command_hash_edge_map_.find(command_hash) !=
         command_hash_edge_map_.end());
  plan_.EdgeFinished(command_hash_edge_map_[command_hash]);
  StartReadyEdges();

  RunCommandContextMap::iterator it =
      run_command_context_map_.find(command_hash);
  if (it == run_command_context_map_.end())
    return;

  it->second.response->set_output(result->output);
  it->second.response->set_status(TransformExitStatus(result->status));
  NinjaThread::PostBlockingPoolTask(
      FROM_HERE,
      base::Bind(&SlaveMainRunner::MD5OutputsOnBlockingPool, this, it->second));
  run_command_context_map_.erase(it);
}

bool SlaveMainRunner::PostCreateThreads() {
  slave_rpc_.reset(new SlaveRPC(master_, port_, this));
  slave_file_thread_.reset(new SlaveFileThread());

  std::set<Edge*> edges;
  ninja_main()->GetAllEdges(&edges);
  for (std::set<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
    uint32 hash = common::HashEdge(*it);
    CHECK(hash_edge_map_.find(hash) == hash_edge_map_.end());
    hash_edge_map_[hash] = (*it);
  }

  ninja_main()->InitForSlave();
  return true;
}

void SlaveMainRunner::RunCommand(const RunCommandRequest* request,
                                 RunCommandResponse* response,
                                 ::google::protobuf::Closure* done) {
  uint32 edge_id = request->edge_id();
  response->set_edge_id(edge_id);

  if (!ContainsKey(hash_edge_map_, edge_id)) {
    response->set_status(RunCommandResponse::kExitFailure);
    response->set_output("This command is NOT ALLOWED to run.");
    NinjaThread::PostTask(
        NinjaThread::RPC, FROM_HERE,
        base::Bind(&SlaveRPC::OnRunCommandDone,
                   base::Unretained(slave_rpc_.get()),
                   done));
    return;
  }

  Edge* edge = hash_edge_map_[edge_id];
  const std::string& command = edge->EvaluateCommand();
  run_command_context_map_[base::Hash(command)] = {request, response, done};

  if (edge->outputs_ready()) {
    CommandRunner::Result result;
    result.status = ExitSuccess;
    OnCommandFinished(edge->EvaluateCommand(), &result);
    return;
  }

  std::string error;
  for (size_t i = 0; i < edge->outputs_.size(); ++i) {
    if (!plan_.AddTarget(edge->outputs_[i], &error)) {
      LOG(ERROR) << error;
    }
  }

  StartReadyEdges();
}

void SlaveMainRunner::Wait() {
}

bool SlaveMainRunner::CreateDirsAndResponseFile(
    const RunCommandRequest* request) {
  base::ThreadRestrictions::AssertIOAllowed();
  for (int i = 0; i < request->output_paths_size(); ++i) {
    base::FilePath dir =
        base::FilePath::FromUTF8Unsafe(request->output_paths(i));
    if (!base::CreateDirectory(dir.DirName()))
      return false;
  }
  if (request->has_rspfile_name()) {
    if (!ninja_main()->disk_interface()->WriteFile(request->rspfile_name(),
                                                   request->rspfile_content()))
      return false;
  }

  return true;
}

void SlaveMainRunner::MD5OutputsOnBlockingPool(
    const RunCommandContext& context) {
  if (context.response->status() == slave::RunCommandResponse::kExitSuccess) {
    for (int i = 0; i < context.request->output_paths_size(); ++i) {
      base::FilePath filename =
          base::FilePath::FromUTF8Unsafe(context.request->output_paths(i));
      std::string md5 = "";
      if (base::PathExists(filename)) {
        md5 = common::GetMd5Digest(filename);
        CHECK(!md5.empty());
      }

      context.response->add_md5()->assign(md5);
    }
  }

  NinjaThread::PostTask(
      NinjaThread::RPC, FROM_HERE,
      base::Bind(&SlaveRPC::OnRunCommandDone,
                 base::Unretained(slave_rpc_.get()),
                 context.done));
}

bool SlaveMainRunner::StartEdge(Edge* edge) {
  if (edge->is_phony())
    return true;

  // Create directories necessary for outputs.
  for (vector<Node*>::iterator o = edge->outputs_.begin();
       o != edge->outputs_.end(); ++o) {
    base::FilePath dir =
        base::FilePath::FromUTF8Unsafe((*o)->path());
    if (!base::CreateDirectory(dir.DirName()))
      return false;
  }

  // Create response file, if needed
  std::string rspfile = edge->GetUnescapedRspfile();
  if (!rspfile.empty()) {
    std::string content = edge->GetBinding("rspfile_content");
    if (!ninja_main()->disk_interface()->WriteFile(rspfile, content))
      return false;
  }

  std::string command = edge->EvaluateCommand();
  command_executor_->RunCommand(edge->EvaluateCommand());
  return true;
}

void SlaveMainRunner::StartReadyEdges() {
  Edge* ready_edge = NULL;
  while ((ready_edge = plan_.FindWork()) != NULL) {
    std::string command = ready_edge->EvaluateCommand();
    command_hash_edge_map_[base::Hash(command)] = ready_edge;
    StartEdge(ready_edge);
  }
}

}  // namespace slave
<commit_msg>[Slave] Don't abort if md5 error.<commit_after>// Copyright (c) 2015 Chaobin Zhang. All rights reserved.
// Use of this source code is governed by the BSD license that can be
// found in the LICENSE file.

#include "slave/slave_main_runner.h"

#include <set>
#include <vector>

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/hash.h"
#include "base/md5.h"
#include "base/stl_util.h"
#include "base/threading/thread_restrictions.h"
#include "common/util.h"
#include "ninja/ninja_main.h"
#include "proto/slave_services.pb.h"
#include "slave/slave_file_thread.h"
#include "slave/slave_rpc.h"
#include "thread/ninja_thread.h"

namespace {

slave::RunCommandResponse::ExitStatus TransformExitStatus(ExitStatus status) {
  switch (status) {
  case ExitSuccess:
    return slave::RunCommandResponse::kExitSuccess;
  case ExitFailure:
    return slave::RunCommandResponse::kExitFailure;
  case ExitInterrupted:
    return slave::RunCommandResponse::kExitInterrupted;
  default:
    NOTREACHED();
    return slave::RunCommandResponse::kExitFailure;
  }
}

void FindAllEdges(Edge* e, std::set<Edge*>* seen, std::vector<Edge*>* edges) {
  if (e == NULL || seen->insert(e).second == false)
    return;

  for (size_t i = 0; i < e->inputs_.size(); ++i)
    FindAllEdges(e->inputs_[i]->in_edge(), seen, edges);

  edges->push_back(e);
}

}  // namespace

namespace slave {

SlaveMainRunner::SlaveMainRunner(const std::string& master, uint16 port)
    : master_(master),
      port_(port),
      command_executor_(new common::CommandExecutor()) {
  command_executor_->AddObserver(this);
}

SlaveMainRunner::~SlaveMainRunner() {
  command_executor_->RemoveObserver(this);
}

void SlaveMainRunner::OnCommandStarted(const std::string& command) {
}

void SlaveMainRunner::OnCommandFinished(const std::string& command,
                                        const CommandRunner::Result* result) {
  uint32 command_hash = base::Hash(command);
  DCHECK(command_hash_edge_map_.find(command_hash) !=
         command_hash_edge_map_.end());
  plan_.EdgeFinished(command_hash_edge_map_[command_hash]);
  StartReadyEdges();

  RunCommandContextMap::iterator it =
      run_command_context_map_.find(command_hash);
  if (it == run_command_context_map_.end())
    return;

  it->second.response->set_output(result->output);
  it->second.response->set_status(TransformExitStatus(result->status));
  NinjaThread::PostBlockingPoolTask(
      FROM_HERE,
      base::Bind(&SlaveMainRunner::MD5OutputsOnBlockingPool, this, it->second));
  run_command_context_map_.erase(it);
}

bool SlaveMainRunner::PostCreateThreads() {
  slave_rpc_.reset(new SlaveRPC(master_, port_, this));
  slave_file_thread_.reset(new SlaveFileThread());

  std::set<Edge*> edges;
  ninja_main()->GetAllEdges(&edges);
  for (std::set<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
    uint32 hash = common::HashEdge(*it);
    CHECK(hash_edge_map_.find(hash) == hash_edge_map_.end());
    hash_edge_map_[hash] = (*it);
  }

  ninja_main()->InitForSlave();
  return true;
}

void SlaveMainRunner::RunCommand(const RunCommandRequest* request,
                                 RunCommandResponse* response,
                                 ::google::protobuf::Closure* done) {
  uint32 edge_id = request->edge_id();
  response->set_edge_id(edge_id);

  if (!ContainsKey(hash_edge_map_, edge_id)) {
    response->set_status(RunCommandResponse::kExitFailure);
    response->set_output("This command is NOT ALLOWED to run.");
    NinjaThread::PostTask(
        NinjaThread::RPC, FROM_HERE,
        base::Bind(&SlaveRPC::OnRunCommandDone,
                   base::Unretained(slave_rpc_.get()),
                   done));
    return;
  }

  Edge* edge = hash_edge_map_[edge_id];
  const std::string& command = edge->EvaluateCommand();
  run_command_context_map_[base::Hash(command)] = {request, response, done};

  if (edge->outputs_ready()) {
    CommandRunner::Result result;
    result.status = ExitSuccess;
    OnCommandFinished(edge->EvaluateCommand(), &result);
    return;
  }

  std::string error;
  for (size_t i = 0; i < edge->outputs_.size(); ++i) {
    if (!plan_.AddTarget(edge->outputs_[i], &error)) {
      LOG(ERROR) << error;
    }
  }

  StartReadyEdges();
}

void SlaveMainRunner::Wait() {
}

bool SlaveMainRunner::CreateDirsAndResponseFile(
    const RunCommandRequest* request) {
  base::ThreadRestrictions::AssertIOAllowed();
  for (int i = 0; i < request->output_paths_size(); ++i) {
    base::FilePath dir =
        base::FilePath::FromUTF8Unsafe(request->output_paths(i));
    if (!base::CreateDirectory(dir.DirName()))
      return false;
  }
  if (request->has_rspfile_name()) {
    if (!ninja_main()->disk_interface()->WriteFile(request->rspfile_name(),
                                                   request->rspfile_content()))
      return false;
  }

  return true;
}

void SlaveMainRunner::MD5OutputsOnBlockingPool(
    const RunCommandContext& context) {
  if (context.response->status() == slave::RunCommandResponse::kExitSuccess) {
    for (int i = 0; i < context.request->output_paths_size(); ++i) {
      base::FilePath filename =
          base::FilePath::FromUTF8Unsafe(context.request->output_paths(i));
      std::string md5 = "";
      if (base::PathExists(filename)) {
        md5 = common::GetMd5Digest(filename);
        if (md5.empty()) {
          LOG(ERROR) << "GetMd5Digest of " << filename.value();
        }
      }

      context.response->add_md5()->assign(md5);
    }
  }

  NinjaThread::PostTask(
      NinjaThread::RPC, FROM_HERE,
      base::Bind(&SlaveRPC::OnRunCommandDone,
                 base::Unretained(slave_rpc_.get()),
                 context.done));
}

bool SlaveMainRunner::StartEdge(Edge* edge) {
  if (edge->is_phony())
    return true;

  // Create directories necessary for outputs.
  for (vector<Node*>::iterator o = edge->outputs_.begin();
       o != edge->outputs_.end(); ++o) {
    base::FilePath dir =
        base::FilePath::FromUTF8Unsafe((*o)->path());
    if (!base::CreateDirectory(dir.DirName()))
      return false;
  }

  // Create response file, if needed
  std::string rspfile = edge->GetUnescapedRspfile();
  if (!rspfile.empty()) {
    std::string content = edge->GetBinding("rspfile_content");
    if (!ninja_main()->disk_interface()->WriteFile(rspfile, content))
      return false;
  }

  std::string command = edge->EvaluateCommand();
  command_executor_->RunCommand(edge->EvaluateCommand());
  return true;
}

void SlaveMainRunner::StartReadyEdges() {
  Edge* ready_edge = NULL;
  while ((ready_edge = plan_.FindWork()) != NULL) {
    std::string command = ready_edge->EvaluateCommand();
    command_hash_edge_map_[base::Hash(command)] = ready_edge;
    StartEdge(ready_edge);
  }
}

}  // namespace slave
<|endoftext|>


<commit_before>//
// Copyright (c) 2012 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

/// @brief  ParallelPrimeSieve sieves primes in parallel
///         using OpenMP 3.0 (2008) or later.

#include "ParallelPrimeSieve.h"
#include "PrimeSieve.h"
#include "imath.h"
#include "config.h"

#include <stdint.h>
#include <cstdlib>
#include <cassert>
#include <algorithm>

#ifdef _OPENMP
  #include <omp.h>
  #include "openmp_RAII.h"
#endif

using namespace soe;

ParallelPrimeSieve::ParallelPrimeSieve() :
  shm_(NULL),
  numThreads_(DEFAULT_NUM_THREADS)
{ }

/// API for the primesieve GUI application
void ParallelPrimeSieve::init(SharedMemory& shm)
{
  setStart(shm.start);
  setStop(shm.stop);
  setSieveSize(shm.sieveSize);
  setFlags(shm.flags);
  setNumThreads(shm.threads);
  shm_ = &shm;
}

int ParallelPrimeSieve::getNumThreads() const
{
  if (numThreads_ == DEFAULT_NUM_THREADS) {
    // Use 1 thread to generate primes in arithmetic order
    return isGenerate() ? 1 : idealNumThreads();
  }
  return numThreads_;
}

void ParallelPrimeSieve::setNumThreads(int threads)
{
  numThreads_ = getInBetween(1, threads, getMaxThreads());
}

/// Get an ideal number of threads for the current
/// set start_ and stop_ numbers.
///
int ParallelPrimeSieve::idealNumThreads() const
{
  uint64_t threshold = std::max(config::MIN_THREAD_INTERVAL, isqrt(stop_) / 5);
  uint64_t threads = getInterval() / threshold;
  threads = getInBetween<uint64_t>(1, threads, getMaxThreads());
  return static_cast<int>(threads);
}

/// Get an interval size that ensures a good load balance
/// when multiple threads are used.
///
uint64_t ParallelPrimeSieve::getThreadInterval(int threads) const
{
  assert(threads > 0);
  uint64_t unbalanced = getInterval() / threads;
  uint64_t balanced = isqrt(stop_) * 1000;
  uint64_t fastest = std::min(balanced, unbalanced);
  uint64_t threadInterval = getInBetween(config::MIN_THREAD_INTERVAL, fastest, config::MAX_THREAD_INTERVAL);
  uint64_t chunks = getInterval() / threadInterval;
  if (chunks < threads * 5u)
    threadInterval = std::max(config::MIN_THREAD_INTERVAL, unbalanced);
  threadInterval += 30 - threadInterval % 30;
  return threadInterval;
}

/// Align n to modulo 30 + 2 to prevent prime k-tuplet
/// (twin primes, prime triplets, ...) gaps.
///
uint64_t ParallelPrimeSieve::align(uint64_t n) const
{
  if (n != start_)
    n = std::min(n + 32 - n % 30, stop_);
  return n;
}

bool ParallelPrimeSieve::tooMany(int threads) const
{
  return (threads > 1 && getInterval() / threads < config::MIN_THREAD_INTERVAL);
}

#ifdef _OPENMP

int ParallelPrimeSieve::getMaxThreads()
{
  return omp_get_max_threads();
}

/// Sieve the primes and prime k-tuplets within [start, stop]
/// in parallel using OpenMP (version 3.0 or later).
///
void ParallelPrimeSieve::sieve()
{
  if (start_ > stop_)
    throw primesieve_error("start must be <= stop");

  int threads = getNumThreads();
  if (tooMany(threads)) threads = idealNumThreads();
  OmpInitLock ompInit(&lock_);

  if (threads == 1)
    PrimeSieve::sieve();
  else {
    double time = omp_get_wtime();
    reset();
    uint64_t threadInterval = getThreadInterval(threads);
    uint64_t count0 = 0, count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0, count6 = 0;

    // The sieve interval [start_, stop_] is subdivided into chunks of
    // size 'threadInterval' that are sieved in parallel using
    // multiple threads. This scales well as each thread sieves using
    // its own private memory without need of synchronization.
    #pragma omp parallel for schedule(dynamic) num_threads(threads) \
        reduction(+: count0, count1, count2, count3, count4, count5, count6)
    for (uint64_t n = start_; n < stop_; n += threadInterval) {
      PrimeSieve ps(*this, omp_get_thread_num());
      uint64_t threadStart = align(n);
      uint64_t threadStop  = align(n + threadInterval);
      ps.sieve(threadStart, threadStop);
      count0 += ps.getCount(0);
      count1 += ps.getCount(1);
      count2 += ps.getCount(2);
      count3 += ps.getCount(3);
      count4 += ps.getCount(4);
      count5 += ps.getCount(5);
      count6 += ps.getCount(6);
    }

    seconds_ = omp_get_wtime() - time;
    counts_[0] = count0;
    counts_[1] = count1;
    counts_[2] = count2;
    counts_[3] = count3;
    counts_[4] = count4;
    counts_[5] = count5;
    counts_[6] = count6;
  }

  // communicate the sieving results to the
  // primesieve GUI application
  if (shm_ != NULL) {
    std::copy(counts_.begin(), counts_.end(), shm_->counts);
    shm_->seconds = seconds_;
  }
}

/// Calculate the sieving status (in percent).
/// @param processed Sum of recently processed segments.
///
bool ParallelPrimeSieve::updateStatus(uint64_t processed, bool waitForLock)
{
  OmpLockGuard lock(getLock<omp_lock_t*>(), waitForLock);
  if (lock.isSet()) {
    PrimeSieve::updateStatus(processed, false);
    if (shm_ != NULL)
      shm_->status = getStatus();
  }
  return lock.isSet();
}

/// Used to synchronize threads for prime number generation

void ParallelPrimeSieve::setLock()
{
  omp_lock_t* lock = getLock<omp_lock_t*>();
  omp_set_lock(lock);
}

void ParallelPrimeSieve::unsetLock()
{
  omp_lock_t* lock = getLock<omp_lock_t*>();
  omp_unset_lock(lock);
}

#endif /* _OPENMP */

/// If OpenMP is not used then ParallelPrimeSieve behaves like
/// the single threaded PrimeSieve.
///
#if !defined(_OPENMP)

int ParallelPrimeSieve::getMaxThreads()
{
  return 1;
}

void ParallelPrimeSieve::sieve()
{
  PrimeSieve::sieve();
}

bool ParallelPrimeSieve::updateStatus(uint64_t processed, bool waitForLock)
{
  return PrimeSieve::updateStatus(processed, waitForLock);
}

void ParallelPrimeSieve::setLock() { }

void ParallelPrimeSieve::unsetLock() { }

#endif
<commit_msg>added support for OpenMP 2.x<commit_after>//
// Copyright (c) 2012 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

/// @brief  ParallelPrimeSieve sieves primes in parallel using
///         OpenMP 2.0 (2002) or later.

#include "ParallelPrimeSieve.h"
#include "PrimeSieve.h"
#include "imath.h"
#include "config.h"

#include <stdint.h>
#include <cstdlib>
#include <cassert>
#include <algorithm>

#ifdef _OPENMP
  #include <omp.h>
  #include "openmp_RAII.h"
#endif

using namespace soe;

ParallelPrimeSieve::ParallelPrimeSieve() :
  shm_(NULL),
  numThreads_(DEFAULT_NUM_THREADS)
{ }

/// API for the primesieve GUI application
void ParallelPrimeSieve::init(SharedMemory& shm)
{
  setStart(shm.start);
  setStop(shm.stop);
  setSieveSize(shm.sieveSize);
  setFlags(shm.flags);
  setNumThreads(shm.threads);
  shm_ = &shm;
}

int ParallelPrimeSieve::getNumThreads() const
{
  if (numThreads_ == DEFAULT_NUM_THREADS) {
    // Use 1 thread to generate primes in arithmetic order
    return isGenerate() ? 1 : idealNumThreads();
  }
  return numThreads_;
}

void ParallelPrimeSieve::setNumThreads(int threads)
{
  numThreads_ = getInBetween(1, threads, getMaxThreads());
}

/// Get an ideal number of threads for the current
/// set start_ and stop_ numbers.
///
int ParallelPrimeSieve::idealNumThreads() const
{
  uint64_t threshold = std::max(config::MIN_THREAD_INTERVAL, isqrt(stop_) / 5);
  uint64_t threads = getInterval() / threshold;
  threads = getInBetween<uint64_t>(1, threads, getMaxThreads());
  return static_cast<int>(threads);
}

/// Get an interval size that ensures a good load balance
/// when multiple threads are used.
///
uint64_t ParallelPrimeSieve::getThreadInterval(int threads) const
{
  assert(threads > 0);
  uint64_t unbalanced = getInterval() / threads;
  uint64_t balanced = isqrt(stop_) * 1000;
  uint64_t fastest = std::min(balanced, unbalanced);
  uint64_t threadInterval = getInBetween(config::MIN_THREAD_INTERVAL, fastest, config::MAX_THREAD_INTERVAL);
  uint64_t chunks = getInterval() / threadInterval;
  if (chunks < threads * 5u)
    threadInterval = std::max(config::MIN_THREAD_INTERVAL, unbalanced);
  threadInterval += 30 - threadInterval % 30;
  return threadInterval;
}

/// Align n to modulo 30 + 2 to prevent prime k-tuplet
/// (twin primes, prime triplets, ...) gaps.
///
uint64_t ParallelPrimeSieve::align(uint64_t n) const
{
  if (n != start_)
    n = std::min(n + 32 - n % 30, stop_);
  return n;
}

bool ParallelPrimeSieve::tooMany(int threads) const
{
  return (threads > 1 && getInterval() / threads < config::MIN_THREAD_INTERVAL);
}

#ifdef _OPENMP

int ParallelPrimeSieve::getMaxThreads()
{
  return omp_get_max_threads();
}

/// Sieve the primes and prime k-tuplets within [start, stop]
/// in parallel using OpenMP multi-threading.
///
void ParallelPrimeSieve::sieve()
{
  if (start_ > stop_)
    throw primesieve_error("start must be <= stop");

  int threads = getNumThreads();
  if (tooMany(threads)) threads = idealNumThreads();
  OmpInitLock ompInit(&lock_);

  if (threads == 1)
    PrimeSieve::sieve();
  else {
    double time = omp_get_wtime();
    reset();
    uint64_t count0 = 0, count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0, count6 = 0;
    uint64_t threadInterval = getThreadInterval(threads);

#if _OPENMP >= 200800 /* OpenMP >= 3.0 (2008) */

    // The sieve interval [start_, stop_] is subdivided into chunks of
    // size 'threadInterval' that are sieved in parallel using
    // multiple threads. This scales well as each thread sieves using
    // its own private memory without need of synchronization.
    #pragma omp parallel for schedule(dynamic) num_threads(threads) \
      reduction(+: count0, count1, count2, count3, count4, count5, count6)
    for (uint64_t n = start_; n < stop_; n += threadInterval) {
      PrimeSieve ps(*this, omp_get_thread_num());
      uint64_t threadStart = align(n);
      uint64_t threadStop  = align(n + threadInterval);
      ps.sieve(threadStart, threadStop);
      count0 += ps.getCount(0);
      count1 += ps.getCount(1);
      count2 += ps.getCount(2);
      count3 += ps.getCount(3);
      count4 += ps.getCount(4);
      count5 += ps.getCount(5);
      count6 += ps.getCount(6);
    }

#else /* OpenMP 2.x */

    int64_t iters = idivCeil(getInterval(), threadInterval);

    #pragma omp parallel for schedule(dynamic) num_threads(threads) \
      reduction(+: count0, count1, count2, count3, count4, count5, count6)
    for (int64_t i = 0; i < iters; i++) {
      PrimeSieve ps(*this, omp_get_thread_num());
      uint64_t threadStart = align(start_ +  i * threadInterval);
      uint64_t threadStop  = align(start_ + (i + 1) * threadInterval);
      ps.sieve(threadStart, threadStop);
      count0 += ps.getCount(0);
      count1 += ps.getCount(1);
      count2 += ps.getCount(2);
      count3 += ps.getCount(3);
      count4 += ps.getCount(4);
      count5 += ps.getCount(5);
      count6 += ps.getCount(6);
    }

#endif

    seconds_ = omp_get_wtime() - time;
    counts_[0] = count0;
    counts_[1] = count1;
    counts_[2] = count2;
    counts_[3] = count3;
    counts_[4] = count4;
    counts_[5] = count5;
    counts_[6] = count6;
  }

  // communicate the sieving results to the
  // primesieve GUI application
  if (shm_ != NULL) {
    std::copy(counts_.begin(), counts_.end(), shm_->counts);
    shm_->seconds = seconds_;
  }
}

/// Calculate the sieving status (in percent).
/// @param processed Sum of recently processed segments.
///
bool ParallelPrimeSieve::updateStatus(uint64_t processed, bool waitForLock)
{
  OmpLockGuard lock(getLock<omp_lock_t*>(), waitForLock);
  if (lock.isSet()) {
    PrimeSieve::updateStatus(processed, false);
    if (shm_ != NULL)
      shm_->status = getStatus();
  }
  return lock.isSet();
}

/// Used to synchronize threads for prime number generation

void ParallelPrimeSieve::setLock()
{
  omp_lock_t* lock = getLock<omp_lock_t*>();
  omp_set_lock(lock);
}

void ParallelPrimeSieve::unsetLock()
{
  omp_lock_t* lock = getLock<omp_lock_t*>();
  omp_unset_lock(lock);
}

#endif /* _OPENMP */

/// If OpenMP is not used then ParallelPrimeSieve behaves like
/// the single threaded PrimeSieve.
///
#if !defined(_OPENMP)

int ParallelPrimeSieve::getMaxThreads()
{
  return 1;
}

void ParallelPrimeSieve::sieve()
{
  PrimeSieve::sieve();
}

bool ParallelPrimeSieve::updateStatus(uint64_t processed, bool waitForLock)
{
  return PrimeSieve::updateStatus(processed, waitForLock);
}

void ParallelPrimeSieve::setLock() { }

void ParallelPrimeSieve::unsetLock() { }

#endif
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include "QGCGeoBoundingCube.h"
#include <QDebug>

double QGCGeoBoundingCube::MaxAlt    =  1000000.0;
double QGCGeoBoundingCube::MinAlt    = -1000000.0;
double QGCGeoBoundingCube::MaxNorth  =  90.0;
double QGCGeoBoundingCube::MaxSouth  = -90.0;
double QGCGeoBoundingCube::MaxWest   = -180.0;
double QGCGeoBoundingCube::MaxEast   =  180.0;

//-----------------------------------------------------------------------------
bool
QGCGeoBoundingCube::isValid() const
{
    return pointNW.isValid() && pointSE.isValid() && pointNW.latitude() != MaxSouth && pointSE.latitude() != MaxNorth && \
           pointNW.longitude() != MaxEast && pointSE.longitude() != MaxWest && pointNW.altitude() < MaxAlt and pointSE.altitude() > MinAlt;
}

//-----------------------------------------------------------------------------
void
QGCGeoBoundingCube::reset()
{
    pointSE = QGeoCoordinate();
    pointNW = QGeoCoordinate();
}

//-----------------------------------------------------------------------------
QGeoCoordinate
QGCGeoBoundingCube::center() const
{
    if(!isValid())
        return QGeoCoordinate();
    double lat = (((pointNW.latitude()  + 90.0)  + (pointSE.latitude()  + 90.0))  / 2.0) - 90.0;
    double lon = (((pointNW.longitude() + 180.0) + (pointSE.longitude() + 180.0)) / 2.0) - 180.0;
    double alt = (pointNW.altitude() + pointSE.altitude()) / 2.0;
    return QGeoCoordinate(lat, lon, alt);
}

//-----------------------------------------------------------------------------
QList<QGeoCoordinate>
QGCGeoBoundingCube::polygon2D() const
{
    QList<QGeoCoordinate> coords;
    if(isValid()) {
        coords.append(QGeoCoordinate(pointNW.latitude(), pointNW.longitude(), pointSE.altitude()));
        coords.append(QGeoCoordinate(pointNW.latitude(), pointSE.longitude(), pointSE.altitude()));
        coords.append(QGeoCoordinate(pointSE.latitude(), pointSE.longitude(), pointSE.altitude()));
        coords.append(QGeoCoordinate(pointSE.latitude(), pointNW.longitude(), pointSE.altitude()));
        coords.append(QGeoCoordinate(pointNW.latitude(), pointNW.longitude(), pointSE.altitude()));
    }
    return coords;
}

//-----------------------------------------------------------------------------
bool
QGCGeoBoundingCube::operator ==(const QList<QGeoCoordinate>& coords) const
{
    QList<QGeoCoordinate> c = polygon2D();
    if(c.size() != coords.size()) return false;
    for(int i = 0; i < c.size(); i++) {
        if(c[i] != coords[i]) return false;
    }
    return true;
}

//-----------------------------------------------------------------------------
double
QGCGeoBoundingCube::width() const
{
    if(!isValid())
        return 0.0;
    QGeoCoordinate ne = QGeoCoordinate(pointNW.latitude(), pointSE.longitude());
    return pointNW.distanceTo(ne);
}

//-----------------------------------------------------------------------------
double
QGCGeoBoundingCube::height() const
{
    if(!isValid())
        return 0.0;
    QGeoCoordinate sw = QGeoCoordinate(pointSE.latitude(), pointNW.longitude());
    return pointNW.distanceTo(sw);
}

//-----------------------------------------------------------------------------
double
QGCGeoBoundingCube::area() const
{
    if(!isValid())
        return 0.0;
    // Area in km^2
    double a = (height() / 1000.0) * (width() / 1000.0);
    //qDebug() << "Area:" << a;
    return a;
}

//-----------------------------------------------------------------------------
double
QGCGeoBoundingCube::radius() const
{
    if(!isValid())
        return 0.0;
    return pointNW.distanceTo(pointSE) / 2.0;
}
<commit_msg>Fix Windows build. I have no idea how this was building elsewhere at all.<commit_after>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include "QGCGeoBoundingCube.h"
#include <QDebug>

double QGCGeoBoundingCube::MaxAlt    =  1000000.0;
double QGCGeoBoundingCube::MinAlt    = -1000000.0;
double QGCGeoBoundingCube::MaxNorth  =  90.0;
double QGCGeoBoundingCube::MaxSouth  = -90.0;
double QGCGeoBoundingCube::MaxWest   = -180.0;
double QGCGeoBoundingCube::MaxEast   =  180.0;

//-----------------------------------------------------------------------------
bool
QGCGeoBoundingCube::isValid() const
{
    return pointNW.isValid() && pointSE.isValid() && pointNW.latitude() != MaxSouth && pointSE.latitude() != MaxNorth && \
           pointNW.longitude() != MaxEast && pointSE.longitude() != MaxWest && pointNW.altitude() < MaxAlt && pointSE.altitude() > MinAlt;
}

//-----------------------------------------------------------------------------
void
QGCGeoBoundingCube::reset()
{
    pointSE = QGeoCoordinate();
    pointNW = QGeoCoordinate();
}

//-----------------------------------------------------------------------------
QGeoCoordinate
QGCGeoBoundingCube::center() const
{
    if(!isValid())
        return QGeoCoordinate();
    double lat = (((pointNW.latitude()  + 90.0)  + (pointSE.latitude()  + 90.0))  / 2.0) - 90.0;
    double lon = (((pointNW.longitude() + 180.0) + (pointSE.longitude() + 180.0)) / 2.0) - 180.0;
    double alt = (pointNW.altitude() + pointSE.altitude()) / 2.0;
    return QGeoCoordinate(lat, lon, alt);
}

//-----------------------------------------------------------------------------
QList<QGeoCoordinate>
QGCGeoBoundingCube::polygon2D() const
{
    QList<QGeoCoordinate> coords;
    if(isValid()) {
        coords.append(QGeoCoordinate(pointNW.latitude(), pointNW.longitude(), pointSE.altitude()));
        coords.append(QGeoCoordinate(pointNW.latitude(), pointSE.longitude(), pointSE.altitude()));
        coords.append(QGeoCoordinate(pointSE.latitude(), pointSE.longitude(), pointSE.altitude()));
        coords.append(QGeoCoordinate(pointSE.latitude(), pointNW.longitude(), pointSE.altitude()));
        coords.append(QGeoCoordinate(pointNW.latitude(), pointNW.longitude(), pointSE.altitude()));
    }
    return coords;
}

//-----------------------------------------------------------------------------
bool
QGCGeoBoundingCube::operator ==(const QList<QGeoCoordinate>& coords) const
{
    QList<QGeoCoordinate> c = polygon2D();
    if(c.size() != coords.size()) return false;
    for(int i = 0; i < c.size(); i++) {
        if(c[i] != coords[i]) return false;
    }
    return true;
}

//-----------------------------------------------------------------------------
double
QGCGeoBoundingCube::width() const
{
    if(!isValid())
        return 0.0;
    QGeoCoordinate ne = QGeoCoordinate(pointNW.latitude(), pointSE.longitude());
    return pointNW.distanceTo(ne);
}

//-----------------------------------------------------------------------------
double
QGCGeoBoundingCube::height() const
{
    if(!isValid())
        return 0.0;
    QGeoCoordinate sw = QGeoCoordinate(pointSE.latitude(), pointNW.longitude());
    return pointNW.distanceTo(sw);
}

//-----------------------------------------------------------------------------
double
QGCGeoBoundingCube::area() const
{
    if(!isValid())
        return 0.0;
    // Area in km^2
    double a = (height() / 1000.0) * (width() / 1000.0);
    //qDebug() << "Area:" << a;
    return a;
}

//-----------------------------------------------------------------------------
double
QGCGeoBoundingCube::radius() const
{
    if(!isValid())
        return 0.0;
    return pointNW.distanceTo(pointSE) / 2.0;
}
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "rpminputstream.h"
#include "cpioinputstream.h"
#include "gzipinputstream.h"
#include "bz2inputstream.h"
#include "subinputstream.h"
#include "textutils.h"

#include <list>

using namespace std;
using namespace Strigi;

class RpmInputStream::RpmHeaderInfo {
};
/**
 * RPM files as specified here:
 * http://www.freestandards.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/swinstall.html
 * and here:
 * http://www.rpm.org/max-rpm-snapshot/s1-rpm-file-format-rpm-file-format.html
 **/
bool
RpmInputStream::checkHeader(const char* data, int32_t datasize) {
    static const char unsigned magic[] = {0xed,0xab,0xee,0xdb,0x03,0x00};
    if (datasize < 6) return false;
    // this check could be more strict
    bool ok = memcmp(data, magic, 6) == 0;
    return ok;
}
RpmInputStream::RpmInputStream(InputStream* input)
        : SubStreamProvider(input), headerinfo(0) {
    uncompressionStream = 0;
    cpio = 0;

    // skip the header
    const char* b;
    // lead:96 bytes
    if (m_input->read(b, 96, 96) != 96) {
        m_status = Error;
        m_error = "File is too small to be an RPM file.";
        return;
    }

    // read signature
    const unsigned char headmagic[] = {0x8e,0xad,0xe8,0x01};
    if (m_input->read(b, 16, 16) != 16 || memcmp(b, headmagic, 4)!=0) {
        m_error = "m_error in signature\n";
        m_status = Error;
        return;
    }
    int32_t nindex = readBigEndianInt32(b+8);
    int32_t hsize = readBigEndianInt32(b+12);
    int32_t sz = nindex*16+hsize;
    if (sz%8) {
        sz+=8-sz%8;
    }
    if (m_input->read(b, sz, sz) != sz) {
        m_status = Error;
        m_error = "RPM seems to be truncated or corrupted.";
        return;
    }

    // read header
    if (m_input->read(b, 16, 16) != 16 || memcmp(b, headmagic, 4)!=0) {
        m_error = "m_error in header\n";
        m_status = Error;
        return;
    }
    nindex = readBigEndianInt32(b+8);
    hsize = readBigEndianInt32(b+12);
    int32_t size = nindex*16+hsize;
    if (m_input->read(b, size, size) != size) {
        m_error = "could not read header\n";
        m_status = Error;
        return;
    }
    for (int32_t i=0; i<nindex; ++i) {
        const unsigned char* e = (const unsigned char*)b+i*16;
        int32_t tag = readBigEndianInt32(e);
        int32_t type = readBigEndianInt32(e+4);
        int32_t offset = readBigEndianInt32(e+8);
        if (offset < 0 || offset >= hsize) {
            m_error = "invalid offset in header\n";
            m_status = Error;
            return;
        }
        int32_t count = readBigEndianInt32(e+12);
        int32_t end = hsize;
        if (i < nindex-1) {
            end = readBigEndianInt32(e+8+16);
        }
        if (end < offset) end = offset;
        if (end > hsize) end = hsize;
// TODO actually put the data into the objects so the analyzers can use them
/*        if (type == 6) {
            string s(b+nindex*16+offset, end-offset);
            printf("%s\n", s.c_str());
        } else if (type == 8 || type == 9) {
            list<string> v;
            // TODO handle string arrays
        }
        printf("%i\t%i\t%i\t%i\n", tag, type, offset, count);*/
    }

    int64_t pos = m_input->position();
    if (m_input->read(b, 16, 16) != 16) {
        m_error =  "could not read payload\n";
        m_status = Error;
        return;
    }
    m_input->reset(pos);
    if (BZ2InputStream::checkHeader(b, 16)) {
        uncompressionStream = new BZ2InputStream(m_input);
    } else {
        uncompressionStream = new GZipInputStream(m_input);
    }
    if (uncompressionStream->status() == Error) {
        m_error = uncompressionStream->error();
        m_status = Error;
        return;
    }
    cpio = new CpioInputStream(uncompressionStream);
    m_status = cpio->status();
}
RpmInputStream::~RpmInputStream() {
    if (uncompressionStream) {
        delete uncompressionStream;
    }
    if (cpio) {
        delete cpio;
    }
    if (headerinfo) {
        delete headerinfo;
    }
}
InputStream*
RpmInputStream::nextEntry() {
    if (m_status) return 0;
    InputStream* entry = cpio->nextEntry();
    m_status = cpio->status();
    if (m_status == Ok) {
        m_entryinfo = cpio->entryInfo();
    } else if (m_status == Error) {
        m_error = cpio->error();
    }
    return entry;
}
<commit_msg>if(bla) delete bla; => delete bla;<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "rpminputstream.h"
#include "cpioinputstream.h"
#include "gzipinputstream.h"
#include "bz2inputstream.h"
#include "subinputstream.h"
#include "textutils.h"

#include <list>

using namespace std;
using namespace Strigi;

class RpmInputStream::RpmHeaderInfo {
};
/**
 * RPM files as specified here:
 * http://www.freestandards.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/swinstall.html
 * and here:
 * http://www.rpm.org/max-rpm-snapshot/s1-rpm-file-format-rpm-file-format.html
 **/
bool
RpmInputStream::checkHeader(const char* data, int32_t datasize) {
    static const char unsigned magic[] = {0xed,0xab,0xee,0xdb,0x03,0x00};
    if (datasize < 6) return false;
    // this check could be more strict
    bool ok = memcmp(data, magic, 6) == 0;
    return ok;
}
RpmInputStream::RpmInputStream(InputStream* input)
        : SubStreamProvider(input), headerinfo(0) {
    uncompressionStream = 0;
    cpio = 0;

    // skip the header
    const char* b;
    // lead:96 bytes
    if (m_input->read(b, 96, 96) != 96) {
        m_status = Error;
        m_error = "File is too small to be an RPM file.";
        return;
    }

    // read signature
    const unsigned char headmagic[] = {0x8e,0xad,0xe8,0x01};
    if (m_input->read(b, 16, 16) != 16 || memcmp(b, headmagic, 4)!=0) {
        m_error = "m_error in signature\n";
        m_status = Error;
        return;
    }
    int32_t nindex = readBigEndianInt32(b+8);
    int32_t hsize = readBigEndianInt32(b+12);
    int32_t sz = nindex*16+hsize;
    if (sz%8) {
        sz+=8-sz%8;
    }
    if (m_input->read(b, sz, sz) != sz) {
        m_status = Error;
        m_error = "RPM seems to be truncated or corrupted.";
        return;
    }

    // read header
    if (m_input->read(b, 16, 16) != 16 || memcmp(b, headmagic, 4)!=0) {
        m_error = "m_error in header\n";
        m_status = Error;
        return;
    }
    nindex = readBigEndianInt32(b+8);
    hsize = readBigEndianInt32(b+12);
    int32_t size = nindex*16+hsize;
    if (m_input->read(b, size, size) != size) {
        m_error = "could not read header\n";
        m_status = Error;
        return;
    }
    for (int32_t i=0; i<nindex; ++i) {
        const unsigned char* e = (const unsigned char*)b+i*16;
        int32_t tag = readBigEndianInt32(e);
        int32_t type = readBigEndianInt32(e+4);
        int32_t offset = readBigEndianInt32(e+8);
        if (offset < 0 || offset >= hsize) {
            m_error = "invalid offset in header\n";
            m_status = Error;
            return;
        }
        int32_t count = readBigEndianInt32(e+12);
        int32_t end = hsize;
        if (i < nindex-1) {
            end = readBigEndianInt32(e+8+16);
        }
        if (end < offset) end = offset;
        if (end > hsize) end = hsize;
// TODO actually put the data into the objects so the analyzers can use them
/*        if (type == 6) {
            string s(b+nindex*16+offset, end-offset);
            printf("%s\n", s.c_str());
        } else if (type == 8 || type == 9) {
            list<string> v;
            // TODO handle string arrays
        }
        printf("%i\t%i\t%i\t%i\n", tag, type, offset, count);*/
    }

    int64_t pos = m_input->position();
    if (m_input->read(b, 16, 16) != 16) {
        m_error =  "could not read payload\n";
        m_status = Error;
        return;
    }
    m_input->reset(pos);
    if (BZ2InputStream::checkHeader(b, 16)) {
        uncompressionStream = new BZ2InputStream(m_input);
    } else {
        uncompressionStream = new GZipInputStream(m_input);
    }
    if (uncompressionStream->status() == Error) {
        m_error = uncompressionStream->error();
        m_status = Error;
        return;
    }
    cpio = new CpioInputStream(uncompressionStream);
    m_status = cpio->status();
}
RpmInputStream::~RpmInputStream() {
    delete uncompressionStream;
    delete cpio;
    delete headerinfo;
}
InputStream*
RpmInputStream::nextEntry() {
    if (m_status) return 0;
    InputStream* entry = cpio->nextEntry();
    m_status = cpio->status();
    if (m_status == Ok) {
        m_entryinfo = cpio->entryInfo();
    } else if (m_status == Error) {
        m_error = cpio->error();
    }
    return entry;
}
<|endoftext|>


<commit_before>/*******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 1       *
*                (c) 2006-2007 MGH, INRIA, USTL, UJF, CNRS                     *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Contact information: contact@sofa-framework.org                              *
*                                                                              *
* Authors: J. Allard, P-J. Bensoussan, G. Bousquet, S. Cotin, C. Duriez,       *
* H. Delingette, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza, M. Nesme,     *
* P. Neumann and F. Poyer                                                      *
*******************************************************************************/

#include <sofa/core/ObjectFactory.h>
#include <sofa/core/componentmodel/behavior/PairInteractionForceField.inl>
#include <sofa/component/forcefield/FrameSpringForceField.inl>
#include <sofa/defaulttype/RigidTypes.h>

namespace sofa
{

namespace core
{
namespace componentmodel
{
namespace behavior
{
template class PairInteractionForceField<Rigid3dTypes>;
template class PairInteractionForceField<Rigid3fTypes>;
}
}
}

namespace component
{

namespace forcefield
{

using namespace sofa::defaulttype;

SOFA_DECL_CLASS ( FrameSpringForceField );
// Register in the Factory

int FrameSpringForceFieldClass = core::RegisterObject ( "Springs for Flexibles" )
        .add< FrameSpringForceField<Rigid3dTypes> >()
        .add< FrameSpringForceField<Rigid3fTypes> >()
        ;

template class FrameSpringForceField<Rigid3dTypes>;
template class FrameSpringForceField<Rigid3fTypes>;

} // namespace forcefield

} // namespace component

} // namespace sofa
<commit_msg>r2357/sofa-dev : UPDATE: update float/double for FrameSpringForceField<commit_after>/*******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 1       *
*                (c) 2006-2007 MGH, INRIA, USTL, UJF, CNRS                     *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Contact information: contact@sofa-framework.org                              *
*                                                                              *
* Authors: J. Allard, P-J. Bensoussan, G. Bousquet, S. Cotin, C. Duriez,       *
* H. Delingette, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza, M. Nesme,     *
* P. Neumann and F. Poyer                                                      *
*******************************************************************************/

#include <sofa/core/ObjectFactory.h>
#include <sofa/core/componentmodel/behavior/PairInteractionForceField.inl>
#include <sofa/component/forcefield/FrameSpringForceField.inl>
#include <sofa/defaulttype/RigidTypes.h>

namespace sofa
{

namespace component
{

namespace forcefield
{

using namespace sofa::defaulttype;

SOFA_DECL_CLASS ( FrameSpringForceField );
// Register in the Factory

int FrameSpringForceFieldClass = core::RegisterObject ( "Springs for Flexibles" )
#ifndef SOFA_FLOAT
        .add< FrameSpringForceField<Rigid3dTypes> >()
#endif
#ifndef SOFA_DOUBLE
        .add< FrameSpringForceField<Rigid3fTypes> >()
#endif
        ;

#ifndef SOFA_FLOAT
template class FrameSpringForceField<Rigid3dTypes>;
#endif
#ifndef SOFA_DOUBLE
template class FrameSpringForceField<Rigid3fTypes>;
#endif

} // namespace forcefield

} // namespace component

} // namespace sofa
<|endoftext|>


<commit_before>/*
  ExtendOSC.cpp
  Created by Joshua Shinavier, 2014
  Released into the public domain.
*/

#include "ExtendOSC.h"

#ifdef BOARD_HAS_USB_SERIAL
#include <SLIPEncodedUSBSerial.h>
SLIPEncodedUSBSerial SLIPSerial(thisBoardsSerialUSB);
#else
#include <SLIPEncodedSerial.h>
SLIPEncodedSerial SLIPSerial(Serial);
#endif

ExtendOSC::ExtendOSC(const char *prefix)
{
    _addressPrefix = prefix;
}

void ExtendOSC::beginSerial() {
    // OSCuino: begin SLIPSerial just like Serial
    // set this as high as you can reliably run on your platform
    SLIPSerial.begin(115200);
/*
#if ARDUINO >= 100
    while(!Serial); // for Arduino Leonardo
#endif
*/
#if ARDUINO >= 100
#ifdef BOARD_HAS_USB_SERIAL
    while(!thisBoardsSerialUSB);
#else
    while(!Serial);
#endif
#endif
}

int ExtendOSC::receiveOSC(class OSCMessage &messageIn) {
    int done = SLIPSerial.endofPacket();
    int size;
    while ((size = SLIPSerial.available()) > 0) {
        while (size--) {
            int c = SLIPSerial.read();
            messageIn.fill(c);
            //sprintf(errstr, "received a byte: %d. bytes: %d, size: %d, hasError: %d", c, messageIn2.bytes(), messageIn2.size(), messageIn2.hasError());
            //sendInfo(errstr);
        }
    }
    return done || SLIPSerial.endofPacket();
}

int ExtendOSC::receiveOSCBundle(class OSCBundle &bundleIn) {
    int done = SLIPSerial.endofPacket();
    int size;
    while ((size = SLIPSerial.available()) > 0) {
        while (size--) {
            int c = SLIPSerial.read();
            bundleIn.fill(c);
        }
    }
    return done || SLIPSerial.endofPacket();
}

void ExtendOSC::sendOSC(class OSCMessage &messageOut) {
    SLIPSerial.beginPacket();
    messageOut.send(SLIPSerial); // send the bytes to the SLIP stream
    SLIPSerial.endPacket(); // mark the end of the OSC Packet
    messageOut.empty(); // free the space occupied by the message
}

void ExtendOSC::sendInfo(const char *msg, ...)
{
    va_list argptr;
    va_start(argptr, msg);
    vsprintf(_messageBuffer, msg, argptr);
    va_end(argptr);

    sprintf(_addressBuffer, "%s/info", _addressPrefix);

    OSCMessage m(_addressBuffer);
    m.add(_messageBuffer);
    sendOSC(m);
}

void ExtendOSC::sendError(const char *msg, ...)
{
    va_list argptr;
    va_start(argptr, msg);
    vsprintf(_messageBuffer, msg, argptr);
    va_end(argptr);

    sprintf(_addressBuffer, "%s/error", _addressPrefix);

    OSCMessage m(_addressBuffer);
    m.add(_messageBuffer);
    sendOSC(m);
}

const char *BUFFER_FULL_msg = "BUFFER_FULL",
    *INVALID_OSC_msg = "INVALID_OSC",
    *ALLOCFAILED_msg = "ALLOCFAILED",
    *INDEX_OUT_OF_BOUNDS_msg = "INDEX_OUT_OF_BOUNDS",
    *unknown_msg = "unknown";

void ExtendOSC::sendOSCError(OSCErrorCode code) {
    const char *name;

    switch(code) {
      case BUFFER_FULL:
          name = BUFFER_FULL_msg;
          break;
      case INVALID_OSC:
         name = INVALID_OSC_msg;
         break;
      case ALLOCFAILED:
         name = ALLOCFAILED_msg;
         break;
      case INDEX_OUT_OF_BOUNDS:
         name = INDEX_OUT_OF_BOUNDS_msg;
         break;
      default:
         name = unknown_msg;
    }

    sendError("OSC message hasError (error type: %s)", name);
}

void ExtendOSC::sendOSCMessageError(class OSCMessage &message) {
    OSCErrorCode code = message.getError();
    sendOSCError(code);
}

void ExtendOSC::sendOSCBundleError(class OSCBundle &bundle) {
    OSCErrorCode code = bundle.getError();
    sendOSCError(code);
}

int ExtendOSC::validArgs(class OSCMessage &m, int totalExpected) {
    if (totalExpected != m.size()) {
        sendError("got %d argument(s), expected %d", m.size(), totalExpected);
        return 0;
    } else {
        return 1;
    }
}<commit_msg>Keep OSC messages from Arduino below the Bluetooth SPP limit of 128 bytes<commit_after>/*
  ExtendOSC.cpp
  Created by Joshua Shinavier, 2014
  Released into the public domain.
*/

#include "ExtendOSC.h"

#ifdef BOARD_HAS_USB_SERIAL
#include <SLIPEncodedUSBSerial.h>
SLIPEncodedUSBSerial SLIPSerial(thisBoardsSerialUSB);
#else
#include <SLIPEncodedSerial.h>
SLIPEncodedSerial SLIPSerial(Serial);
#endif

ExtendOSC::ExtendOSC(const char *prefix)
{
    _addressPrefix = prefix;
}

void ExtendOSC::beginSerial() {
    // OSCuino: begin SLIPSerial just like Serial
    // set this as high as you can reliably run on your platform
    SLIPSerial.begin(115200);
/*
#if ARDUINO >= 100
    while(!Serial); // for Arduino Leonardo
#endif
*/
#if ARDUINO >= 100
#ifdef BOARD_HAS_USB_SERIAL
    while(!thisBoardsSerialUSB);
#else
    while(!Serial);
#endif
#endif
}

int ExtendOSC::receiveOSC(class OSCMessage &messageIn) {
    int done = SLIPSerial.endofPacket();
    int size;
    while ((size = SLIPSerial.available()) > 0) {
        while (size--) {
            int c = SLIPSerial.read();
            messageIn.fill(c);
            //sprintf(errstr, "received a byte: %d. bytes: %d, size: %d, hasError: %d", c, messageIn2.bytes(), messageIn2.size(), messageIn2.hasError());
            //sendInfo(errstr);
        }
    }
    return done || SLIPSerial.endofPacket();
}

int ExtendOSC::receiveOSCBundle(class OSCBundle &bundleIn) {
    int done = SLIPSerial.endofPacket();
    int size;
    while ((size = SLIPSerial.available()) > 0) {
        while (size--) {
            int c = SLIPSerial.read();
            bundleIn.fill(c);
        }
    }
    return done || SLIPSerial.endofPacket();
}

void ExtendOSC::sendOSC(class OSCMessage &messageOut) {
    // 128 bytes is the maximum payload capacity of Bluetooth SPP (Serial Port Profile)
    if (messageOut.bytes() > 128) {
        sendError("message is %d bytes long, exceeding limit of 128 bytes")
    }

    SLIPSerial.beginPacket();
    messageOut.send(SLIPSerial); // send the bytes to the SLIP stream
    SLIPSerial.endPacket(); // mark the end of the OSC Packet
    messageOut.empty(); // free the space occupied by the message
}

void ExtendOSC::sendInfo(const char *msg, ...)
{
    va_list argptr;
    va_start(argptr, msg);
    vsprintf(_messageBuffer, msg, argptr);
    va_end(argptr);

    sprintf(_addressBuffer, "%s/info", _addressPrefix);

    OSCMessage m(_addressBuffer);
    m.add(_messageBuffer);
    sendOSC(m);
}

void ExtendOSC::sendError(const char *msg, ...)
{
    va_list argptr;
    va_start(argptr, msg);
    vsprintf(_messageBuffer, msg, argptr);
    va_end(argptr);

    sprintf(_addressBuffer, "%s/error", _addressPrefix);

    OSCMessage m(_addressBuffer);
    m.add(_messageBuffer);
    sendOSC(m);
}

const char *BUFFER_FULL_msg = "BUFFER_FULL",
    *INVALID_OSC_msg = "INVALID_OSC",
    *ALLOCFAILED_msg = "ALLOCFAILED",
    *INDEX_OUT_OF_BOUNDS_msg = "INDEX_OUT_OF_BOUNDS",
    *unknown_msg = "unknown";

void ExtendOSC::sendOSCError(OSCErrorCode code) {
    const char *name;

    switch(code) {
      case BUFFER_FULL:
          name = BUFFER_FULL_msg;
          break;
      case INVALID_OSC:
         name = INVALID_OSC_msg;
         break;
      case ALLOCFAILED:
         name = ALLOCFAILED_msg;
         break;
      case INDEX_OUT_OF_BOUNDS:
         name = INDEX_OUT_OF_BOUNDS_msg;
         break;
      default:
         name = unknown_msg;
    }

    sendError("OSC message hasError (error type: %s)", name);
}

void ExtendOSC::sendOSCMessageError(class OSCMessage &message) {
    OSCErrorCode code = message.getError();
    sendOSCError(code);
}

void ExtendOSC::sendOSCBundleError(class OSCBundle &bundle) {
    OSCErrorCode code = bundle.getError();
    sendOSCError(code);
}

int ExtendOSC::validArgs(class OSCMessage &m, int totalExpected) {
    if (totalExpected != m.size()) {
        sendError("got %d argument(s), expected %d", m.size(), totalExpected);
        return 0;
    } else {
        return 1;
    }
}<|endoftext|>


<commit_before>#include "instanciate.h"

using namespace Yuni;

namespace ny
{
namespace Pass
{
namespace Instanciate
{

	namespace {

	void pragmaBodyStart(SequenceBuilder& seq)
	{
		assert(seq.frame != nullptr);
		assert(not seq.signatureOnly);
		assert(seq.codeGenerationLock == 0 and "any good reason to not generate code ?");
		assert(seq.out != nullptr and "no output IR sequence");

		auto& frame = *seq.frame;
		auto& atom = frame.atom;
		if (not atom.isFunction())
			return;

		bool generateCode = seq.canGenerateCode();
		uint32_t count = atom.parameters.size();

		atom.parameters.each([&](uint32_t i, const AnyString& name, const Vardef& vardef)
		{
			// lvid for the given parameter
			uint32_t lvid  = i + 1 + 1; // 1: return type, 2: first parameter
			assert(lvid < frame.lvids.size());
			// Obviously, the parameters are not synthetic objects
			// but real variables
			frame.lvids[lvid].synthetic = false;

			// Parameters Deep copy (if required)
			if (name[0] != '^')
			{
				// normal input parameter (not captured - does not start with '^')
				// clone it if necessary (only non-ref parameters)
				if (not seq.cdeftable.classdef(vardef.clid).qualifiers.ref)
				{
					if (debugmode and generateCode)
						seq.out->emitComment(String{"----- deep copy parameter "} << i << " aka " << name);
					// a register has already been reserved for cloning parameters
					uint32_t clone = 2 + count + i; // 1: return type, 2: first parameter
					assert(clone < frame.lvids.size());
					// the new value is not synthetic
					frame.lvids[clone].synthetic = false;
					bool r = seq.instanciateAssignment(frame, clone, lvid, false, false, true);
					if (unlikely(not r))
						frame.invalidate(clone);
					if (seq.canBeAcquired(lvid))
					{
						frame.lvids[lvid].autorelease = true;
						frame.lvids[clone].autorelease = false;
					}
					if (generateCode)
					{
						seq.out->emitStore(lvid, clone); // register swap
						if (debugmode)
							seq.out->emitComment("--\n");
					}
				}
			}
		});
		// generating some code on the fly
		if (atom.isSpecial() /*ctor, operators...*/ and generateCode)
		{
			// variables initialization (for a ctor)
			if (seq.generateClassVarsAutoInit)
			{
				seq.generateClassVarsAutoInit = false;
				seq.generateMemberVarDefaultInitialization();
			}
			// variables destruction (for dtor)
			if (seq.generateClassVarsAutoRelease)
			{
				seq.generateClassVarsAutoRelease = false;
				seq.generateMemberVarDefaultDispose();
			}
			// variables cloning (copy a ctor)
			if (seq.generateClassVarsAutoClone)
			{
				seq.generateClassVarsAutoClone = false;
				seq.generateMemberVarDefaultClone();
			}
		}
	}

	void pragmaCodegen(SequenceBuilder& seq, bool onoff)
	{
		auto& refcount = seq.codeGenerationLock;
		if (onoff)
		{
			if (refcount > 0) // re-enable code generation
				--refcount;
		}
		else
			++refcount;
	}

	void pragmaBlueprintSize(SequenceBuilder& seq, uint32_t opcodeCount)
	{
		if (0 == seq.layerDepthLimit)
		{
			// ignore the current blueprint
			//*cursor += operands.value.blueprintsize;
			assert(seq.frame != nullptr);
			assert(seq.frame->offsetOpcodeBlueprint != (uint32_t) -1);
			auto startOffset = seq.frame->offsetOpcodeBlueprint;
			if (unlikely(opcodeCount < 3))
				return (void) (ice() << "invalid blueprint size when instanciating atom");

			// goto the end of the blueprint
			// -2: the final 'end' opcode must be interpreted
			*seq.cursor = &seq.currentSequence.at(startOffset + opcodeCount - 1 - 1);
		}
	}

	void pragmaShortcircuitMutateToBool(SequenceBuilder& seq, const IR::ISA::Operand<IR::ISA::Op::pragma>& operands)
	{
		uint32_t lvid = operands.value.shortcircuitMutate.lvid;
		uint32_t source = operands.value.shortcircuitMutate.source;

		seq.frame->lvids[lvid].synthetic = false;

		if (true)
		{
			auto& instr = *(*seq.cursor - 1);
			assert(instr.opcodes[0] == static_cast<uint32_t>(IR::ISA::Op::stackalloc));
			uint32_t sizeoflvid = instr.to<IR::ISA::Op::stackalloc>().lvid;

			// sizeof
			auto& atombool = *(seq.cdeftable.atoms().core.object[nyt_bool]);
			seq.out->emitSizeof(sizeoflvid, atombool.atomid);

			auto& opc = seq.cdeftable.substitute(lvid);
			opc.mutateToAtom(&atombool);
			opc.qualifiers.ref = true;
			// ALLOC: memory allocation of the new temporary object
			seq.out->emitMemalloc(lvid, sizeoflvid);
			seq.out->emitRef(lvid);
			seq.frame->lvids[lvid].autorelease = true;
			// reset the internal value of the object
			seq.out->emitFieldset(source, /*self*/lvid, 0); // builtin
		}
		else
			seq.out->emitStore(lvid, source);
	}

	} // anonymous namespace

	void SequenceBuilder::visit(const IR::ISA::Operand<IR::ISA::Op::pragma>& operands)
	{
		assert(static_cast<uint32_t>(operands.pragma) < IR::ISA::PragmaCount);
		auto pragma = static_cast<IR::ISA::Pragma>(operands.pragma);
		switch (pragma)
		{
			case IR::ISA::Pragma::codegen:
			{
				pragmaCodegen(*this, operands.value.codegen != 0);
				break;
			}
			case IR::ISA::Pragma::bodystart:
			{
				// In 'signature only' mode, we only care about the
				// parameter user types. Everything from this point in unrelevant
				if (signatureOnly)
					currentSequence.invalidateCursor(*cursor);
				else
					pragmaBodyStart(*this); // params deep copy, implicit var auto-init...
				break;
			}
			case IR::ISA::Pragma::blueprintsize:
			{
				pragmaBlueprintSize(*this, operands.value.blueprintsize);
				break;
			}
			case IR::ISA::Pragma::visibility:
			{
				assert(frame != nullptr);
				break;
			}
			case IR::ISA::Pragma::shortcircuitOpNopOffset:
			{
				shortcircuit.label = operands.value.shortcircuitMetadata.label;
				break;
			}
			case IR::ISA::Pragma::shortcircuitMutateToBool:
			{
				pragmaShortcircuitMutateToBool(*this, operands);
				break;
			}
			case IR::ISA::Pragma::synthetic:
			{
				uint32_t lvid = operands.value.synthetic.lvid;
				bool onoff = (operands.value.synthetic.onoff != 0);
				frame->lvids[lvid].synthetic = onoff;
				break;
			}
			case IR::ISA::Pragma::suggest:
			case IR::ISA::Pragma::builtinalias:
			case IR::ISA::Pragma::shortcircuit:
			case IR::ISA::Pragma::unknown:
				break;
		}
	}

} // namespace Instanciate
} // namespace Pass
} // namespace ny
<commit_msg>added param type check<commit_after>#include "instanciate.h"

using namespace Yuni;

namespace ny
{
namespace Pass
{
namespace Instanciate
{

	namespace {

	void pragmaBodyStart(SequenceBuilder& seq)
	{
		assert(seq.frame != nullptr);
		assert(not seq.signatureOnly);
		assert(seq.codeGenerationLock == 0 and "any good reason to not generate code ?");
		assert(seq.out != nullptr and "no output IR sequence");

		auto& frame = *seq.frame;
		auto& atom = frame.atom;
		if (not atom.isFunction())
			return;

		bool generateCode = seq.canGenerateCode();
		uint32_t count = atom.parameters.size();

		atom.parameters.each([&](uint32_t i, const AnyString& name, const Vardef& vardef)
		{
			// lvid for the given parameter
			uint32_t lvid  = i + 1 + 1; // 1: return type, 2: first parameter
			assert(lvid < frame.lvids.size());
			// Obviously, the parameters are not synthetic objects
			// but real variables
			frame.lvids[lvid].synthetic = false;

			// Parameters Deep copy (if required)
			auto& cdef = seq.cdeftable.classdef(vardef.clid);
			if (name[0] != '^')
			{
				// normal input parameter (not captured - does not start with '^')
				// clone it if necessary (only non-ref parameters)
				if (not cdef.qualifiers.ref)
				{
					if (debugmode and generateCode)
						seq.out->emitComment(String{"----- deep copy parameter "} << i << " aka " << name);
					// a register has already been reserved for cloning parameters
					uint32_t clone = 2 + count + i; // 1: return type, 2: first parameter
					assert(clone < frame.lvids.size());
					// the new value is not synthetic
					frame.lvids[clone].synthetic = false;
					bool r = seq.instanciateAssignment(frame, clone, lvid, false, false, true);
					if (unlikely(not r))
						frame.invalidate(clone);
					if (seq.canBeAcquired(lvid))
					{
						frame.lvids[lvid].autorelease = true;
						frame.lvids[clone].autorelease = false;
					}
					if (generateCode)
					{
						seq.out->emitStore(lvid, clone); // register swap
						if (debugmode)
							seq.out->emitComment("--\n");
					}
				}
			}
			if (not cdef.isBuiltinOrVoid())
			{
				auto* paramatom = seq.cdeftable.findClassdefAtom(cdef);
				if (unlikely(!paramatom))
				{
					frame.invalidate(lvid);
					ice() << "invalid parameter type " << i << " for " << atom.caption(seq.cdeftable);
				}
			}
		});
		// generating some code on the fly
		if (atom.isSpecial() /*ctor, operators...*/ and generateCode)
		{
			// variables initialization (for a ctor)
			if (seq.generateClassVarsAutoInit)
			{
				seq.generateClassVarsAutoInit = false;
				seq.generateMemberVarDefaultInitialization();
			}
			// variables destruction (for dtor)
			if (seq.generateClassVarsAutoRelease)
			{
				seq.generateClassVarsAutoRelease = false;
				seq.generateMemberVarDefaultDispose();
			}
			// variables cloning (copy a ctor)
			if (seq.generateClassVarsAutoClone)
			{
				seq.generateClassVarsAutoClone = false;
				seq.generateMemberVarDefaultClone();
			}
		}
	}

	void pragmaCodegen(SequenceBuilder& seq, bool onoff)
	{
		auto& refcount = seq.codeGenerationLock;
		if (onoff)
		{
			if (refcount > 0) // re-enable code generation
				--refcount;
		}
		else
			++refcount;
	}

	void pragmaBlueprintSize(SequenceBuilder& seq, uint32_t opcodeCount)
	{
		if (0 == seq.layerDepthLimit)
		{
			// ignore the current blueprint
			//*cursor += operands.value.blueprintsize;
			assert(seq.frame != nullptr);
			assert(seq.frame->offsetOpcodeBlueprint != (uint32_t) -1);
			auto startOffset = seq.frame->offsetOpcodeBlueprint;
			if (unlikely(opcodeCount < 3))
				return (void) (ice() << "invalid blueprint size when instanciating atom");

			// goto the end of the blueprint
			// -2: the final 'end' opcode must be interpreted
			*seq.cursor = &seq.currentSequence.at(startOffset + opcodeCount - 1 - 1);
		}
	}

	void pragmaShortcircuitMutateToBool(SequenceBuilder& seq, const IR::ISA::Operand<IR::ISA::Op::pragma>& operands)
	{
		uint32_t lvid = operands.value.shortcircuitMutate.lvid;
		uint32_t source = operands.value.shortcircuitMutate.source;

		seq.frame->lvids[lvid].synthetic = false;

		if (true)
		{
			auto& instr = *(*seq.cursor - 1);
			assert(instr.opcodes[0] == static_cast<uint32_t>(IR::ISA::Op::stackalloc));
			uint32_t sizeoflvid = instr.to<IR::ISA::Op::stackalloc>().lvid;

			// sizeof
			auto& atombool = *(seq.cdeftable.atoms().core.object[nyt_bool]);
			seq.out->emitSizeof(sizeoflvid, atombool.atomid);

			auto& opc = seq.cdeftable.substitute(lvid);
			opc.mutateToAtom(&atombool);
			opc.qualifiers.ref = true;
			// ALLOC: memory allocation of the new temporary object
			seq.out->emitMemalloc(lvid, sizeoflvid);
			seq.out->emitRef(lvid);
			seq.frame->lvids[lvid].autorelease = true;
			// reset the internal value of the object
			seq.out->emitFieldset(source, /*self*/lvid, 0); // builtin
		}
		else
			seq.out->emitStore(lvid, source);
	}

	} // anonymous namespace

	void SequenceBuilder::visit(const IR::ISA::Operand<IR::ISA::Op::pragma>& operands)
	{
		assert(static_cast<uint32_t>(operands.pragma) < IR::ISA::PragmaCount);
		auto pragma = static_cast<IR::ISA::Pragma>(operands.pragma);
		switch (pragma)
		{
			case IR::ISA::Pragma::codegen:
			{
				pragmaCodegen(*this, operands.value.codegen != 0);
				break;
			}
			case IR::ISA::Pragma::bodystart:
			{
				// In 'signature only' mode, we only care about the
				// parameter user types. Everything from this point in unrelevant
				if (signatureOnly)
					currentSequence.invalidateCursor(*cursor);
				else
					pragmaBodyStart(*this); // params deep copy, implicit var auto-init...
				break;
			}
			case IR::ISA::Pragma::blueprintsize:
			{
				pragmaBlueprintSize(*this, operands.value.blueprintsize);
				break;
			}
			case IR::ISA::Pragma::visibility:
			{
				assert(frame != nullptr);
				break;
			}
			case IR::ISA::Pragma::shortcircuitOpNopOffset:
			{
				shortcircuit.label = operands.value.shortcircuitMetadata.label;
				break;
			}
			case IR::ISA::Pragma::shortcircuitMutateToBool:
			{
				pragmaShortcircuitMutateToBool(*this, operands);
				break;
			}
			case IR::ISA::Pragma::synthetic:
			{
				uint32_t lvid = operands.value.synthetic.lvid;
				bool onoff = (operands.value.synthetic.onoff != 0);
				frame->lvids[lvid].synthetic = onoff;
				break;
			}
			case IR::ISA::Pragma::suggest:
			case IR::ISA::Pragma::builtinalias:
			case IR::ISA::Pragma::shortcircuit:
			case IR::ISA::Pragma::unknown:
				break;
		}
	}

} // namespace Instanciate
} // namespace Pass
} // namespace ny
<|endoftext|>