<commit_before>/* Copyright 2014 Open Source Robotics Foundation, 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.
 */

#ifndef RCLCPP_RCLCPP_CLIENT_HPP_
#define RCLCPP_RCLCPP_CLIENT_HPP_

#include <memory>

#include <ros_middleware_interface/functions.h>
#include <ros_middleware_interface/handles.h>

#include <rclcpp/utilities.hpp>
#include <rclcpp/macros.hpp>
#include <future>
#include <map>
#include <utility>

namespace rclcpp
{

// Forward declaration for friend statement
namespace node {class Node;}

namespace client
{

class ClientBase
{
  friend class rclcpp::executor::Executor;
public:
  RCLCPP_MAKE_SHARED_DEFINITIONS(ClientBase);

  ClientBase(
    ros_middleware_interface::ClientHandle client_handle,
    std::string &service_name)
    : client_handle_(client_handle), service_name_(service_name)
  {}

  std::string get_service_name()
  {
    return this->service_name_;
  }

  ros_middleware_interface::ClientHandle get_client_handle()
  {
    return this->client_handle_;
  }

  virtual std::shared_ptr<void> create_response() = 0;
  virtual std::shared_ptr<void> create_request_header() = 0;
  virtual void handle_response(std::shared_ptr<void> &response, std::shared_ptr<void> &req_id) = 0;

private:
  RCLCPP_DISABLE_COPY(ClientBase);

  ros_middleware_interface::ClientHandle client_handle_;
  std::string service_name_;

};

template<typename ServiceT>
class Client : public ClientBase
{
public:
  typedef std::promise<typename ServiceT::Response::Ptr> Promise;
  typedef std::shared_ptr<Promise> SharedPromise;
  typedef std::shared_future<typename ServiceT::Response::Ptr> SharedFuture;

  typedef std::function<void(SharedFuture)> CallbackType;

  RCLCPP_MAKE_SHARED_DEFINITIONS(Client);

  Client(ros_middleware_interface::ClientHandle client_handle,
         std::string& service_name)
    : ClientBase(client_handle, service_name)
  {}

  std::shared_ptr<void> get_response(int64_t sequence_number)
  {
    auto pair = this->pending_requests_[sequence_number];
    return pair.second;
  }

  std::shared_ptr<void> create_response()
  {
    return std::shared_ptr<void>(new typename ServiceT::Response());
  }

  std::shared_ptr<void> create_request_header()
  {
    return std::shared_ptr<void>(new ros_middleware_interface::RequestId());
  }

  void handle_response(std::shared_ptr<void> &response, std::shared_ptr<void> &req_id)
  {
    auto typed_req_id = std::static_pointer_cast<ros_middleware_interface::RequestId>(req_id);
    auto typed_response = std::static_pointer_cast<typename ServiceT::Response>(response);
    int64_t sequence_number = typed_req_id->sequence_number;
    auto tuple = this->pending_requests_[sequence_number];
    auto call_promise = std::get<0>(tuple);
    auto callback = std::get<1>(tuple);
    auto future = std::get<2>(tuple);
    this->pending_requests_.erase(sequence_number);
    call_promise->set_value(typed_response);
    callback(future);
  }

  SharedFuture async_send_request(
    typename ServiceT::Request::Ptr &request,
    typename ServiceT::Response::Ptr &response)
  {
    return async_send_request(request, response, [] (SharedFuture f) { });
  }

  SharedFuture async_send_request(
    typename ServiceT::Request::Ptr &request,
    typename ServiceT::Response::Ptr &response,
    CallbackType cb)
  {
    int64_t sequence_number = ::ros_middleware_interface::send_request(get_client_handle(), request.get());

    SharedPromise call_promise = std::make_shared<Promise>();
    SharedFuture f(call_promise->get_future());
    pending_requests_[sequence_number] = std::make_tuple(call_promise, cb, f);
    return f;
  }

private:
  RCLCPP_DISABLE_COPY(Client);

  std::map<int64_t, std::tuple<SharedPromise, CallbackType, SharedFuture> > pending_requests_;
};

} /* namespace client */
} /* namespace rclcpp */

#endif /* RCLCPP_RCLCPP_CLIENT_HPP_ */
<commit_msg>Removed unused response object<commit_after>/* Copyright 2014 Open Source Robotics Foundation, 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.
 */

#ifndef RCLCPP_RCLCPP_CLIENT_HPP_
#define RCLCPP_RCLCPP_CLIENT_HPP_

#include <memory>

#include <ros_middleware_interface/functions.h>
#include <ros_middleware_interface/handles.h>

#include <rclcpp/utilities.hpp>
#include <rclcpp/macros.hpp>
#include <future>
#include <map>
#include <utility>

namespace rclcpp
{

// Forward declaration for friend statement
namespace node {class Node;}

namespace client
{

class ClientBase
{
  friend class rclcpp::executor::Executor;
public:
  RCLCPP_MAKE_SHARED_DEFINITIONS(ClientBase);

  ClientBase(
    ros_middleware_interface::ClientHandle client_handle,
    std::string &service_name)
    : client_handle_(client_handle), service_name_(service_name)
  {}

  std::string get_service_name()
  {
    return this->service_name_;
  }

  ros_middleware_interface::ClientHandle get_client_handle()
  {
    return this->client_handle_;
  }

  virtual std::shared_ptr<void> create_response() = 0;
  virtual std::shared_ptr<void> create_request_header() = 0;
  virtual void handle_response(std::shared_ptr<void> &response, std::shared_ptr<void> &req_id) = 0;

private:
  RCLCPP_DISABLE_COPY(ClientBase);

  ros_middleware_interface::ClientHandle client_handle_;
  std::string service_name_;

};

template<typename ServiceT>
class Client : public ClientBase
{
public:
  typedef std::promise<typename ServiceT::Response::Ptr> Promise;
  typedef std::shared_ptr<Promise> SharedPromise;
  typedef std::shared_future<typename ServiceT::Response::Ptr> SharedFuture;

  typedef std::function<void(SharedFuture)> CallbackType;

  RCLCPP_MAKE_SHARED_DEFINITIONS(Client);

  Client(ros_middleware_interface::ClientHandle client_handle,
         std::string& service_name)
    : ClientBase(client_handle, service_name)
  {}

  std::shared_ptr<void> create_response()
  {
    return std::shared_ptr<void>(new typename ServiceT::Response());
  }

  std::shared_ptr<void> create_request_header()
  {
    return std::shared_ptr<void>(new ros_middleware_interface::RequestId());
  }

  void handle_response(std::shared_ptr<void> &response, std::shared_ptr<void> &req_id)
  {
    auto typed_req_id = std::static_pointer_cast<ros_middleware_interface::RequestId>(req_id);
    auto typed_response = std::static_pointer_cast<typename ServiceT::Response>(response);
    int64_t sequence_number = typed_req_id->sequence_number;
    auto tuple = this->pending_requests_[sequence_number];
    auto call_promise = std::get<0>(tuple);
    auto callback = std::get<1>(tuple);
    auto future = std::get<2>(tuple);
    this->pending_requests_.erase(sequence_number);
    call_promise->set_value(typed_response);
    callback(future);
  }

  SharedFuture async_send_request(
    typename ServiceT::Request::Ptr &request)
  {
    return async_send_request(request, [] (SharedFuture f) { });
  }

  SharedFuture async_send_request(
    typename ServiceT::Request::Ptr &request,
    CallbackType cb)
  {
    int64_t sequence_number = ::ros_middleware_interface::send_request(get_client_handle(), request.get());

    SharedPromise call_promise = std::make_shared<Promise>();
    SharedFuture f(call_promise->get_future());
    pending_requests_[sequence_number] = std::make_tuple(call_promise, cb, f);
    return f;
  }

private:
  RCLCPP_DISABLE_COPY(Client);

  std::map<int64_t, std::tuple<SharedPromise, CallbackType, SharedFuture> > pending_requests_;
};

} /* namespace client */
} /* namespace rclcpp */

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


<commit_before>/*
 *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  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
 */
/*
 * @file       crypto-init.cpp
 * @author     Maciej Karpiuk (m.karpiuk2@samsung.com)
 * @version    1.0
 */

#include "crypto-init.h"
#include <mutex>
#include <openssl/evp.h>

namespace CKM {

namespace {
bool isCryptoInitialized = false;
std::mutex cryptoInitMutex;
}

void initCryptoLib() {
    std::lock_guard<std::mutex> lock(cryptoInitMutex);
    if(!isCryptoInitialized)
    {
        isCryptoInitialized = true;
        OpenSSL_add_all_ciphers();
        OpenSSL_add_all_algorithms();
        OpenSSL_add_all_digests();
    }
}

} /* namespace CKM */
<commit_msg>Optimize openssl initialization<commit_after>/*
 *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  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
 */
/*
 * @file       crypto-init.cpp
 * @author     Maciej Karpiuk (m.karpiuk2@samsung.com)
 * @version    1.0
 */

#include "crypto-init.h"
#include <mutex>
#include <openssl/evp.h>
#include <atomic>

namespace CKM {

namespace {
std::mutex cryptoInitMutex;

void initOpenSSL();

typedef void(*initFnPtr)();

// has to be atomic as storing function pointer is not an atomic operation on armv7l
std::atomic<initFnPtr> initFn (&initOpenSSL);

void initEmpty() {}

void initOpenSSL() {
    // DCLP
    std::lock_guard<std::mutex> lock(cryptoInitMutex);
    /*
     * We don't care about memory ordering here. Current thread will order it correctly and for
     * other threads only store matters. Also only one thread can be here at once because of lock.
     */
    if(initFn.load(std::memory_order_relaxed) != &initEmpty)
    {
        OpenSSL_add_all_ciphers();
        OpenSSL_add_all_algorithms();
        OpenSSL_add_all_digests();

        /*
         * Synchronizes with load. Everything that happened before this store in this thread is
         * visible to everything that happens after load in another thread. We switch to an empty
         * function here.
         */
        initFn.store(&initEmpty, std::memory_order_release);
    }
}

} // namespace anonymous

void initCryptoLib() {
    /*
     * Synchronizes with store. Everything that happened before store in another thread will be
     * visible in this thread after load.
     */
    initFn.load(std::memory_order_acquire)();
}

} /* namespace CKM */
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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/common/chrome_plugin_lib.h"

#include "base/command_line.h"
#include "base/hash_tables.h"
#include "base/histogram.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/perftimer.h"
#include "base/thread.h"
#if defined(OS_WIN)
#include "base/registry.h"
#endif
#include "base/string_util.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/chrome_paths.h"
#include "webkit/glue/plugins/plugin_list.h"

using base::TimeDelta;

// TODO(port): revisit when plugins happier
#if defined(OS_WIN)
const TCHAR ChromePluginLib::kRegistryChromePlugins[] =
    _T("Software\\Google\\Chrome\\Plugins");
static const TCHAR kRegistryLoadOnStartup[] = _T("LoadOnStartup");
static const TCHAR kRegistryPath[] = _T("Path");
#endif

typedef base::hash_map<FilePath, scoped_refptr<ChromePluginLib> >
    PluginMap;

// A map of all the instantiated plugins.
static PluginMap* g_loaded_libs;

// The thread plugins are loaded and used in, lazily initialized upon
// the first creation call.
static PlatformThreadId g_plugin_thread_id = 0;
static MessageLoop* g_plugin_thread_loop = NULL;

#ifdef GEARS_STATIC_LIB
// defined in gears/base/chrome/module_cr.cc
CPError STDCALL Gears_CP_Initialize(CPID id, const CPBrowserFuncs *bfuncs,
                                    CPPluginFuncs *pfuncs);
#endif

static bool IsSingleProcessMode() {
  // We don't support ChromePlugins in single-process mode.
  return CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
}

// static
bool ChromePluginLib::IsInitialized() {
  return (g_loaded_libs != NULL);
}

// static
ChromePluginLib* ChromePluginLib::Create(const FilePath& filename,
                                         const CPBrowserFuncs* bfuncs) {
  // Keep a map of loaded plugins to ensure we only load each library once.
  if (!g_loaded_libs) {
    g_loaded_libs = new PluginMap();
    g_plugin_thread_id = PlatformThread::CurrentId();
    g_plugin_thread_loop = MessageLoop::current();
  }
  DCHECK(IsPluginThread());

  PluginMap::const_iterator iter = g_loaded_libs->find(filename);
  if (iter != g_loaded_libs->end())
    return iter->second;

  scoped_refptr<ChromePluginLib> plugin(new ChromePluginLib(filename));
  if (!plugin->CP_Initialize(bfuncs))
    return NULL;

  (*g_loaded_libs)[filename] = plugin;
  return plugin;
}

// static
ChromePluginLib* ChromePluginLib::Find(const FilePath& filename) {
  if (g_loaded_libs) {
    PluginMap::const_iterator iter = g_loaded_libs->find(filename);
    if (iter != g_loaded_libs->end())
      return iter->second;
  }
  return NULL;
}

// static
void ChromePluginLib::Destroy(const FilePath& filename) {
  DCHECK(g_loaded_libs);
  PluginMap::iterator iter = g_loaded_libs->find(filename);
  if (iter != g_loaded_libs->end()) {
    iter->second->Unload();
    g_loaded_libs->erase(iter);
  }
}

// static
bool ChromePluginLib::IsPluginThread() {
  return PlatformThread::CurrentId() == g_plugin_thread_id;
}

// static
MessageLoop* ChromePluginLib::GetPluginThreadLoop() {
  return g_plugin_thread_loop;
}

// static
void ChromePluginLib::RegisterPluginsWithNPAPI() {
  // We don't support ChromePlugins in single-process mode.
  if (IsSingleProcessMode())
    return;

  FilePath path;
  if (!PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
    return;
  // Note: we can only access the NPAPI list because the PluginService has done
  // the locking for us.  We should not touch it anywhere else.
  NPAPI::PluginList::AddExtraPluginPath(path);
}

static void LogPluginLoadTime(const TimeDelta &time) {
  UMA_HISTOGRAM_TIMES("Gears.LoadTime", time);
}

// static
void ChromePluginLib::LoadChromePlugins(const CPBrowserFuncs* bfuncs) {
  static bool loaded = false;
  if (loaded)
    return;
  loaded = true;

  // We don't support ChromePlugins in single-process mode.
  if (IsSingleProcessMode())
    return;

  FilePath path;
  if (!PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
    return;

  PerfTimer timer;
  ChromePluginLib::Create(path, bfuncs);
  LogPluginLoadTime(timer.Elapsed());

  // TODO(mpcomplete): disabled loading of plugins from the registry until we
  // phase out registry keys from the gears installer.
#if 0
  for (RegistryKeyIterator iter(HKEY_CURRENT_USER, kRegistryChromePlugins);
       iter.Valid(); ++iter) {
    // Use the registry to gather plugin across the file system.
    std::wstring reg_path = kRegistryChromePlugins;
    reg_path.append(L"\\");
    reg_path.append(iter.Name());
    RegKey key(HKEY_CURRENT_USER, reg_path.c_str());

    DWORD is_persistent;
    if (key.ReadValueDW(kRegistryLoadOnStartup, &is_persistent) &&
        is_persistent) {
      std::wstring path;
      if (key.ReadValue(kRegistryPath, &path)) {
        ChromePluginLib::Create(path, bfuncs);
      }
    }
  }
#endif
}

// static
void ChromePluginLib::UnloadAllPlugins() {
  if (g_loaded_libs) {
    PluginMap::iterator it;
    for (PluginMap::iterator it = g_loaded_libs->begin();
         it != g_loaded_libs->end(); ++it) {
      it->second->Unload();
    }
    delete g_loaded_libs;
    g_loaded_libs = NULL;
  }
}

const CPPluginFuncs& ChromePluginLib::functions() const {
  DCHECK(initialized_);
  DCHECK(IsPluginThread());
  return plugin_funcs_;
}

ChromePluginLib::ChromePluginLib(const FilePath& filename)
    : filename_(filename),
#if defined(OS_WIN)
      module_(0),
#endif
      initialized_(false),
      CP_VersionNegotiate_(NULL),
      CP_Initialize_(NULL) {
  memset((void*)&plugin_funcs_, 0, sizeof(plugin_funcs_));
}

ChromePluginLib::~ChromePluginLib() {
}

bool ChromePluginLib::CP_Initialize(const CPBrowserFuncs* bfuncs) {
  LOG(INFO) << "ChromePluginLib::CP_Initialize(" << filename_.value() <<
               "): initialized=" << initialized_;
  if (initialized_)
    return true;

  if (!Load())
    return false;

  if (CP_VersionNegotiate_) {
    uint16 selected_version = 0;
    CPError rv = CP_VersionNegotiate_(CP_VERSION, CP_VERSION,
                                      &selected_version);
    if ( (rv != CPERR_SUCCESS) || (selected_version != CP_VERSION))
      return false;
  }

  plugin_funcs_.size = sizeof(plugin_funcs_);
  CPError rv = CP_Initialize_(cpid(), bfuncs, &plugin_funcs_);
  initialized_ = (rv == CPERR_SUCCESS) &&
      (CP_GET_MAJOR_VERSION(plugin_funcs_.version) == CP_MAJOR_VERSION) &&
      (CP_GET_MINOR_VERSION(plugin_funcs_.version) <= CP_MINOR_VERSION);
  LOG(INFO) << "ChromePluginLib::CP_Initialize(" << filename_.value() <<
               "): initialized=" << initialized_ <<
               "): result=" << rv;

  return initialized_;
}

void ChromePluginLib::CP_Shutdown() {
  DCHECK(initialized_);
  functions().shutdown();
  initialized_ = false;
  memset((void*)&plugin_funcs_, 0, sizeof(plugin_funcs_));
}

int ChromePluginLib::CP_Test(void* param) {
  DCHECK(initialized_);
  if (!CP_Test_)
    return -1;
  return CP_Test_(param);
}

bool ChromePluginLib::Load() {
#if !defined(OS_WIN)
  // TODO(port): plugins not yet implemented
  NOTIMPLEMENTED() << " -- gears loading code.";
  return false;
#else
  DCHECK(module_ == 0);
#ifdef GEARS_STATIC_LIB
  FilePath path;
  if (filename_.BaseName().value().find(FILE_PATH_LITERAL("gears")) == 0) {
    CP_Initialize_ = &Gears_CP_Initialize;
    return true;
  }
#endif

  module_ = LoadLibrary(filename_.value().c_str());
  if (module_ == 0)
    return false;

  // required initialization function
  CP_Initialize_ = reinterpret_cast<CP_InitializeFunc>
      (GetProcAddress(module_, "CP_Initialize"));

  if (!CP_Initialize_) {
    FreeLibrary(module_);
    module_ = 0;
    return false;
  }

  // optional version negotiation function
  CP_VersionNegotiate_ = reinterpret_cast<CP_VersionNegotiateFunc>
      (GetProcAddress(module_, "CP_VersionNegotiate"));

  // optional test function
  CP_Test_ = reinterpret_cast<CP_TestFunc>
      (GetProcAddress(module_, "CP_Test"));

  return true;
#endif
}

void ChromePluginLib::Unload() {
  NotificationService::current()->Notify(
      NotificationType::CHROME_PLUGIN_UNLOADED,
      Source<ChromePluginLib>(this),
      NotificationService::NoDetails());

  if (initialized_)
    CP_Shutdown();

#if defined(OS_WIN)
  if (module_) {
    FreeLibrary(module_);
    module_ = 0;
  }
#endif
}
<commit_msg>posix: drop Gears NOTIMPLEMENTED()<commit_after>// Copyright (c) 2006-2008 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/common/chrome_plugin_lib.h"

#include "base/command_line.h"
#include "base/hash_tables.h"
#include "base/histogram.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/perftimer.h"
#include "base/thread.h"
#if defined(OS_WIN)
#include "base/registry.h"
#endif
#include "base/string_util.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/chrome_paths.h"
#include "webkit/glue/plugins/plugin_list.h"

using base::TimeDelta;

// TODO(port): revisit when plugins happier
#if defined(OS_WIN)
const TCHAR ChromePluginLib::kRegistryChromePlugins[] =
    _T("Software\\Google\\Chrome\\Plugins");
static const TCHAR kRegistryLoadOnStartup[] = _T("LoadOnStartup");
static const TCHAR kRegistryPath[] = _T("Path");
#endif

typedef base::hash_map<FilePath, scoped_refptr<ChromePluginLib> >
    PluginMap;

// A map of all the instantiated plugins.
static PluginMap* g_loaded_libs;

// The thread plugins are loaded and used in, lazily initialized upon
// the first creation call.
static PlatformThreadId g_plugin_thread_id = 0;
static MessageLoop* g_plugin_thread_loop = NULL;

#ifdef GEARS_STATIC_LIB
// defined in gears/base/chrome/module_cr.cc
CPError STDCALL Gears_CP_Initialize(CPID id, const CPBrowserFuncs *bfuncs,
                                    CPPluginFuncs *pfuncs);
#endif

static bool IsSingleProcessMode() {
  // We don't support ChromePlugins in single-process mode.
  return CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
}

// static
bool ChromePluginLib::IsInitialized() {
  return (g_loaded_libs != NULL);
}

// static
ChromePluginLib* ChromePluginLib::Create(const FilePath& filename,
                                         const CPBrowserFuncs* bfuncs) {
  // Keep a map of loaded plugins to ensure we only load each library once.
  if (!g_loaded_libs) {
    g_loaded_libs = new PluginMap();
    g_plugin_thread_id = PlatformThread::CurrentId();
    g_plugin_thread_loop = MessageLoop::current();
  }
  DCHECK(IsPluginThread());

  PluginMap::const_iterator iter = g_loaded_libs->find(filename);
  if (iter != g_loaded_libs->end())
    return iter->second;

  scoped_refptr<ChromePluginLib> plugin(new ChromePluginLib(filename));
  if (!plugin->CP_Initialize(bfuncs))
    return NULL;

  (*g_loaded_libs)[filename] = plugin;
  return plugin;
}

// static
ChromePluginLib* ChromePluginLib::Find(const FilePath& filename) {
  if (g_loaded_libs) {
    PluginMap::const_iterator iter = g_loaded_libs->find(filename);
    if (iter != g_loaded_libs->end())
      return iter->second;
  }
  return NULL;
}

// static
void ChromePluginLib::Destroy(const FilePath& filename) {
  DCHECK(g_loaded_libs);
  PluginMap::iterator iter = g_loaded_libs->find(filename);
  if (iter != g_loaded_libs->end()) {
    iter->second->Unload();
    g_loaded_libs->erase(iter);
  }
}

// static
bool ChromePluginLib::IsPluginThread() {
  return PlatformThread::CurrentId() == g_plugin_thread_id;
}

// static
MessageLoop* ChromePluginLib::GetPluginThreadLoop() {
  return g_plugin_thread_loop;
}

// static
void ChromePluginLib::RegisterPluginsWithNPAPI() {
  // We don't support ChromePlugins in single-process mode.
  if (IsSingleProcessMode())
    return;

  FilePath path;
  if (!PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
    return;
  // Note: we can only access the NPAPI list because the PluginService has done
  // the locking for us.  We should not touch it anywhere else.
  NPAPI::PluginList::AddExtraPluginPath(path);
}

static void LogPluginLoadTime(const TimeDelta &time) {
  UMA_HISTOGRAM_TIMES("Gears.LoadTime", time);
}

// static
void ChromePluginLib::LoadChromePlugins(const CPBrowserFuncs* bfuncs) {
  static bool loaded = false;
  if (loaded)
    return;
  loaded = true;

  // We don't support ChromePlugins in single-process mode.
  if (IsSingleProcessMode())
    return;

  FilePath path;
  if (!PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
    return;

  PerfTimer timer;
  ChromePluginLib::Create(path, bfuncs);
  LogPluginLoadTime(timer.Elapsed());

  // TODO(mpcomplete): disabled loading of plugins from the registry until we
  // phase out registry keys from the gears installer.
#if 0
  for (RegistryKeyIterator iter(HKEY_CURRENT_USER, kRegistryChromePlugins);
       iter.Valid(); ++iter) {
    // Use the registry to gather plugin across the file system.
    std::wstring reg_path = kRegistryChromePlugins;
    reg_path.append(L"\\");
    reg_path.append(iter.Name());
    RegKey key(HKEY_CURRENT_USER, reg_path.c_str());

    DWORD is_persistent;
    if (key.ReadValueDW(kRegistryLoadOnStartup, &is_persistent) &&
        is_persistent) {
      std::wstring path;
      if (key.ReadValue(kRegistryPath, &path)) {
        ChromePluginLib::Create(path, bfuncs);
      }
    }
  }
#endif
}

// static
void ChromePluginLib::UnloadAllPlugins() {
  if (g_loaded_libs) {
    PluginMap::iterator it;
    for (PluginMap::iterator it = g_loaded_libs->begin();
         it != g_loaded_libs->end(); ++it) {
      it->second->Unload();
    }
    delete g_loaded_libs;
    g_loaded_libs = NULL;
  }
}

const CPPluginFuncs& ChromePluginLib::functions() const {
  DCHECK(initialized_);
  DCHECK(IsPluginThread());
  return plugin_funcs_;
}

ChromePluginLib::ChromePluginLib(const FilePath& filename)
    : filename_(filename),
#if defined(OS_WIN)
      module_(0),
#endif
      initialized_(false),
      CP_VersionNegotiate_(NULL),
      CP_Initialize_(NULL) {
  memset((void*)&plugin_funcs_, 0, sizeof(plugin_funcs_));
}

ChromePluginLib::~ChromePluginLib() {
}

bool ChromePluginLib::CP_Initialize(const CPBrowserFuncs* bfuncs) {
  LOG(INFO) << "ChromePluginLib::CP_Initialize(" << filename_.value() <<
               "): initialized=" << initialized_;
  if (initialized_)
    return true;

  if (!Load())
    return false;

  if (CP_VersionNegotiate_) {
    uint16 selected_version = 0;
    CPError rv = CP_VersionNegotiate_(CP_VERSION, CP_VERSION,
                                      &selected_version);
    if ( (rv != CPERR_SUCCESS) || (selected_version != CP_VERSION))
      return false;
  }

  plugin_funcs_.size = sizeof(plugin_funcs_);
  CPError rv = CP_Initialize_(cpid(), bfuncs, &plugin_funcs_);
  initialized_ = (rv == CPERR_SUCCESS) &&
      (CP_GET_MAJOR_VERSION(plugin_funcs_.version) == CP_MAJOR_VERSION) &&
      (CP_GET_MINOR_VERSION(plugin_funcs_.version) <= CP_MINOR_VERSION);
  LOG(INFO) << "ChromePluginLib::CP_Initialize(" << filename_.value() <<
               "): initialized=" << initialized_ <<
               "): result=" << rv;

  return initialized_;
}

void ChromePluginLib::CP_Shutdown() {
  DCHECK(initialized_);
  functions().shutdown();
  initialized_ = false;
  memset((void*)&plugin_funcs_, 0, sizeof(plugin_funcs_));
}

int ChromePluginLib::CP_Test(void* param) {
  DCHECK(initialized_);
  if (!CP_Test_)
    return -1;
  return CP_Test_(param);
}

bool ChromePluginLib::Load() {
#if !defined(OS_WIN)
  // Mac and Linux won't implement Gears.
  return false;
#else
  DCHECK(module_ == 0);
#ifdef GEARS_STATIC_LIB
  FilePath path;
  if (filename_.BaseName().value().find(FILE_PATH_LITERAL("gears")) == 0) {
    CP_Initialize_ = &Gears_CP_Initialize;
    return true;
  }
#endif

  module_ = LoadLibrary(filename_.value().c_str());
  if (module_ == 0)
    return false;

  // required initialization function
  CP_Initialize_ = reinterpret_cast<CP_InitializeFunc>
      (GetProcAddress(module_, "CP_Initialize"));

  if (!CP_Initialize_) {
    FreeLibrary(module_);
    module_ = 0;
    return false;
  }

  // optional version negotiation function
  CP_VersionNegotiate_ = reinterpret_cast<CP_VersionNegotiateFunc>
      (GetProcAddress(module_, "CP_VersionNegotiate"));

  // optional test function
  CP_Test_ = reinterpret_cast<CP_TestFunc>
      (GetProcAddress(module_, "CP_Test"));

  return true;
#endif
}

void ChromePluginLib::Unload() {
  NotificationService::current()->Notify(
      NotificationType::CHROME_PLUGIN_UNLOADED,
      Source<ChromePluginLib>(this),
      NotificationService::NoDetails());

  if (initialized_)
    CP_Shutdown();

#if defined(OS_WIN)
  if (module_) {
    FreeLibrary(module_);
    module_ = 0;
  }
#endif
}
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/kernel/xobject.h"

#include <vector>

#include "xenia/base/byte_stream.h"
#include "xenia/base/clock.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/notify_listener.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#include "xenia/kernel/xenumerator.h"
#include "xenia/kernel/xevent.h"
#include "xenia/kernel/xfile.h"
#include "xenia/kernel/xmutant.h"
#include "xenia/kernel/xsemaphore.h"
#include "xenia/kernel/xthread.h"

namespace xe {
namespace kernel {

XObject::XObject(KernelState* kernel_state, Type type)
    : kernel_state_(kernel_state),
      pointer_ref_count_(1),
      type_(type),
      guest_object_ptr_(0),
      allocated_guest_object_(false) {
  handles_.reserve(10);
  if (kernel_state) {
    kernel_state->object_table()->AddHandle(this, &handles_[0]);
  }
}

XObject::~XObject() {
  assert_zero(pointer_ref_count_);

  if (allocated_guest_object_) {
    uint32_t ptr = guest_object_ptr_ - sizeof(X_OBJECT_HEADER);
    auto header = memory()->TranslateVirtual<X_OBJECT_HEADER*>(ptr);

    // Free the object creation info
    if (header->object_type_ptr) {
      memory()->SystemHeapFree(header->object_type_ptr);
    }

    memory()->SystemHeapFree(ptr);
  }
}

Emulator* XObject::emulator() const { return kernel_state_->emulator_; }
KernelState* XObject::kernel_state() const { return kernel_state_; }
Memory* XObject::memory() const { return kernel_state_->memory(); }

XObject::Type XObject::type() { return type_; }

void XObject::RetainHandle() {
  kernel_state_->object_table()->RetainHandle(handles_[0]);
}

bool XObject::ReleaseHandle() {
  // FIXME: Return true when handle is actually released.
  return kernel_state_->object_table()->ReleaseHandle(handles_[0]) ==
         X_STATUS_SUCCESS;
}

void XObject::Retain() { ++pointer_ref_count_; }

void XObject::Release() {
  if (--pointer_ref_count_ == 0) {
    delete this;
  }
}

X_STATUS XObject::Delete() {
  if (kernel_state_ == nullptr) {
    // Fake return value for api-scanner
    return X_STATUS_SUCCESS;
  } else {
    if (!name_.empty()) {
      kernel_state_->object_table()->RemoveNameMapping(name_);
    }
    return kernel_state_->object_table()->RemoveHandle(handles_[0]);
  }
}

bool XObject::SaveObject(ByteStream* stream) {
  stream->Write<uint32_t>(allocated_guest_object_);
  stream->Write<uint32_t>(guest_object_ptr_);

  stream->Write(uint32_t(handles_.size()));
  stream->Write(&handles_[0], handles_.size() * sizeof(X_HANDLE));

  return true;
}

bool XObject::RestoreObject(ByteStream* stream) {
  allocated_guest_object_ = stream->Read<uint32_t>() > 0;
  guest_object_ptr_ = stream->Read<uint32_t>();

  handles_.resize(stream->Read<uint32_t>());
  stream->Read(&handles_[0], handles_.size() * sizeof(X_HANDLE));

  // Restore our pointer to our handles in the object table.
  for (size_t i = 0; i < handles_.size(); i++) {
    kernel_state_->object_table()->RestoreHandle(handles_[i], this);
  }

  return true;
}

object_ref<XObject> XObject::Restore(KernelState* kernel_state, Type type,
                                     ByteStream* stream) {
  switch (type) {
    case kTypeEnumerator:
      break;
    case kTypeEvent:
      return XEvent::Restore(kernel_state, stream);
    case kTypeFile:
      break;
    case kTypeIOCompletion:
      break;
    case kTypeModule:
      break;
    case kTypeMutant:
      break;
    case kTypeNotifyListener:
      return NotifyListener::Restore(kernel_state, stream);
    case kTypeSemaphore:
      break;
    case kTypeSession:
      break;
    case kTypeSocket:
      break;
    case kTypeThread:
      return XThread::Restore(kernel_state, stream);
    case kTypeTimer:
      break;
    default:
      assert_always("No restore handler exists for this object!");
      return nullptr;
  }

  return nullptr;
}

void XObject::SetAttributes(uint32_t obj_attributes_ptr) {
  if (!obj_attributes_ptr) {
    return;
  }

  auto name = X_ANSI_STRING::to_string_indirect(memory()->virtual_membase(),
                                                obj_attributes_ptr + 4);
  if (!name.empty()) {
    name_ = std::move(name);
    kernel_state_->object_table()->AddNameMapping(name_, handles_[0]);
  }
}

uint32_t XObject::TimeoutTicksToMs(int64_t timeout_ticks) {
  if (timeout_ticks > 0) {
    // Absolute time, based on January 1, 1601.
    // TODO(benvanik): convert time to relative time.
    assert_always();
    return 0;
  } else if (timeout_ticks < 0) {
    // Relative time.
    return (uint32_t)(-timeout_ticks / 10000);  // Ticks -> MS
  } else {
    return 0;
  }
}

X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
                       uint32_t alertable, uint64_t* opt_timeout) {
  auto wait_handle = GetWaitHandle();
  if (!wait_handle) {
    // Object doesn't support waiting.
    return X_STATUS_SUCCESS;
  }

  auto timeout_ms =
      opt_timeout ? std::chrono::milliseconds(Clock::ScaleGuestDurationMillis(
                        TimeoutTicksToMs(*opt_timeout)))
                  : std::chrono::milliseconds::max();

  auto result =
      xe::threading::Wait(wait_handle, alertable ? true : false, timeout_ms);
  switch (result) {
    case xe::threading::WaitResult::kSuccess:
      return X_STATUS_SUCCESS;
    case xe::threading::WaitResult::kUserCallback:
      // Or X_STATUS_ALERTED?
      return X_STATUS_USER_APC;
    case xe::threading::WaitResult::kTimeout:
      xe::threading::MaybeYield();
      return X_STATUS_TIMEOUT;
    default:
    case xe::threading::WaitResult::kAbandoned:
    case xe::threading::WaitResult::kFailed:
      return X_STATUS_ABANDONED_WAIT_0;
  }
}

X_STATUS XObject::SignalAndWait(XObject* signal_object, XObject* wait_object,
                                uint32_t wait_reason, uint32_t processor_mode,
                                uint32_t alertable, uint64_t* opt_timeout) {
  auto timeout_ms =
      opt_timeout ? std::chrono::milliseconds(Clock::ScaleGuestDurationMillis(
                        TimeoutTicksToMs(*opt_timeout)))
                  : std::chrono::milliseconds::max();

  auto result = xe::threading::SignalAndWait(
      signal_object->GetWaitHandle(), wait_object->GetWaitHandle(),
      alertable ? true : false, timeout_ms);
  switch (result) {
    case xe::threading::WaitResult::kSuccess:
      return X_STATUS_SUCCESS;
    case xe::threading::WaitResult::kUserCallback:
      // Or X_STATUS_ALERTED?
      return X_STATUS_USER_APC;
    case xe::threading::WaitResult::kTimeout:
      xe::threading::MaybeYield();
      return X_STATUS_TIMEOUT;
    default:
    case xe::threading::WaitResult::kAbandoned:
    case xe::threading::WaitResult::kFailed:
      return X_STATUS_ABANDONED_WAIT_0;
  }
}

X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
                               uint32_t wait_type, uint32_t wait_reason,
                               uint32_t processor_mode, uint32_t alertable,
                               uint64_t* opt_timeout) {
  std::vector<xe::threading::WaitHandle*> wait_handles(count);
  for (size_t i = 0; i < count; ++i) {
    wait_handles[i] = objects[i]->GetWaitHandle();
    assert_not_null(wait_handles[i]);
  }

  auto timeout_ms =
      opt_timeout ? std::chrono::milliseconds(Clock::ScaleGuestDurationMillis(
                        TimeoutTicksToMs(*opt_timeout)))
                  : std::chrono::milliseconds::max();

  if (wait_type) {
    auto result = xe::threading::WaitAny(std::move(wait_handles),
                                         alertable ? true : false, timeout_ms);
    switch (result.first) {
      case xe::threading::WaitResult::kSuccess:
        return X_STATUS(result.second);
      case xe::threading::WaitResult::kUserCallback:
        // Or X_STATUS_ALERTED?
        return X_STATUS_USER_APC;
      case xe::threading::WaitResult::kTimeout:
        xe::threading::MaybeYield();
        return X_STATUS_TIMEOUT;
      default:
      case xe::threading::WaitResult::kAbandoned:
        return X_STATUS(X_STATUS_ABANDONED_WAIT_0 + result.second);
      case xe::threading::WaitResult::kFailed:
        return X_STATUS_UNSUCCESSFUL;
    }
  } else {
    auto result = xe::threading::WaitAll(std::move(wait_handles),
                                         alertable ? true : false, timeout_ms);
    switch (result) {
      case xe::threading::WaitResult::kSuccess:
        return X_STATUS_SUCCESS;
      case xe::threading::WaitResult::kUserCallback:
        // Or X_STATUS_ALERTED?
        return X_STATUS_USER_APC;
      case xe::threading::WaitResult::kTimeout:
        xe::threading::MaybeYield();
        return X_STATUS_TIMEOUT;
      default:
      case xe::threading::WaitResult::kAbandoned:
      case xe::threading::WaitResult::kFailed:
        return X_STATUS_ABANDONED_WAIT_0;
    }
  }
}

uint8_t* XObject::CreateNative(uint32_t size) {
  auto global_lock = xe::global_critical_region::AcquireDirect();

  uint32_t total_size = size + sizeof(X_OBJECT_HEADER);

  auto mem = memory()->SystemHeapAlloc(total_size);
  if (!mem) {
    // Out of memory!
    return nullptr;
  }

  allocated_guest_object_ = true;
  memory()->Zero(mem, total_size);
  SetNativePointer(mem + sizeof(X_OBJECT_HEADER), true);

  auto header = memory()->TranslateVirtual<X_OBJECT_HEADER*>(mem);

  auto object_type = memory()->SystemHeapAlloc(sizeof(X_OBJECT_TYPE));
  if (object_type) {
    // Set it up in the header.
    // Some kernel method is accessing this struct and dereferencing a member
    // @ offset 0x14
    header->object_type_ptr = object_type;
  }

  return memory()->TranslateVirtual(guest_object_ptr_);
}

void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) {
  auto global_lock = xe::global_critical_region::AcquireDirect();

  // If hit: We've already setup the native ptr with CreateNative!
  assert_zero(guest_object_ptr_);

  auto header =
      kernel_state_->memory()->TranslateVirtual<X_DISPATCH_HEADER*>(native_ptr);

  // Memory uninitialized, so don't bother with the check.
  if (!uninitialized) {
    assert_true(!(header->wait_list_blink & 0x1));
  }

  // Stash pointer in struct.
  // FIXME: This assumes the object has a dispatch header (some don't!)
  StashNative(header, this);

  guest_object_ptr_ = native_ptr;
}

object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
                                             void* native_ptr,
                                             int32_t as_type) {
  assert_not_null(native_ptr);

  // Unfortunately the XDK seems to inline some KeInitialize calls, meaning
  // we never see it and just randomly start getting passed events/timers/etc.
  // Luckily it seems like all other calls (Set/Reset/Wait/etc) are used and
  // we don't have to worry about PPC code poking the struct. Because of that,
  // we init on first use, store our pointer in the struct, and dereference it
  // each time.
  // We identify this by checking the low bit of wait_list_blink - if it's 1,
  // we have already put our pointer in there.

  auto global_lock = xe::global_critical_region::AcquireDirect();

  auto header = reinterpret_cast<X_DISPATCH_HEADER*>(native_ptr);

  if (as_type == -1) {
    as_type = header->type;
  }

  if (header->wait_list_blink & 0x1) {
    // Already initialized.
    uint64_t object_ptr = ((uint64_t)header->wait_list_flink << 32) |
                          ((header->wait_list_blink) & ~0x1);
    XObject* object = reinterpret_cast<XObject*>(object_ptr);
    // TODO(benvanik): assert nothing has been changed in the struct.
    return retain_object<XObject>(object);
  } else {
    // First use, create new.
    // http://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html
    XObject* object = nullptr;
    switch (as_type) {
      case 0:  // EventNotificationObject
      case 1:  // EventSynchronizationObject
      {
        auto ev = new XEvent(kernel_state);
        ev->InitializeNative(native_ptr, header);
        object = ev;
      } break;
      case 2:  // MutantObject
      {
        auto mutant = new XMutant(kernel_state);
        mutant->InitializeNative(native_ptr, header);
        object = mutant;
      } break;
      case 5:  // SemaphoreObject
      {
        auto sem = new XSemaphore(kernel_state);
        sem->InitializeNative(native_ptr, header);
        object = sem;
      } break;
      case 3:   // ProcessObject
      case 4:   // QueueObject
      case 6:   // ThreadObject
      case 7:   // GateObject
      case 8:   // TimerNotificationObject
      case 9:   // TimerSynchronizationObject
      case 18:  // ApcObject
      case 19:  // DpcObject
      case 20:  // DeviceQueueObject
      case 21:  // EventPairObject
      case 22:  // InterruptObject
      case 23:  // ProfileObject
      case 24:  // ThreadedDpcObject
      default:
        assert_always();
        return NULL;
    }

    // Stash pointer in struct.
    // FIXME: This assumes the object contains a dispatch header (some don't!)
    StashNative(header, object);

    // NOTE: we are double-retaining, as the object is implicitly created and
    // can never be released.
    return retain_object<XObject>(object);
  }
}

}  // namespace kernel
}  // namespace xe
<commit_msg>REBASE: Fix vector out of range access.<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/kernel/xobject.h"

#include <vector>

#include "xenia/base/byte_stream.h"
#include "xenia/base/clock.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/notify_listener.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#include "xenia/kernel/xenumerator.h"
#include "xenia/kernel/xevent.h"
#include "xenia/kernel/xfile.h"
#include "xenia/kernel/xmutant.h"
#include "xenia/kernel/xsemaphore.h"
#include "xenia/kernel/xthread.h"

namespace xe {
namespace kernel {

XObject::XObject(KernelState* kernel_state, Type type)
    : kernel_state_(kernel_state),
      pointer_ref_count_(1),
      type_(type),
      guest_object_ptr_(0),
      allocated_guest_object_(false) {
  handles_.reserve(10);
  if (kernel_state) {
    X_HANDLE handle;
    kernel_state->object_table()->AddHandle(this, &handle);
    handles_[0] = handle;
  }
}

XObject::~XObject() {
  assert_zero(pointer_ref_count_);

  if (allocated_guest_object_) {
    uint32_t ptr = guest_object_ptr_ - sizeof(X_OBJECT_HEADER);
    auto header = memory()->TranslateVirtual<X_OBJECT_HEADER*>(ptr);

    // Free the object creation info
    if (header->object_type_ptr) {
      memory()->SystemHeapFree(header->object_type_ptr);
    }

    memory()->SystemHeapFree(ptr);
  }
}

Emulator* XObject::emulator() const { return kernel_state_->emulator_; }
KernelState* XObject::kernel_state() const { return kernel_state_; }
Memory* XObject::memory() const { return kernel_state_->memory(); }

XObject::Type XObject::type() { return type_; }

void XObject::RetainHandle() {
  kernel_state_->object_table()->RetainHandle(handles_[0]);
}

bool XObject::ReleaseHandle() {
  // FIXME: Return true when handle is actually released.
  return kernel_state_->object_table()->ReleaseHandle(handles_[0]) ==
         X_STATUS_SUCCESS;
}

void XObject::Retain() { ++pointer_ref_count_; }

void XObject::Release() {
  if (--pointer_ref_count_ == 0) {
    delete this;
  }
}

X_STATUS XObject::Delete() {
  if (kernel_state_ == nullptr) {
    // Fake return value for api-scanner
    return X_STATUS_SUCCESS;
  } else {
    if (!name_.empty()) {
      kernel_state_->object_table()->RemoveNameMapping(name_);
    }
    return kernel_state_->object_table()->RemoveHandle(handles_[0]);
  }
}

bool XObject::SaveObject(ByteStream* stream) {
  stream->Write<uint32_t>(allocated_guest_object_);
  stream->Write<uint32_t>(guest_object_ptr_);

  stream->Write(uint32_t(handles_.size()));
  stream->Write(&handles_[0], handles_.size() * sizeof(X_HANDLE));

  return true;
}

bool XObject::RestoreObject(ByteStream* stream) {
  allocated_guest_object_ = stream->Read<uint32_t>() > 0;
  guest_object_ptr_ = stream->Read<uint32_t>();

  handles_.resize(stream->Read<uint32_t>());
  stream->Read(&handles_[0], handles_.size() * sizeof(X_HANDLE));

  // Restore our pointer to our handles in the object table.
  for (size_t i = 0; i < handles_.size(); i++) {
    kernel_state_->object_table()->RestoreHandle(handles_[i], this);
  }

  return true;
}

object_ref<XObject> XObject::Restore(KernelState* kernel_state, Type type,
                                     ByteStream* stream) {
  switch (type) {
    case kTypeEnumerator:
      break;
    case kTypeEvent:
      return XEvent::Restore(kernel_state, stream);
    case kTypeFile:
      break;
    case kTypeIOCompletion:
      break;
    case kTypeModule:
      break;
    case kTypeMutant:
      break;
    case kTypeNotifyListener:
      return NotifyListener::Restore(kernel_state, stream);
    case kTypeSemaphore:
      break;
    case kTypeSession:
      break;
    case kTypeSocket:
      break;
    case kTypeThread:
      return XThread::Restore(kernel_state, stream);
    case kTypeTimer:
      break;
    default:
      assert_always("No restore handler exists for this object!");
      return nullptr;
  }

  return nullptr;
}

void XObject::SetAttributes(uint32_t obj_attributes_ptr) {
  if (!obj_attributes_ptr) {
    return;
  }

  auto name = X_ANSI_STRING::to_string_indirect(memory()->virtual_membase(),
                                                obj_attributes_ptr + 4);
  if (!name.empty()) {
    name_ = std::move(name);
    kernel_state_->object_table()->AddNameMapping(name_, handles_[0]);
  }
}

uint32_t XObject::TimeoutTicksToMs(int64_t timeout_ticks) {
  if (timeout_ticks > 0) {
    // Absolute time, based on January 1, 1601.
    // TODO(benvanik): convert time to relative time.
    assert_always();
    return 0;
  } else if (timeout_ticks < 0) {
    // Relative time.
    return (uint32_t)(-timeout_ticks / 10000);  // Ticks -> MS
  } else {
    return 0;
  }
}

X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
                       uint32_t alertable, uint64_t* opt_timeout) {
  auto wait_handle = GetWaitHandle();
  if (!wait_handle) {
    // Object doesn't support waiting.
    return X_STATUS_SUCCESS;
  }

  auto timeout_ms =
      opt_timeout ? std::chrono::milliseconds(Clock::ScaleGuestDurationMillis(
                        TimeoutTicksToMs(*opt_timeout)))
                  : std::chrono::milliseconds::max();

  auto result =
      xe::threading::Wait(wait_handle, alertable ? true : false, timeout_ms);
  switch (result) {
    case xe::threading::WaitResult::kSuccess:
      return X_STATUS_SUCCESS;
    case xe::threading::WaitResult::kUserCallback:
      // Or X_STATUS_ALERTED?
      return X_STATUS_USER_APC;
    case xe::threading::WaitResult::kTimeout:
      xe::threading::MaybeYield();
      return X_STATUS_TIMEOUT;
    default:
    case xe::threading::WaitResult::kAbandoned:
    case xe::threading::WaitResult::kFailed:
      return X_STATUS_ABANDONED_WAIT_0;
  }
}

X_STATUS XObject::SignalAndWait(XObject* signal_object, XObject* wait_object,
                                uint32_t wait_reason, uint32_t processor_mode,
                                uint32_t alertable, uint64_t* opt_timeout) {
  auto timeout_ms =
      opt_timeout ? std::chrono::milliseconds(Clock::ScaleGuestDurationMillis(
                        TimeoutTicksToMs(*opt_timeout)))
                  : std::chrono::milliseconds::max();

  auto result = xe::threading::SignalAndWait(
      signal_object->GetWaitHandle(), wait_object->GetWaitHandle(),
      alertable ? true : false, timeout_ms);
  switch (result) {
    case xe::threading::WaitResult::kSuccess:
      return X_STATUS_SUCCESS;
    case xe::threading::WaitResult::kUserCallback:
      // Or X_STATUS_ALERTED?
      return X_STATUS_USER_APC;
    case xe::threading::WaitResult::kTimeout:
      xe::threading::MaybeYield();
      return X_STATUS_TIMEOUT;
    default:
    case xe::threading::WaitResult::kAbandoned:
    case xe::threading::WaitResult::kFailed:
      return X_STATUS_ABANDONED_WAIT_0;
  }
}

X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
                               uint32_t wait_type, uint32_t wait_reason,
                               uint32_t processor_mode, uint32_t alertable,
                               uint64_t* opt_timeout) {
  std::vector<xe::threading::WaitHandle*> wait_handles(count);
  for (size_t i = 0; i < count; ++i) {
    wait_handles[i] = objects[i]->GetWaitHandle();
    assert_not_null(wait_handles[i]);
  }

  auto timeout_ms =
      opt_timeout ? std::chrono::milliseconds(Clock::ScaleGuestDurationMillis(
                        TimeoutTicksToMs(*opt_timeout)))
                  : std::chrono::milliseconds::max();

  if (wait_type) {
    auto result = xe::threading::WaitAny(std::move(wait_handles),
                                         alertable ? true : false, timeout_ms);
    switch (result.first) {
      case xe::threading::WaitResult::kSuccess:
        return X_STATUS(result.second);
      case xe::threading::WaitResult::kUserCallback:
        // Or X_STATUS_ALERTED?
        return X_STATUS_USER_APC;
      case xe::threading::WaitResult::kTimeout:
        xe::threading::MaybeYield();
        return X_STATUS_TIMEOUT;
      default:
      case xe::threading::WaitResult::kAbandoned:
        return X_STATUS(X_STATUS_ABANDONED_WAIT_0 + result.second);
      case xe::threading::WaitResult::kFailed:
        return X_STATUS_UNSUCCESSFUL;
    }
  } else {
    auto result = xe::threading::WaitAll(std::move(wait_handles),
                                         alertable ? true : false, timeout_ms);
    switch (result) {
      case xe::threading::WaitResult::kSuccess:
        return X_STATUS_SUCCESS;
      case xe::threading::WaitResult::kUserCallback:
        // Or X_STATUS_ALERTED?
        return X_STATUS_USER_APC;
      case xe::threading::WaitResult::kTimeout:
        xe::threading::MaybeYield();
        return X_STATUS_TIMEOUT;
      default:
      case xe::threading::WaitResult::kAbandoned:
      case xe::threading::WaitResult::kFailed:
        return X_STATUS_ABANDONED_WAIT_0;
    }
  }
}

uint8_t* XObject::CreateNative(uint32_t size) {
  auto global_lock = xe::global_critical_region::AcquireDirect();

  uint32_t total_size = size + sizeof(X_OBJECT_HEADER);

  auto mem = memory()->SystemHeapAlloc(total_size);
  if (!mem) {
    // Out of memory!
    return nullptr;
  }

  allocated_guest_object_ = true;
  memory()->Zero(mem, total_size);
  SetNativePointer(mem + sizeof(X_OBJECT_HEADER), true);

  auto header = memory()->TranslateVirtual<X_OBJECT_HEADER*>(mem);

  auto object_type = memory()->SystemHeapAlloc(sizeof(X_OBJECT_TYPE));
  if (object_type) {
    // Set it up in the header.
    // Some kernel method is accessing this struct and dereferencing a member
    // @ offset 0x14
    header->object_type_ptr = object_type;
  }

  return memory()->TranslateVirtual(guest_object_ptr_);
}

void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) {
  auto global_lock = xe::global_critical_region::AcquireDirect();

  // If hit: We've already setup the native ptr with CreateNative!
  assert_zero(guest_object_ptr_);

  auto header =
      kernel_state_->memory()->TranslateVirtual<X_DISPATCH_HEADER*>(native_ptr);

  // Memory uninitialized, so don't bother with the check.
  if (!uninitialized) {
    assert_true(!(header->wait_list_blink & 0x1));
  }

  // Stash pointer in struct.
  // FIXME: This assumes the object has a dispatch header (some don't!)
  StashNative(header, this);

  guest_object_ptr_ = native_ptr;
}

object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
                                             void* native_ptr,
                                             int32_t as_type) {
  assert_not_null(native_ptr);

  // Unfortunately the XDK seems to inline some KeInitialize calls, meaning
  // we never see it and just randomly start getting passed events/timers/etc.
  // Luckily it seems like all other calls (Set/Reset/Wait/etc) are used and
  // we don't have to worry about PPC code poking the struct. Because of that,
  // we init on first use, store our pointer in the struct, and dereference it
  // each time.
  // We identify this by checking the low bit of wait_list_blink - if it's 1,
  // we have already put our pointer in there.

  auto global_lock = xe::global_critical_region::AcquireDirect();

  auto header = reinterpret_cast<X_DISPATCH_HEADER*>(native_ptr);

  if (as_type == -1) {
    as_type = header->type;
  }

  if (header->wait_list_blink & 0x1) {
    // Already initialized.
    uint64_t object_ptr = ((uint64_t)header->wait_list_flink << 32) |
                          ((header->wait_list_blink) & ~0x1);
    XObject* object = reinterpret_cast<XObject*>(object_ptr);
    // TODO(benvanik): assert nothing has been changed in the struct.
    return retain_object<XObject>(object);
  } else {
    // First use, create new.
    // http://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html
    XObject* object = nullptr;
    switch (as_type) {
      case 0:  // EventNotificationObject
      case 1:  // EventSynchronizationObject
      {
        auto ev = new XEvent(kernel_state);
        ev->InitializeNative(native_ptr, header);
        object = ev;
      } break;
      case 2:  // MutantObject
      {
        auto mutant = new XMutant(kernel_state);
        mutant->InitializeNative(native_ptr, header);
        object = mutant;
      } break;
      case 5:  // SemaphoreObject
      {
        auto sem = new XSemaphore(kernel_state);
        sem->InitializeNative(native_ptr, header);
        object = sem;
      } break;
      case 3:   // ProcessObject
      case 4:   // QueueObject
      case 6:   // ThreadObject
      case 7:   // GateObject
      case 8:   // TimerNotificationObject
      case 9:   // TimerSynchronizationObject
      case 18:  // ApcObject
      case 19:  // DpcObject
      case 20:  // DeviceQueueObject
      case 21:  // EventPairObject
      case 22:  // InterruptObject
      case 23:  // ProfileObject
      case 24:  // ThreadedDpcObject
      default:
        assert_always();
        return NULL;
    }

    // Stash pointer in struct.
    // FIXME: This assumes the object contains a dispatch header (some don't!)
    StashNative(header, object);

    // NOTE: we are double-retaining, as the object is implicitly created and
    // can never be released.
    return retain_object<XObject>(object);
  }
}

}  // namespace kernel
}  // namespace xe
<|endoftext|>


<commit_before>#include "Odometer.h"
#include <igvc_msgs/velocity_pair.h>
#include <igvc_msgs/velocity_pair.h>
#include <math.h>
#include <nav_msgs/Odometry.h>
#include <ros/ros.h>
#include "Odometer.h"

double wheel_separation;

/**
 * Coneverts wheel velocities to odometry message using trigonometry for calculations
 * In the ros coordinate convention x is forward, y is leftward, and z is upward relative to the robot
 * The position is published in an absolute reference frame relative to the initial position
 * The velocities (twist) is in a reference frame relative to the robot
*/
void Odometer::enc_callback(const igvc_msgs::velocity_pair& msg)
{
  float leftVelocity = msg.left_velocity * 0.8;
  float rightVelocity = msg.right_velocity * 0.8;
  float deltaT = msg.duration;

  float angularVelocity = (rightVelocity - leftVelocity) / wheel_separation;
  float deltaTheta = angularVelocity * deltaT;
  float velocity = (rightVelocity + leftVelocity) / 2;

  geometry_msgs::Vector3 linearVelocities;
  linearVelocities.z = 0;

  if (fabs(rightVelocity - leftVelocity) > 1e-4)
  {  // 1e-4 is the point where less of a difference is straight
    linearVelocities.y = velocity * sin(deltaTheta);
    linearVelocities.x = velocity * cos(deltaTheta);
  }
  else
  {
    // limit where turn radius is infinite (ie. straight line)
    linearVelocities.y = 0;
    linearVelocities.x = velocity;
  }

  // set angular velocities - assuming 2D operation
  geometry_msgs::Vector3 angularVelocities;
  angularVelocities.x = 0.0;
  angularVelocities.y = 0.0;
  angularVelocities.z = angularVelocity;

  nav_msgs::Odometry odom;
  odom.twist.twist.linear = linearVelocities;
  odom.twist.twist.angular = angularVelocities;

  // update global positions
  // note x and y velocities are local reference frame - convert to global then increment poition
  float dx = linearVelocities.x * deltaT;
  float dy = linearVelocities.y * deltaT;
  x += dx * cos(yaw) - dy * sin(yaw);
  y += dx * sin(yaw) + dy * cos(yaw);
  yaw += deltaTheta;

  // enter message info for global position
  odom.pose.pose.position.x = x;
  odom.pose.pose.position.y = y;
  odom.pose.pose.orientation = tf::createQuaternionMsgFromYaw(yaw);

  // Row-major representation of the 6x6 covariance matrix
  // The orientation parameters use a fixed-axis representation.
  // In order, the parameters are:
  // (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis)
  odom.twist.covariance = { 0.3, 1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 0.25, 1e-4, 1e-4, 1e-4, 1e-4,
                            1e-4, 1e-4, 1e6,  1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 1e6,  1e-4, 1e-4,
                            1e-4, 1e-4, 1e-4, 1e-4, 1e6,  1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 0.62 };
  // the position covariance takes same form as twist covariance above
  // this grows without bounds as error accumulates - disregard exact reading with high variance
  odom.pose.covariance = { 1e6,  1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e6,  1e-6, 1e-6, 1e-6, 1e-6,
                           1e-6, 1e-6, 1e6,  1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e6,  1e-6, 1e-6,
                           1e-6, 1e-6, 1e-6, 1e-6, 1e6,  1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e6 };

  // setting sequence of message
  odom.header.seq = seq++;

  // setting reference frames
  odom.header.frame_id = "wheel_odom";
  odom.child_frame_id = "base_footprint";

  // set time then publish
  odom.header.stamp = ros::Time::now();
  pub.publish(odom);
}

Odometer::Odometer(ros::NodeHandle& nh)
{
  sub = nh.subscribe("/encoders", 10, &Odometer::enc_callback, this);
  pub = nh.advertise<nav_msgs::Odometry>("/wheel_odometry", 10);

  // initializing sequence number for messages
  seq = 0;

  // initialize position - map published is relative to position at time t=0
  x = 0;
  y = 0;
  yaw = 0;
}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "wheel_odom");
  ros::NodeHandle nh;

  ros::NodeHandle pNh("~");

  pNh.param("wheel_separation", wheel_separation, 0.83);

  Odometer odom(nh);

  ROS_INFO_STREAM("wheel odometry node has started");

  ros::spin();
}
<commit_msg>fixed issues from last commit<commit_after>#include "Odometer.h"
#include <igvc_msgs/velocity_pair.h>
#include <igvc_msgs/velocity_pair.h>
#include <math.h>
#include <nav_msgs/Odometry.h>
#include <ros/ros.h>
#include "Odometer.h"

double wheel_separation;

/**
 * Coneverts wheel velocities to odometry message using trigonometry for calculations
 * In the ros coordinate convention x is forward, y is leftward, and z is upward relative to the robot
 * The position is published in an absolute reference frame relative to the initial position
 * The velocities (twist) is in a reference frame relative to the robot
*/
void Odometer::enc_callback(const igvc_msgs::velocity_pair& msg)
{
  float leftVelocity = msg.left_velocity;
  float rightVelocity = msg.right_velocity;
  float deltaT = msg.duration;

  float angularVelocity = (rightVelocity - leftVelocity) / wheel_separation;
  float deltaTheta = angularVelocity * deltaT;
  float velocity = (rightVelocity + leftVelocity) / 2;

  geometry_msgs::Vector3 linearVelocities;
  linearVelocities.z = 0;

  if (fabs(rightVelocity - leftVelocity) > 1e-4)
  {  // 1e-4 is the point where less of a difference is straight
    linearVelocities.y = velocity * sin(deltaTheta);
    linearVelocities.x = velocity * cos(deltaTheta);
  }
  else
  {
    // limit where turn radius is infinite (ie. straight line)
    linearVelocities.y = 0;
    linearVelocities.x = velocity;
  }

  // set angular velocities - assuming 2D operation
  geometry_msgs::Vector3 angularVelocities;
  angularVelocities.x = 0.0;
  angularVelocities.y = 0.0;
  angularVelocities.z = angularVelocity;

  nav_msgs::Odometry odom;
  odom.twist.twist.linear = linearVelocities;
  odom.twist.twist.angular = angularVelocities;

  // update global positions
  // note x and y velocities are local reference frame - convert to global then increment poition
  float dx = linearVelocities.x * deltaT;
  float dy = linearVelocities.y * deltaT;
  x += dx * cos(yaw) - dy * sin(yaw);
  y += dx * sin(yaw) + dy * cos(yaw);
  yaw += deltaTheta;

  // enter message info for global position
  odom.pose.pose.position.x = x;
  odom.pose.pose.position.y = y;
  odom.pose.pose.orientation = tf::createQuaternionMsgFromYaw(yaw);

  // Row-major representation of the 6x6 covariance matrix
  // The orientation parameters use a fixed-axis representation.
  // In order, the parameters are:
  // (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis)
  odom.twist.covariance = { 0.02, 1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 0.25, 1e-4, 1e-4, 1e-4, 1e-4,
                            1e-4, 1e-4, 1e6,  1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 1e6,  1e-4, 1e-4,
                            1e-4, 1e-4, 1e-4, 1e-4, 1e6,  1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 0.62 };
  // the position covariance takes same form as twist covariance above
  // this grows without bounds as error accumulates - disregard exact reading with high variance
  odom.pose.covariance = { 1e6,  1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e6,  1e-6, 1e-6, 1e-6, 1e-6,
                           1e-6, 1e-6, 1e6,  1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e6,  1e-6, 1e-6,
                           1e-6, 1e-6, 1e-6, 1e-6, 1e6,  1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e6 };

  // setting sequence of message
  odom.header.seq = seq++;

  // setting reference frames
  odom.header.frame_id = "wheel_odom";
  odom.child_frame_id = "base_footprint";

  // set time then publish
  odom.header.stamp = ros::Time::now();
  pub.publish(odom);
}

Odometer::Odometer(ros::NodeHandle& nh)
{
  sub = nh.subscribe("/encoders", 10, &Odometer::enc_callback, this);
  pub = nh.advertise<nav_msgs::Odometry>("/wheel_odometry", 10);

  // initializing sequence number for messages
  seq = 0;

  // initialize position - map published is relative to position at time t=0
  x = 0;
  y = 0;
  yaw = 0;
}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "wheel_odom");
  ros::NodeHandle nh;

  ros::NodeHandle pNh("~");

  pNh.param("wheel_separation", wheel_separation, 0.83);

  Odometer odom(nh);

  ROS_INFO_STREAM("wheel odometry node has started");

  ros::spin();
}
<|endoftext|>


<commit_before>#include <QString>
#include <QFileInfo>
#include <QUrl>
#include "kernel.h"
#include "connectorinterface.h"
#include "resource.h"
#include "ilwisdata.h"
#include "angle.h"
#include "geometries.h"
#include "ellipsoid.h"
#include "projection.h"
#include "proj4parameters.h"
#include "ilwisobject.h"
#include "mastercatalog.h"
#include "resourcemodel.h"

#define tempHardPath "h:/projects/Ilwis4/projects/client/qml/desktop/mobile/images/"
//#define tempHardPath "d:/projects/ilwis/Ilwis4/projects/client/qml/desktop/mobile/images/"

using namespace Ilwis;
//using namespace Desktopclient;

QString ResourceModel::getProperty(const QString &propertyname) const
{
    if(_item.hasProperty(propertyname))
        return _item[propertyname].toString();
    return sUNDEF;
}

ResourceModel::ResourceModel()
{

}

ResourceModel::ResourceModel(const Ilwis::Resource& source, QObject *parent) :
    QObject(parent), _imagePath(sUNDEF),_type(itUNKNOWN), _isRoot(false)
{
    resource(source);
}

ResourceModel::ResourceModel(const ResourceModel &model) : QObject(model.parent())
{
    _displayName = model._displayName;

    _item = model._item;
    _imagePath = model._imagePath;
    _type = model._type;
    _isRoot = model._isRoot;
    _selected = model._selected;
    _is3d = model._is3d;
}

ResourceModel &ResourceModel::operator=(const ResourceModel &model)
{
    _displayName = model._displayName;

    _item = model._item;
    _imagePath = model._imagePath;
    _type = model._type;
    _isRoot = model._isRoot;
   _selected = model._selected;
      _is3d = model._is3d;

    return *this;
}

ResourceModel::~ResourceModel()
{

}

QString ResourceModel::imagePath() const
{
    return _imagePath;
}

quint64 ResourceModel::type() const
{
    return _type;
}

QString ResourceModel::typeName() const
{
    return TypeHelper::type2name(_type);
}

QString ResourceModel::name() const
{
    if ( _item.isValid()) {
        return _item.name();
    }
    return "";
}

QString ResourceModel::size() const
{
    if ( _item.isValid() && _item.ilwisType() != itCATALOG){
        quint64 sz = _item.size();
        if ( sz != 0)
            return  QString::number(sz);
    }
    return "";
}

QString ResourceModel::description() const
{
    if ( _item.isValid())
        return _item.description();
    return "";
}

QString ResourceModel::dimensions() const
{
    if ( _item.isValid())
        return _item.dimensions();
    return "";
}

QString ResourceModel::displayName() const
{
    return _displayName;
}

void ResourceModel::setDisplayName(const QString &name)
{
    _displayName = name;
    _item.name(name, false);
}

QString ResourceModel::url() const
{
    return _item.url().toString();
}

QString ResourceModel::container() const
{
   return _item.container().toString();
}

QString ResourceModel::iconPath() const
{
    if ( _iconPath != "")
        return _iconPath;

    quint64 tp = _item.ilwisType();
    if ( hasType(_item.extendedType(), itCATALOG)){
        return iconPath(tp | itCATALOG);
    }
    if ( hasType(_item.extendedType(), itFILE) && tp == itCATALOG)
        return iconPath(tp | itCOVERAGE);
    if ( hasType(_item.extendedType(), itTABLE) && tp == itCATALOG)
        return iconPath(tp | itTABLE);
    return iconPath(tp);
}

void ResourceModel::iconPath(const QString &name)
{
    _iconPath = name;
}

QString ResourceModel::iconPath(IlwisTypes tp)
{
    if ( tp == (itRASTER|itCATALOG))
        return "raster203d.png";
    if ( tp == (itTABLE|itCATALOG))
        return "catalogTable20.png";
    if ( tp == (itCOVERAGE|itCATALOG))
        return "catalogSpatial20.png";
    if ( tp & itRASTER)
        return "raster20CS1.png";
    else if ( tp == itPOLYGON)
        return "polygon20CS1.png";
    else if ( tp == itLINE)
        return "line20.png";
    else if ( tp == itPOINT)
        return "point20.png";
    else if ( hasType(tp, itFEATURE))
        return "feature20CS1.png";
    else if ( tp & itTABLE)
        return "table20CS1.png";
    else if ( tp & itCOORDSYSTEM)
        return "csy20.png";
    else if ( tp & itGEOREF)
        return "georeference20.png";
    else if ( tp == itCATALOG)
        return "folder20.png";
    else if ( tp & itDOMAIN)
        return "domain.png";
    else if ( tp & itREPRESENTATION)
        return "representation20.png";
    else if ( hasType(tp,itNUMBER))
        return "numbers20.png";
    else if ( hasType(tp,itPROJECTION))
        return "projection20.png";
    else if ( hasType(tp,itELLIPSOID))
        return "ellipsoid20.png";
    else if ( tp & itSTRING)
        return "text20.png";
    else if ( tp & itOPERATIONMETADATA)
        return "operation20.png";
    else
        return "eye.png";
}

bool ResourceModel::isRoot() const
{
    return _isRoot;
}

QString ResourceModel::id() const
{
    if ( _item.isValid())
        return QString::number(_item.id());
    return sUNDEF;
}

Resource ResourceModel::item() const
{
    return _item;
}

QString ResourceModel::domainName() const {
    QString nme =  propertyName("domain");
    if ( nme != displayName() && nme != "")
        return nme;
    quint64 tp = _item.ilwisType();
    if ( hasType(tp, itCOVERAGE))
        return "self";
    return "";
}

QString ResourceModel::domainType() const {
    QString nme = propertyTypeName(itDOMAIN, "domain");
    if ( nme != "")
        return nme;
    quint64 tp = _item.ilwisType();
    if ( hasType(tp, itCOVERAGE))
        return "IndexedIdentifier";
    return "";
}

QString ResourceModel::proj42DisplayName(const QString& proj4Def) const{
    Proj4Parameters parms(proj4Def);
    QString projName = Projection::projectionCode2Name(parms["proj"]);
    QString ellipse = Ellipsoid::ellipsoidCode2Name(parms["proj"]);
    if ( ellipse == sUNDEF)
        return sUNDEF;
    return projName + "/" + ellipse;
}

QString ResourceModel::coordinateSystemName() const {
    QString proj = _item["projectionname"].toString();
    if ( proj != sUNDEF)
        return proj;

    QString nme =  propertyName("coordinatesystem");
    if ( nme != displayName() && nme != "" && nme != sUNDEF)
        return nme;
    if ( nme == ""){
        nme = _item["coordinatesystem"].toString();
        if ( nme != sUNDEF){
            int index = nme.toLower().indexOf("code=");
            if ( index == -1){
                nme = _item.code();
            }
            if ((index = nme.toLower().indexOf("code=epsg")) != -1){
                nme = nme.mid(5);
            }
            else if ( (index = nme.toLower().indexOf("code=proj4")) != -1){
                nme = proj42DisplayName(nme.mid(5));
            }else {
                nme = Projection::projectionCode2Name(nme.mid(5));
            }
        }
    }
    return nme != sUNDEF ? nme : "";
}

QString ResourceModel::coordinateSystemType() const {
    QString txt = propertyTypeName(itCOORDSYSTEM, "coordinatesystem");
    return txt.left(txt.size() - QString("CoordinateSystem").size());
}

QString ResourceModel::geoReferenceName() const
{
    QString nme = propertyName("georeference");
    if ( nme != displayName())
        return nme;
    return "";
}

QString ResourceModel::geoReferenceType() const
{
    return propertyTypeName(itGEOREF, "georeference");
}

void ResourceModel::resource(const Ilwis::Resource& res)
{
    Resource item = res;
    if ( item.name() == sUNDEF) {
        QString name  = res.url().toString(QUrl::RemoveScheme | QUrl::RemoveQuery | QUrl::RemovePassword | QUrl::StripTrailingSlash);
        name = name.mid(3);
        item.name(name, false);
    }

    _type = item.ilwisType();
    _item = item;
    if ( hasType(item.ilwisType(), itCOVERAGE)){
        QString dim = _item.dimensions();
        _is3d = dim.split(" ").size() == 3;
    }

    if ( item.url().toString() == "file://"){
        _displayName = "root";
        _isRoot = true;
    }
    else if ( item.url().scheme() == "file") {
        QFileInfo inf(_item.url().toLocalFile());
        QString path = inf.absolutePath();
        _isRoot = inf.isRoot();
        _displayName = item.name();
        QFileInfo thumbPath = path + "/thumbs/" + _displayName + ".png";
        if ( thumbPath.exists()) {
            _imagePath =  "file:///" +  thumbPath.absoluteFilePath();
        } else {
            if ( item.ilwisType() == itCATALOG) {
                _imagePath = "catalog.png";
            }
            if ( hasType(item.ilwisType(), itRASTER))
                 _imagePath = "remote.png";
            else if ( hasType(item.ilwisType(), itFEATURE))
                _imagePath = "polygon.png";
            else if ( hasType(item.ilwisType(), itCOORDSYSTEM))
                _imagePath = "csy.png";
            else if ( hasType(item.ilwisType(), itGEOREF))
                _imagePath = "grf.png";
            else if ( hasType(item.ilwisType(), itTABLE))
                _imagePath = "table.jpg";
            else if ( hasType(item.ilwisType(), itDOMAIN))
                _imagePath = "domainn.png";
            else if ( hasType(item.ilwisType(), itREPRESENTATION))
                _imagePath = "representation20.png";
            else
                _imagePath = "blank.png";
        }
    }else{
        if ( item.hasProperty("longname"))
            _displayName =  item["longname"].toString();
        else
            _displayName = item.name();
    }
}

Ilwis::Resource ResourceModel::resource() const
{
    return _item;
}

Ilwis::Resource& ResourceModel::resourceRef()
{
    return _item;
}

bool ResourceModel::isSelected() const
{
    return _selected;
}

void ResourceModel::setIsSelected(bool yesno)
{
    _selected = yesno;
    emit isSelectedChanged();
}

QString ResourceModel::propertyName( const QString& property) const{
    if ( _item.isValid()) {
        bool ok;
        quint64 iddomain =  _item[property].toLongLong(&ok);
        if ( ok) {
            return Ilwis::mastercatalog()->id2Resource(iddomain).name();
        }
    }
    return "";

}

QString  ResourceModel::propertyTypeName(quint64 typ, const QString& propertyName) const {
    if ( _item.isValid()) {
        if (_item.extendedType() & typ) {
            bool ok;
            quint64 idprop =  _item[propertyName].toLongLong(&ok);
            if ( ok) {
                quint64 tp = Ilwis::mastercatalog()->id2Resource(idprop).ilwisType();
                return Ilwis::IlwisObject::type2Name(tp);
            }
        }
    }
    return "";
}

<commit_msg>added bool as icon type<commit_after>#include <QString>
#include <QFileInfo>
#include <QUrl>
#include "kernel.h"
#include "connectorinterface.h"
#include "resource.h"
#include "ilwisdata.h"
#include "angle.h"
#include "geometries.h"
#include "ellipsoid.h"
#include "projection.h"
#include "proj4parameters.h"
#include "ilwisobject.h"
#include "mastercatalog.h"
#include "resourcemodel.h"

#define tempHardPath "h:/projects/Ilwis4/projects/client/qml/desktop/mobile/images/"
//#define tempHardPath "d:/projects/ilwis/Ilwis4/projects/client/qml/desktop/mobile/images/"

using namespace Ilwis;
//using namespace Desktopclient;

QString ResourceModel::getProperty(const QString &propertyname) const
{
    if(_item.hasProperty(propertyname))
        return _item[propertyname].toString();
    return sUNDEF;
}

ResourceModel::ResourceModel()
{

}

ResourceModel::ResourceModel(const Ilwis::Resource& source, QObject *parent) :
    QObject(parent), _imagePath(sUNDEF),_type(itUNKNOWN), _isRoot(false)
{
    resource(source);
}

ResourceModel::ResourceModel(const ResourceModel &model) : QObject(model.parent())
{
    _displayName = model._displayName;

    _item = model._item;
    _imagePath = model._imagePath;
    _type = model._type;
    _isRoot = model._isRoot;
    _selected = model._selected;
    _is3d = model._is3d;
}

ResourceModel &ResourceModel::operator=(const ResourceModel &model)
{
    _displayName = model._displayName;

    _item = model._item;
    _imagePath = model._imagePath;
    _type = model._type;
    _isRoot = model._isRoot;
   _selected = model._selected;
      _is3d = model._is3d;

    return *this;
}

ResourceModel::~ResourceModel()
{

}

QString ResourceModel::imagePath() const
{
    return _imagePath;
}

quint64 ResourceModel::type() const
{
    return _type;
}

QString ResourceModel::typeName() const
{
    return TypeHelper::type2name(_type);
}

QString ResourceModel::name() const
{
    if ( _item.isValid()) {
        return _item.name();
    }
    return "";
}

QString ResourceModel::size() const
{
    if ( _item.isValid() && _item.ilwisType() != itCATALOG){
        quint64 sz = _item.size();
        if ( sz != 0)
            return  QString::number(sz);
    }
    return "";
}

QString ResourceModel::description() const
{
    if ( _item.isValid())
        return _item.description();
    return "";
}

QString ResourceModel::dimensions() const
{
    if ( _item.isValid())
        return _item.dimensions();
    return "";
}

QString ResourceModel::displayName() const
{
    return _displayName;
}

void ResourceModel::setDisplayName(const QString &name)
{
    _displayName = name;
    _item.name(name, false);
}

QString ResourceModel::url() const
{
    return _item.url().toString();
}

QString ResourceModel::container() const
{
   return _item.container().toString();
}

QString ResourceModel::iconPath() const
{
    if ( _iconPath != "")
        return _iconPath;

    quint64 tp = _item.ilwisType();
    if ( hasType(_item.extendedType(), itCATALOG)){
        return iconPath(tp | itCATALOG);
    }
    if ( hasType(_item.extendedType(), itFILE) && tp == itCATALOG)
        return iconPath(tp | itCOVERAGE);
    if ( hasType(_item.extendedType(), itTABLE) && tp == itCATALOG)
        return iconPath(tp | itTABLE);
    return iconPath(tp);
}

void ResourceModel::iconPath(const QString &name)
{
    _iconPath = name;
}

QString ResourceModel::iconPath(IlwisTypes tp)
{
    if ( tp == (itRASTER|itCATALOG))
        return "raster203d.png";
    if ( tp == (itTABLE|itCATALOG))
        return "catalogTable20.png";
    if ( tp == (itCOVERAGE|itCATALOG))
        return "catalogSpatial20.png";
    if ( tp & itRASTER)
        return "raster20CS1.png";
    else if ( tp == itPOLYGON)
        return "polygon20CS1.png";
    else if ( tp == itLINE)
        return "line20.png";
    else if ( tp == itPOINT)
        return "point20.png";
    else if ( hasType(tp, itFEATURE))
        return "feature20CS1.png";
    else if ( tp & itTABLE)
        return "table20CS1.png";
    else if ( tp & itCOORDSYSTEM)
        return "csy20.png";
    else if ( tp & itGEOREF)
        return "georeference20.png";
    else if ( tp == itCATALOG)
        return "folder20.png";
    else if ( tp & itDOMAIN)
        return "domain.png";
    else if ( tp & itREPRESENTATION)
        return "representation20.png";
    else if ( hasType(tp,itNUMBER))
        return "numbers20.png";
    else if ( hasType(tp,itBOOL))
        return "bool20.png";
    else if ( hasType(tp,itPROJECTION))
        return "projection20.png";
    else if ( hasType(tp,itELLIPSOID))
        return "ellipsoid20.png";
    else if ( tp & itSTRING)
        return "text20.png";
    else if ( tp & itOPERATIONMETADATA)
        return "operation20.png";
    else
        return "eye.png";
}

bool ResourceModel::isRoot() const
{
    return _isRoot;
}

QString ResourceModel::id() const
{
    if ( _item.isValid())
        return QString::number(_item.id());
    return sUNDEF;
}

Resource ResourceModel::item() const
{
    return _item;
}

QString ResourceModel::domainName() const {
    QString nme =  propertyName("domain");
    if ( nme != displayName() && nme != "")
        return nme;
    quint64 tp = _item.ilwisType();
    if ( hasType(tp, itCOVERAGE))
        return "self";
    return "";
}

QString ResourceModel::domainType() const {
    QString nme = propertyTypeName(itDOMAIN, "domain");
    if ( nme != "")
        return nme;
    quint64 tp = _item.ilwisType();
    if ( hasType(tp, itCOVERAGE))
        return "IndexedIdentifier";
    return "";
}

QString ResourceModel::proj42DisplayName(const QString& proj4Def) const{
    Proj4Parameters parms(proj4Def);
    QString projName = Projection::projectionCode2Name(parms["proj"]);
    QString ellipse = Ellipsoid::ellipsoidCode2Name(parms["proj"]);
    if ( ellipse == sUNDEF)
        return sUNDEF;
    return projName + "/" + ellipse;
}

QString ResourceModel::coordinateSystemName() const {
    QString proj = _item["projectionname"].toString();
    if ( proj != sUNDEF)
        return proj;

    QString nme =  propertyName("coordinatesystem");
    if ( nme != displayName() && nme != "" && nme != sUNDEF)
        return nme;
    if ( nme == ""){
        nme = _item["coordinatesystem"].toString();
        if ( nme != sUNDEF){
            int index = nme.toLower().indexOf("code=");
            if ( index == -1){
                nme = _item.code();
            }
            if ((index = nme.toLower().indexOf("code=epsg")) != -1){
                nme = nme.mid(5);
            }
            else if ( (index = nme.toLower().indexOf("code=proj4")) != -1){
                nme = proj42DisplayName(nme.mid(5));
            }else {
                nme = Projection::projectionCode2Name(nme.mid(5));
            }
        }
    }
    return nme != sUNDEF ? nme : "";
}

QString ResourceModel::coordinateSystemType() const {
    QString txt = propertyTypeName(itCOORDSYSTEM, "coordinatesystem");
    return txt.left(txt.size() - QString("CoordinateSystem").size());
}

QString ResourceModel::geoReferenceName() const
{
    QString nme = propertyName("georeference");
    if ( nme != displayName())
        return nme;
    return "";
}

QString ResourceModel::geoReferenceType() const
{
    return propertyTypeName(itGEOREF, "georeference");
}

void ResourceModel::resource(const Ilwis::Resource& res)
{
    Resource item = res;
    if ( item.name() == sUNDEF) {
        QString name  = res.url().toString(QUrl::RemoveScheme | QUrl::RemoveQuery | QUrl::RemovePassword | QUrl::StripTrailingSlash);
        name = name.mid(3);
        item.name(name, false);
    }

    _type = item.ilwisType();
    _item = item;
    if ( hasType(item.ilwisType(), itCOVERAGE)){
        QString dim = _item.dimensions();
        _is3d = dim.split(" ").size() == 3;
    }

    if ( item.url().toString() == "file://"){
        _displayName = "root";
        _isRoot = true;
    }
    else if ( item.url().scheme() == "file") {
        QFileInfo inf(_item.url().toLocalFile());
        QString path = inf.absolutePath();
        _isRoot = inf.isRoot();
        _displayName = item.name();
        QFileInfo thumbPath = path + "/thumbs/" + _displayName + ".png";
        if ( thumbPath.exists()) {
            _imagePath =  "file:///" +  thumbPath.absoluteFilePath();
        } else {
            if ( item.ilwisType() == itCATALOG) {
                _imagePath = "catalog.png";
            }
            if ( hasType(item.ilwisType(), itRASTER))
                 _imagePath = "remote.png";
            else if ( hasType(item.ilwisType(), itFEATURE))
                _imagePath = "polygon.png";
            else if ( hasType(item.ilwisType(), itCOORDSYSTEM))
                _imagePath = "csy.png";
            else if ( hasType(item.ilwisType(), itGEOREF))
                _imagePath = "grf.png";
            else if ( hasType(item.ilwisType(), itTABLE))
                _imagePath = "table.jpg";
            else if ( hasType(item.ilwisType(), itDOMAIN))
                _imagePath = "domainn.png";
            else if ( hasType(item.ilwisType(), itREPRESENTATION))
                _imagePath = "representation20.png";
            else
                _imagePath = "blank.png";
        }
    }else{
        if ( item.hasProperty("longname"))
            _displayName =  item["longname"].toString();
        else
            _displayName = item.name();
    }
}

Ilwis::Resource ResourceModel::resource() const
{
    return _item;
}

Ilwis::Resource& ResourceModel::resourceRef()
{
    return _item;
}

bool ResourceModel::isSelected() const
{
    return _selected;
}

void ResourceModel::setIsSelected(bool yesno)
{
    _selected = yesno;
    emit isSelectedChanged();
}

QString ResourceModel::propertyName( const QString& property) const{
    if ( _item.isValid()) {
        bool ok;
        quint64 iddomain =  _item[property].toLongLong(&ok);
        if ( ok) {
            return Ilwis::mastercatalog()->id2Resource(iddomain).name();
        }
    }
    return "";

}

QString  ResourceModel::propertyTypeName(quint64 typ, const QString& propertyName) const {
    if ( _item.isValid()) {
        if (_item.extendedType() & typ) {
            bool ok;
            quint64 idprop =  _item[propertyName].toLongLong(&ok);
            if ( ok) {
                quint64 tp = Ilwis::mastercatalog()->id2Resource(idprop).ilwisType();
                return Ilwis::IlwisObject::type2Name(tp);
            }
        }
    }
    return "";
}

<|endoftext|>