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

#include <signal.h>
#include <stdlib.h>

#if defined(OS_WIN)
#include <windows.h>
#endif

#include <iostream>
#include <fstream>

#include "base/at_exit.h"
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/stringprintf.h"
#include "base/string_number_conversions.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/webdriver/commands/alert_commands.h"
#include "chrome/test/webdriver/commands/appcache_status_command.h"
#include "chrome/test/webdriver/commands/browser_connection_commands.h"
#include "chrome/test/webdriver/commands/chrome_commands.h"
#include "chrome/test/webdriver/commands/cookie_commands.h"
#include "chrome/test/webdriver/commands/create_session.h"
#include "chrome/test/webdriver/commands/execute_async_script_command.h"
#include "chrome/test/webdriver/commands/execute_command.h"
#include "chrome/test/webdriver/commands/file_upload_command.h"
#include "chrome/test/webdriver/commands/find_element_commands.h"
#include "chrome/test/webdriver/commands/html5_location_commands.h"
#include "chrome/test/webdriver/commands/html5_storage_commands.h"
#include "chrome/test/webdriver/commands/keys_command.h"
#include "chrome/test/webdriver/commands/log_command.h"
#include "chrome/test/webdriver/commands/navigate_commands.h"
#include "chrome/test/webdriver/commands/mouse_commands.h"
#include "chrome/test/webdriver/commands/screenshot_command.h"
#include "chrome/test/webdriver/commands/session_with_id.h"
#include "chrome/test/webdriver/commands/set_timeout_commands.h"
#include "chrome/test/webdriver/commands/source_command.h"
#include "chrome/test/webdriver/commands/target_locator_commands.h"
#include "chrome/test/webdriver/commands/title_command.h"
#include "chrome/test/webdriver/commands/url_command.h"
#include "chrome/test/webdriver/commands/webelement_commands.h"
#include "chrome/test/webdriver/commands/window_commands.h"
#include "chrome/test/webdriver/webdriver_dispatch.h"
#include "chrome/test/webdriver/webdriver_logging.h"
#include "chrome/test/webdriver/webdriver_session_manager.h"
#include "chrome/test/webdriver/webdriver_util.h"
#include "third_party/mongoose/mongoose.h"

#if defined(OS_WIN)
#include <time.h>
#elif defined(OS_POSIX)
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#endif

namespace webdriver {

namespace {

void InitCallbacks(Dispatcher* dispatcher,
                   base::WaitableEvent* shutdown_event,
                   bool forbid_other_requests) {
  dispatcher->AddShutdown("/shutdown", shutdown_event);
  dispatcher->AddStatus("/status");
  dispatcher->AddLog("/log");

  dispatcher->Add<CreateSession>("/session");

  // WebElement commands
  dispatcher->Add<FindOneElementCommand>(  "/session/*/element");
  dispatcher->Add<FindManyElementsCommand>("/session/*/elements");
  dispatcher->Add<ActiveElementCommand>(   "/session/*/element/active");
  dispatcher->Add<FindOneElementCommand>(  "/session/*/element/*/element");
  dispatcher->Add<FindManyElementsCommand>("/session/*/elements/*/elements");
  dispatcher->Add<ElementAttributeCommand>("/session/*/element/*/attribute/*");
  dispatcher->Add<ElementCssCommand>(      "/session/*/element/*/css/*");
  dispatcher->Add<ElementClearCommand>(    "/session/*/element/*/clear");
  dispatcher->Add<ElementDisplayedCommand>("/session/*/element/*/displayed");
  dispatcher->Add<ElementEnabledCommand>(  "/session/*/element/*/enabled");
  dispatcher->Add<ElementEqualsCommand>(   "/session/*/element/*/equals/*");
  dispatcher->Add<ElementLocationCommand>( "/session/*/element/*/location");
  dispatcher->Add<ElementLocationInViewCommand>(
      "/session/*/element/*/location_in_view");
  dispatcher->Add<ElementNameCommand>(    "/session/*/element/*/name");
  dispatcher->Add<ElementSelectedCommand>("/session/*/element/*/selected");
  dispatcher->Add<ElementSizeCommand>(    "/session/*/element/*/size");
  dispatcher->Add<ElementSubmitCommand>(  "/session/*/element/*/submit");
  dispatcher->Add<ElementTextCommand>(    "/session/*/element/*/text");
  dispatcher->Add<ElementToggleCommand>(  "/session/*/element/*/toggle");
  dispatcher->Add<ElementValueCommand>(   "/session/*/element/*/value");

  dispatcher->Add<ScreenshotCommand>("/session/*/screenshot");

  // Mouse Commands
  dispatcher->Add<MoveAndClickCommand>("/session/*/element/*/click");
  dispatcher->Add<DragCommand>(        "/session/*/element/*/drag");
  dispatcher->Add<HoverCommand>(       "/session/*/element/*/hover");

  dispatcher->Add<MoveToCommand>(     "/session/*/moveto");
  dispatcher->Add<ClickCommand>(      "/session/*/click");
  dispatcher->Add<ButtonDownCommand>( "/session/*/buttondown");
  dispatcher->Add<ButtonUpCommand>(   "/session/*/buttonup");
  dispatcher->Add<DoubleClickCommand>("/session/*/doubleclick");

  // All session based commands should be listed after the element based
  // commands to avoid potential mapping conflicts from an overzealous
  // wildcard match. For example, /session/*/title maps to the handler to
  // fetch the page title. If mapped first, this would overwrite the handler
  // for /session/*/element/*/attribute/title, which should fetch the title
  // attribute of the element.
  dispatcher->Add<AcceptAlertCommand>(  "/session/*/accept_alert");
  dispatcher->Add<AlertTextCommand>(    "/session/*/alert_text");
  dispatcher->Add<BackCommand>(         "/session/*/back");
  dispatcher->Add<DismissAlertCommand>( "/session/*/dismiss_alert");
  dispatcher->Add<ExecuteCommand>(      "/session/*/execute");
  dispatcher->Add<ExecuteAsyncScriptCommand>(
                                        "/session/*/execute_async");
  dispatcher->Add<ForwardCommand>(      "/session/*/forward");
  dispatcher->Add<SwitchFrameCommand>(  "/session/*/frame");
  dispatcher->Add<KeysCommand>(         "/session/*/keys");
  dispatcher->Add<RefreshCommand>(      "/session/*/refresh");
  dispatcher->Add<SourceCommand>(       "/session/*/source");
  dispatcher->Add<TitleCommand>(        "/session/*/title");
  dispatcher->Add<URLCommand>(          "/session/*/url");
  dispatcher->Add<WindowCommand>(       "/session/*/window");
  dispatcher->Add<WindowHandleCommand>( "/session/*/window_handle");
  dispatcher->Add<WindowHandlesCommand>("/session/*/window_handles");
  dispatcher->Add<WindowSizeCommand>(   "/session/*/window/*/size");
  dispatcher->Add<WindowPositionCommand>(
                                        "/session/*/window/*/position");
  dispatcher->Add<SetAsyncScriptTimeoutCommand>(
                                        "/session/*/timeouts/async_script");
  dispatcher->Add<ImplicitWaitCommand>( "/session/*/timeouts/implicit_wait");
  dispatcher->Add<LogCommand>(          "/session/*/log");
  dispatcher->Add<FileUploadCommand>(   "/session/*/file");

  // Cookie functions.
  dispatcher->Add<CookieCommand>(     "/session/*/cookie");
  dispatcher->Add<NamedCookieCommand>("/session/*/cookie/*");

  dispatcher->Add<BrowserConnectionCommand>("/session/*/browser_connection");
  dispatcher->Add<AppCacheStatusCommand>("/session/*/application_cache/status");

  // Chrome-specific commands.
  dispatcher->Add<ExtensionsCommand>("/session/*/chrome/extensions");
  dispatcher->Add<ExtensionCommand>("/session/*/chrome/extension/*");
  dispatcher->Add<ViewsCommand>("/session/*/chrome/views");

  // HTML5 functions.
  dispatcher->Add<HTML5LocationCommand>("/session/*/location");
  dispatcher->Add<LocalStorageCommand>("/session/*/local_storage");
  dispatcher->Add<LocalStorageSizeCommand>("/session/*/local_storage/size");
  dispatcher->Add<LocalStorageKeyCommand>("/session/*/local_storage/key*");
  dispatcher->Add<SessionStorageCommand>("/session/*/session_storage");
  dispatcher->Add<SessionStorageSizeCommand>("/session/*/session_storage/size");
  dispatcher->Add<SessionStorageKeyCommand>("/session/*/session_storage/key*");

  // Since the /session/* is a wild card that would match the above URIs, this
  // line MUST be after all other webdriver command callbacks.
  dispatcher->Add<SessionWithID>("/session/*");

  if (forbid_other_requests)
    dispatcher->ForbidAllOtherRequests();
}

void* ProcessHttpRequest(mg_event event_raised,
                         struct mg_connection* connection,
                         const struct mg_request_info* request_info) {
  bool handler_result_code = false;
  if (event_raised == MG_NEW_REQUEST) {
    handler_result_code =
        reinterpret_cast<Dispatcher*>(request_info->user_data)->
            ProcessHttpRequest(connection, request_info);
  }

  return reinterpret_cast<void*>(handler_result_code);
}

void MakeMongooseOptions(const std::string& port,
                         const std::string& root,
                         int http_threads,
                         bool enable_keep_alive,
                         std::vector<std::string>* out_options) {
  out_options->push_back("listening_ports");
  out_options->push_back(port);
  out_options->push_back("enable_keep_alive");
  out_options->push_back(enable_keep_alive ? "yes" : "no");
  out_options->push_back("num_threads");
  out_options->push_back(base::IntToString(http_threads));
  if (!root.empty()) {
    out_options->push_back("document_root");
    out_options->push_back(root);
  }
}

}  // namespace

int RunChromeDriver() {
  base::AtExitManager exit;
  base::WaitableEvent shutdown_event(false, false);
  CommandLine* cmd_line = CommandLine::ForCurrentProcess();

#if defined(OS_POSIX)
  signal(SIGPIPE, SIG_IGN);
#endif
  srand((unsigned int)time(NULL));

  // Register Chrome's path provider so that the AutomationProxy will find our
  // built Chrome.
  chrome::RegisterPathProvider();
  TestTimeouts::Initialize();

  // Parse command line flags.
  std::string port = "9515";
  FilePath log_path;
  std::string root;
  std::string url_base;
  int http_threads = 4;
  bool enable_keep_alive = true;
  if (cmd_line->HasSwitch("port"))
    port = cmd_line->GetSwitchValueASCII("port");
  if (cmd_line->HasSwitch("log-path"))
    log_path = cmd_line->GetSwitchValuePath("log-path");
  // The 'root' flag allows the user to specify a location to serve files from.
  // If it is not given, a callback will be registered to forbid all file
  // requests.
  if (cmd_line->HasSwitch("root"))
    root = cmd_line->GetSwitchValueASCII("root");
  if (cmd_line->HasSwitch("url-base"))
    url_base = cmd_line->GetSwitchValueASCII("url-base");
  if (cmd_line->HasSwitch("http-threads")) {
    if (!base::StringToInt(cmd_line->GetSwitchValueASCII("http-threads"),
                           &http_threads)) {
      std::cerr << "'http-threads' option must be an integer";
      return 1;
    }
  }
  if (cmd_line->HasSwitch("disable-keep-alive"))
    enable_keep_alive = false;

  bool logging_success = InitWebDriverLogging(log_path, kAllLogLevel);
  std::string chromedriver_info = base::StringPrintf(
      "ChromeDriver %s", chrome::kChromeVersion);
  FilePath chromedriver_exe;
  if (PathService::Get(base::FILE_EXE, &chromedriver_exe)) {
    chromedriver_info += base::StringPrintf(
        " %" PRFilePath, chromedriver_exe.value().c_str());
  }
  FileLog::Get()->Log(kInfoLogLevel, base::Time::Now(), chromedriver_info);

  SessionManager* manager = SessionManager::GetInstance();
  manager->set_port(port);
  manager->set_url_base(url_base);

  Dispatcher dispatcher(url_base);
  InitCallbacks(&dispatcher, &shutdown_event, root.empty());

  std::vector<std::string> args;
  MakeMongooseOptions(port, root, http_threads, enable_keep_alive, &args);
  scoped_array<const char*> options(new const char*[args.size() + 1]);
  for (size_t i = 0; i < args.size(); ++i) {
    options[i] = args[i].c_str();
  }
  options[args.size()] = NULL;

  // Initialize SHTTPD context.
  // Listen on port 9515 or port specified on command line.
  // TODO(jmikhail) Maybe add port 9516 as a secure connection.
  struct mg_context* ctx = mg_start(&ProcessHttpRequest,
                                    &dispatcher,
                                    options.get());
  if (ctx == NULL) {
#if defined(OS_WIN)
    return WSAEADDRINUSE;
#else
    return EADDRINUSE;
#endif
  }

  // The tests depend on parsing the first line ChromeDriver outputs,
  // so all other logging should happen after this.
  std::cout << "Started ChromeDriver" << std::endl
            << "port=" << port << std::endl
            << "version=" << chrome::kChromeVersion << std::endl;
  if (logging_success)
    std::cout << "log=" << FileLog::Get()->path().value() << std::endl;
  else
    std::cout << "Log file could not be created" << std::endl;

  // Run until we receive command to shutdown.
  // Don't call mg_stop because mongoose will hang if clients are still
  // connected when keep-alive is enabled.
  shutdown_event.Wait();

  return (EXIT_SUCCESS);
}

}  // namespace webdriver

int main(int argc, char *argv[]) {
  CommandLine::Init(argc, argv);
  webdriver::RunChromeDriver();
}
<commit_msg>[chromedriver] Exit with correct code and log error if port is already used. BUG=chromedriver:71 TEST=none<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <signal.h>
#include <stdlib.h>

#if defined(OS_WIN)
#include <windows.h>
#endif

#include <iostream>
#include <fstream>

#include "base/at_exit.h"
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/stringprintf.h"
#include "base/string_number_conversions.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/webdriver/commands/alert_commands.h"
#include "chrome/test/webdriver/commands/appcache_status_command.h"
#include "chrome/test/webdriver/commands/browser_connection_commands.h"
#include "chrome/test/webdriver/commands/chrome_commands.h"
#include "chrome/test/webdriver/commands/cookie_commands.h"
#include "chrome/test/webdriver/commands/create_session.h"
#include "chrome/test/webdriver/commands/execute_async_script_command.h"
#include "chrome/test/webdriver/commands/execute_command.h"
#include "chrome/test/webdriver/commands/file_upload_command.h"
#include "chrome/test/webdriver/commands/find_element_commands.h"
#include "chrome/test/webdriver/commands/html5_location_commands.h"
#include "chrome/test/webdriver/commands/html5_storage_commands.h"
#include "chrome/test/webdriver/commands/keys_command.h"
#include "chrome/test/webdriver/commands/log_command.h"
#include "chrome/test/webdriver/commands/navigate_commands.h"
#include "chrome/test/webdriver/commands/mouse_commands.h"
#include "chrome/test/webdriver/commands/screenshot_command.h"
#include "chrome/test/webdriver/commands/session_with_id.h"
#include "chrome/test/webdriver/commands/set_timeout_commands.h"
#include "chrome/test/webdriver/commands/source_command.h"
#include "chrome/test/webdriver/commands/target_locator_commands.h"
#include "chrome/test/webdriver/commands/title_command.h"
#include "chrome/test/webdriver/commands/url_command.h"
#include "chrome/test/webdriver/commands/webelement_commands.h"
#include "chrome/test/webdriver/commands/window_commands.h"
#include "chrome/test/webdriver/webdriver_dispatch.h"
#include "chrome/test/webdriver/webdriver_logging.h"
#include "chrome/test/webdriver/webdriver_session_manager.h"
#include "chrome/test/webdriver/webdriver_util.h"
#include "third_party/mongoose/mongoose.h"

#if defined(OS_WIN)
#include <time.h>
#elif defined(OS_POSIX)
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#endif

namespace webdriver {

namespace {

void InitCallbacks(Dispatcher* dispatcher,
                   base::WaitableEvent* shutdown_event,
                   bool forbid_other_requests) {
  dispatcher->AddShutdown("/shutdown", shutdown_event);
  dispatcher->AddStatus("/status");
  dispatcher->AddLog("/log");

  dispatcher->Add<CreateSession>("/session");

  // WebElement commands
  dispatcher->Add<FindOneElementCommand>(  "/session/*/element");
  dispatcher->Add<FindManyElementsCommand>("/session/*/elements");
  dispatcher->Add<ActiveElementCommand>(   "/session/*/element/active");
  dispatcher->Add<FindOneElementCommand>(  "/session/*/element/*/element");
  dispatcher->Add<FindManyElementsCommand>("/session/*/elements/*/elements");
  dispatcher->Add<ElementAttributeCommand>("/session/*/element/*/attribute/*");
  dispatcher->Add<ElementCssCommand>(      "/session/*/element/*/css/*");
  dispatcher->Add<ElementClearCommand>(    "/session/*/element/*/clear");
  dispatcher->Add<ElementDisplayedCommand>("/session/*/element/*/displayed");
  dispatcher->Add<ElementEnabledCommand>(  "/session/*/element/*/enabled");
  dispatcher->Add<ElementEqualsCommand>(   "/session/*/element/*/equals/*");
  dispatcher->Add<ElementLocationCommand>( "/session/*/element/*/location");
  dispatcher->Add<ElementLocationInViewCommand>(
      "/session/*/element/*/location_in_view");
  dispatcher->Add<ElementNameCommand>(    "/session/*/element/*/name");
  dispatcher->Add<ElementSelectedCommand>("/session/*/element/*/selected");
  dispatcher->Add<ElementSizeCommand>(    "/session/*/element/*/size");
  dispatcher->Add<ElementSubmitCommand>(  "/session/*/element/*/submit");
  dispatcher->Add<ElementTextCommand>(    "/session/*/element/*/text");
  dispatcher->Add<ElementToggleCommand>(  "/session/*/element/*/toggle");
  dispatcher->Add<ElementValueCommand>(   "/session/*/element/*/value");

  dispatcher->Add<ScreenshotCommand>("/session/*/screenshot");

  // Mouse Commands
  dispatcher->Add<MoveAndClickCommand>("/session/*/element/*/click");
  dispatcher->Add<DragCommand>(        "/session/*/element/*/drag");
  dispatcher->Add<HoverCommand>(       "/session/*/element/*/hover");

  dispatcher->Add<MoveToCommand>(     "/session/*/moveto");
  dispatcher->Add<ClickCommand>(      "/session/*/click");
  dispatcher->Add<ButtonDownCommand>( "/session/*/buttondown");
  dispatcher->Add<ButtonUpCommand>(   "/session/*/buttonup");
  dispatcher->Add<DoubleClickCommand>("/session/*/doubleclick");

  // All session based commands should be listed after the element based
  // commands to avoid potential mapping conflicts from an overzealous
  // wildcard match. For example, /session/*/title maps to the handler to
  // fetch the page title. If mapped first, this would overwrite the handler
  // for /session/*/element/*/attribute/title, which should fetch the title
  // attribute of the element.
  dispatcher->Add<AcceptAlertCommand>(  "/session/*/accept_alert");
  dispatcher->Add<AlertTextCommand>(    "/session/*/alert_text");
  dispatcher->Add<BackCommand>(         "/session/*/back");
  dispatcher->Add<DismissAlertCommand>( "/session/*/dismiss_alert");
  dispatcher->Add<ExecuteCommand>(      "/session/*/execute");
  dispatcher->Add<ExecuteAsyncScriptCommand>(
                                        "/session/*/execute_async");
  dispatcher->Add<ForwardCommand>(      "/session/*/forward");
  dispatcher->Add<SwitchFrameCommand>(  "/session/*/frame");
  dispatcher->Add<KeysCommand>(         "/session/*/keys");
  dispatcher->Add<RefreshCommand>(      "/session/*/refresh");
  dispatcher->Add<SourceCommand>(       "/session/*/source");
  dispatcher->Add<TitleCommand>(        "/session/*/title");
  dispatcher->Add<URLCommand>(          "/session/*/url");
  dispatcher->Add<WindowCommand>(       "/session/*/window");
  dispatcher->Add<WindowHandleCommand>( "/session/*/window_handle");
  dispatcher->Add<WindowHandlesCommand>("/session/*/window_handles");
  dispatcher->Add<WindowSizeCommand>(   "/session/*/window/*/size");
  dispatcher->Add<WindowPositionCommand>(
                                        "/session/*/window/*/position");
  dispatcher->Add<SetAsyncScriptTimeoutCommand>(
                                        "/session/*/timeouts/async_script");
  dispatcher->Add<ImplicitWaitCommand>( "/session/*/timeouts/implicit_wait");
  dispatcher->Add<LogCommand>(          "/session/*/log");
  dispatcher->Add<FileUploadCommand>(   "/session/*/file");

  // Cookie functions.
  dispatcher->Add<CookieCommand>(     "/session/*/cookie");
  dispatcher->Add<NamedCookieCommand>("/session/*/cookie/*");

  dispatcher->Add<BrowserConnectionCommand>("/session/*/browser_connection");
  dispatcher->Add<AppCacheStatusCommand>("/session/*/application_cache/status");

  // Chrome-specific commands.
  dispatcher->Add<ExtensionsCommand>("/session/*/chrome/extensions");
  dispatcher->Add<ExtensionCommand>("/session/*/chrome/extension/*");
  dispatcher->Add<ViewsCommand>("/session/*/chrome/views");

  // HTML5 functions.
  dispatcher->Add<HTML5LocationCommand>("/session/*/location");
  dispatcher->Add<LocalStorageCommand>("/session/*/local_storage");
  dispatcher->Add<LocalStorageSizeCommand>("/session/*/local_storage/size");
  dispatcher->Add<LocalStorageKeyCommand>("/session/*/local_storage/key*");
  dispatcher->Add<SessionStorageCommand>("/session/*/session_storage");
  dispatcher->Add<SessionStorageSizeCommand>("/session/*/session_storage/size");
  dispatcher->Add<SessionStorageKeyCommand>("/session/*/session_storage/key*");

  // Since the /session/* is a wild card that would match the above URIs, this
  // line MUST be after all other webdriver command callbacks.
  dispatcher->Add<SessionWithID>("/session/*");

  if (forbid_other_requests)
    dispatcher->ForbidAllOtherRequests();
}

void* ProcessHttpRequest(mg_event event_raised,
                         struct mg_connection* connection,
                         const struct mg_request_info* request_info) {
  bool handler_result_code = false;
  if (event_raised == MG_NEW_REQUEST) {
    handler_result_code =
        reinterpret_cast<Dispatcher*>(request_info->user_data)->
            ProcessHttpRequest(connection, request_info);
  }

  return reinterpret_cast<void*>(handler_result_code);
}

void MakeMongooseOptions(const std::string& port,
                         const std::string& root,
                         int http_threads,
                         bool enable_keep_alive,
                         std::vector<std::string>* out_options) {
  out_options->push_back("listening_ports");
  out_options->push_back(port);
  out_options->push_back("enable_keep_alive");
  out_options->push_back(enable_keep_alive ? "yes" : "no");
  out_options->push_back("num_threads");
  out_options->push_back(base::IntToString(http_threads));
  if (!root.empty()) {
    out_options->push_back("document_root");
    out_options->push_back(root);
  }
}

}  // namespace

int RunChromeDriver() {
  base::AtExitManager exit;
  base::WaitableEvent shutdown_event(false, false);
  CommandLine* cmd_line = CommandLine::ForCurrentProcess();

#if defined(OS_POSIX)
  signal(SIGPIPE, SIG_IGN);
#endif
  srand((unsigned int)time(NULL));

  // Register Chrome's path provider so that the AutomationProxy will find our
  // built Chrome.
  chrome::RegisterPathProvider();
  TestTimeouts::Initialize();

  // Parse command line flags.
  std::string port = "9515";
  FilePath log_path;
  std::string root;
  std::string url_base;
  int http_threads = 4;
  bool enable_keep_alive = true;
  if (cmd_line->HasSwitch("port"))
    port = cmd_line->GetSwitchValueASCII("port");
  if (cmd_line->HasSwitch("log-path"))
    log_path = cmd_line->GetSwitchValuePath("log-path");
  // The 'root' flag allows the user to specify a location to serve files from.
  // If it is not given, a callback will be registered to forbid all file
  // requests.
  if (cmd_line->HasSwitch("root"))
    root = cmd_line->GetSwitchValueASCII("root");
  if (cmd_line->HasSwitch("url-base"))
    url_base = cmd_line->GetSwitchValueASCII("url-base");
  if (cmd_line->HasSwitch("http-threads")) {
    if (!base::StringToInt(cmd_line->GetSwitchValueASCII("http-threads"),
                           &http_threads)) {
      std::cerr << "'http-threads' option must be an integer";
      return 1;
    }
  }
  if (cmd_line->HasSwitch("disable-keep-alive"))
    enable_keep_alive = false;

  bool logging_success = InitWebDriverLogging(log_path, kAllLogLevel);
  std::string chromedriver_info = base::StringPrintf(
      "ChromeDriver %s", chrome::kChromeVersion);
  FilePath chromedriver_exe;
  if (PathService::Get(base::FILE_EXE, &chromedriver_exe)) {
    chromedriver_info += base::StringPrintf(
        " %" PRFilePath, chromedriver_exe.value().c_str());
  }
  FileLog::Get()->Log(kInfoLogLevel, base::Time::Now(), chromedriver_info);

  SessionManager* manager = SessionManager::GetInstance();
  manager->set_port(port);
  manager->set_url_base(url_base);

  Dispatcher dispatcher(url_base);
  InitCallbacks(&dispatcher, &shutdown_event, root.empty());

  std::vector<std::string> args;
  MakeMongooseOptions(port, root, http_threads, enable_keep_alive, &args);
  scoped_array<const char*> options(new const char*[args.size() + 1]);
  for (size_t i = 0; i < args.size(); ++i) {
    options[i] = args[i].c_str();
  }
  options[args.size()] = NULL;

  // Initialize SHTTPD context.
  // Listen on port 9515 or port specified on command line.
  // TODO(jmikhail) Maybe add port 9516 as a secure connection.
  struct mg_context* ctx = mg_start(&ProcessHttpRequest,
                                    &dispatcher,
                                    options.get());
  if (ctx == NULL) {
    std::cerr << "Port already in use. Exiting..." << std::endl;
#if defined(OS_WIN)
    return WSAEADDRINUSE;
#else
    return EADDRINUSE;
#endif
  }

  // The tests depend on parsing the first line ChromeDriver outputs,
  // so all other logging should happen after this.
  std::cout << "Started ChromeDriver" << std::endl
            << "port=" << port << std::endl
            << "version=" << chrome::kChromeVersion << std::endl;
  if (logging_success)
    std::cout << "log=" << FileLog::Get()->path().value() << std::endl;
  else
    std::cout << "Log file could not be created" << std::endl;

  // Run until we receive command to shutdown.
  // Don't call mg_stop because mongoose will hang if clients are still
  // connected when keep-alive is enabled.
  shutdown_event.Wait();

  return (EXIT_SUCCESS);
}

}  // namespace webdriver

int main(int argc, char *argv[]) {
  CommandLine::Init(argc, argv);
  return webdriver::RunChromeDriver();
}
<|endoftext|>


<commit_before>/*
 * libx6adc.cpp
 *
 *  Created on: Oct 30, 2013
 *      Author: qlab
 */

#include "headings.h"
#include "libx6adc.h"
#include "X6_1000.h"

// globals
map<unsigned, std::unique_ptr<X6_1000>> X6s_;
unsigned numDevices_ = 0;

// initialize the library --contructor hook in header
void init() {
	//Open the logging file
	FILE* pFile = fopen("libx6.log", "a");
	Output2FILE::Stream() = pFile;

	static Innovative::X6_1000M x6;
	numDevices_ = static_cast<unsigned int>(x6.BoardCount());
	FILE_LOG(logINFO) << "Initializing BBN libx6 with " << numDevices_ << " device" << (numDevices_ > 1 ? "s" : "") << " found.";
}

//cleanup on driver unload --destructor hook in header
void cleanup(){
	FILE_LOG(logINFO) << "Cleaning up libx6 before driver unloading." << endl;
	if (Output2FILE::Stream()) {
		fclose(Output2FILE::Stream());
	}
}

//Define a couple of templated wrapper functions to make library calls and catch thrown errors
//First one for void calls
template<typename F, typename... Args>
X6_STATUS x6_call(const unsigned deviceID, F func, Args... args){
	try{
		(X6s_.at(deviceID).get()->*func)(args...); // for some reason the compiler can't infer the correct dereference operator without the get function
	}
	catch (std::out_of_range e) {
		if (X6s_.find(deviceID) == X6s_.end()) {
			return X6_UNCONNECTED;
		} else {
			return X6_UNKNOWN_ERROR;
		}
	}
	catch (X6_STATUS status) {
		return status;
	}
	catch (...) {
		return X6_UNKNOWN_ERROR;
	}
}

//and one for to store getter values in pointer passed to library
template<typename R, typename F, typename... Args>
X6_STATUS x6_getter(const unsigned deviceID, F func, R* resPtr, Args... args){
	try {
		*resPtr = (X6s_.at(deviceID).get()->*func)(args...);
		//Nothing thrown then assume OK
		return X6_OK;
	}
	catch (std::out_of_range e) {
		if (X6s_.find(deviceID) == X6s_.end()) {
			return X6_UNCONNECTED;
		} else {
			return X6_UNKNOWN_ERROR;
		}
	}
	catch (X6_STATUS status) {
		return status;
	}
	catch (...) {
		return X6_UNKNOWN_ERROR;
	}
}

#ifdef __cplusplus
extern "C" {
#endif

X6_STATUS get_num_devices(unsigned* numDevices) {
	*numDevices = numDevices_;
	return X6_OK;
}

X6_STATUS connect_by_ID(int deviceID) {
	if (deviceID >= numDevices_) return X6_NO_DEVICE_FOUND;
	if (X6s_.find(deviceID) == X6s_.end()){
		X6s_[deviceID] = std::unique_ptr<X6_1000>(new X6_1000()); //turn-into make_unique when we can go to gcc 4.9
	}
	return x6_call(deviceID, &X6_1000::open, deviceID);
}

X6_STATUS disconnect(int deviceID) {
	X6_STATUS status = x6_call(deviceID, &X6_1000::close);

	if (status == X6_OK){
		X6s_.erase(deviceID);
	}
	return status;
}

X6_STATUS initX6(int deviceID) {
	return x6_call(deviceID, &X6_1000::init);
}

X6_STATUS read_firmware_version(int deviceID, uint32_t* version) {
	return x6_getter(deviceID, &X6_1000::read_firmware_version, version);
}

X6_STATUS set_digitizer_mode(int deviceID, DigitizerMode mode) {
	return x6_call(deviceID, &X6_1000::set_digitizer_mode, mode);
}

X6_STATUS get_digitizer_mode(int deviceID, DigitizerMode* digitizerMode) {
	return x6_getter(deviceID, &X6_1000::get_digitizer_mode, digitizerMode);
}

X6_STATUS set_sampleRate(int deviceID, double freq){
	//assume for now we'll use the internal clock
	//varadic pack must be last so pass default arguments here too
	return x6_call(deviceID, &X6_1000::set_clock, INTERNAL_CLOCK, freq, FRONT_PANEL);
}

X6_STATUS get_sampleRate(int deviceID, double* freq) {
	return x6_getter(deviceID, &X6_1000::get_pll_frequency, freq);
}

X6_STATUS set_trigger_source(int deviceID, TriggerSource triggerSource) {
	return x6_call(deviceID, &X6_1000::set_trigger_source, triggerSource);
}

X6_STATUS get_trigger_source(int deviceID, TriggerSource* triggerSource) {
	return x6_getter(deviceID, &X6_1000::get_trigger_source, triggerSource);
}

X6_STATUS set_reference(int deviceID, ReferenceSource src) {
	//varadic pack must be last so pass default argument here too
	return x6_call(deviceID, &X6_1000::set_reference, src, 10e6);
}

X6_STATUS get_reference(int deviceID, ReferenceSource* src) {
	return x6_getter(deviceID, &X6_1000::get_reference, src);
}

X6_STATUS enable_stream(int deviceID, int a, int b, int c) {
	return x6_call(deviceID, &X6_1000::enable_stream, a, b, c);
}

X6_STATUS disable_stream(int deviceID, int a, int b, int c) {
	return x6_call(deviceID, &X6_1000::disable_stream, a, b, c);
}

X6_STATUS set_averager_settings(int deviceID, int recordLength, int numSegments, int waveforms, int roundRobins) {
	return x6_call(deviceID, &X6_1000::set_averager_settings, recordLength, numSegments, waveforms, roundRobins);
}

X6_STATUS set_nco_frequency(int deviceID, int a, int b, double freq) {
	return x6_call(deviceID, &X6_1000::set_nco_frequency, a, b, freq);
}

X6_STATUS set_threshold(int deviceID, int a, int b, double threshold) {
	return x6_call(deviceID, &X6_1000::set_threshold, a, b, threshold);
}

X6_STATUS write_kernel(int deviceID, int a, int b, double* kernel, unsigned length) {
	return x6_call(deviceID, &X6_1000::write_kernel, a, b, kernel, length);
}

X6_STATUS acquire(int deviceID) {
	return x6_call(deviceID, &X6_1000::acquire);
}

X6_STATUS wait_for_acquisition(int deviceID, unsigned timeOut) {
	return x6_call(deviceID, &X6_1000::wait_for_acquisition, timeOut);
}

X6_STATUS get_is_running(int deviceID, int* isRunning) {
	return x6_getter(deviceID, &X6_1000::get_is_running, isRunning);
}

X6_STATUS get_has_new_data(int deviceID, int* hasNewData) {
	return x6_getter(deviceID, &X6_1000::get_has_new_data, hasNewData);
}

X6_STATUS stop(int deviceID) {
	return x6_call(deviceID, &X6_1000::stop);
}

X6_STATUS transfer_waveform(int deviceID, ChannelTuple *channelTuples, unsigned numChannels, double* buffer, unsigned bufferLength) {
	// when passed a single ChannelTuple, fills buffer with the corresponding waveform data
	// when passed multple ChannelTuples, fills buffer with the corresponding correlation data
	vector<Channel> channels(numChannels);
	for (int i = 0; i < numChannels; i++) {
		channels[i] = Channel(channelTuples[i].a, channelTuples[i].b, channelTuples[i].c);
	}
	if (numChannels == 1) {
		return x6_call(deviceID, &X6_1000::transfer_waveform, channels[0], buffer, bufferLength);
	} else {
		return x6_call(deviceID, &X6_1000::transfer_correlation, channels, buffer, bufferLength);
	}
}

X6_STATUS transfer_variance(int deviceID, ChannelTuple *channelTuples, unsigned numChannels, double* buffer, unsigned bufferLength) {
	vector<Channel> channels(numChannels);
	for (int i = 0; i < numChannels; i++) {
		channels[i] = Channel(channelTuples[i].a, channelTuples[i].b, channelTuples[i].c);
	}
	if (numChannels == 1) {
		return x6_call(deviceID, &X6_1000::transfer_variance, channels[0], buffer, bufferLength);
	} else {
		return x6_call(deviceID, &X6_1000::transfer_correlation_variance, channels, buffer, bufferLength);
	}
}

X6_STATUS get_buffer_size(int deviceID, ChannelTuple *channelTuples, unsigned numChannels, int* bufferSize) {
	vector<Channel> channels(numChannels);
	for (int i = 0; i < numChannels; i++) {
		channels[i] = Channel(channelTuples[i].a, channelTuples[i].b, channelTuples[i].c);
	}
	return x6_getter(deviceID, &X6_1000::get_buffer_size, bufferSize, channels);
}

X6_STATUS get_variance_buffer_size(int deviceID, ChannelTuple *channelTuples, unsigned numChannels, int* bufferSize) {
	vector<Channel> channels(numChannels);
	for (int i = 0; i < numChannels; i++) {
		channels[i] = Channel(channelTuples[i].a, channelTuples[i].b, channelTuples[i].c);
	}
	return x6_getter(deviceID, &X6_1000::get_variance_buffer_size, bufferSize, channels);
}

//Expects a null-terminated character array
X6_STATUS set_log(char* fileNameArr) {
	string fileName(fileNameArr);
	if (fileName.compare("stdout") == 0){
		return update_log(stdout);
	}
	else if (fileName.compare("stderr") == 0){
		return update_log(stderr);
	}
	else{

		FILE* pFile = fopen(fileName.c_str(), "a");
		if (!pFile) {
			return X6_FILE_ERROR;
		}

		return update_log(pFile);
	}
}

X6_STATUS update_log(FILE* pFile) {
	if (pFile) {
		//Close the current file
		if (Output2FILE::Stream()) fclose(Output2FILE::Stream());
		//Assign the new one
		Output2FILE::Stream() = pFile;
		return X6_OK;
	} else {
		return X6_FILE_ERROR;
	}
}

X6_STATUS set_logging_level(int logLevel) {
	FILELog::ReportingLevel() = TLogLevel(logLevel);
	return X6_OK;
}

X6_STATUS read_register(int deviceID, int wbAddr, int offset, uint32_t* regValue){
	return x6_getter(deviceID, &X6_1000::read_wishbone_register, regValue, wbAddr, offset);
}

X6_STATUS write_register(int deviceID, int wbAddr, int offset, int data){
	return x6_call(deviceID, &X6_1000::write_wishbone_register, wbAddr, offset, data);
}

X6_STATUS get_logic_temperature(int deviceID, int method, float* temp) {
	if (method == 0)
		return x6_getter(deviceID, &X6_1000::get_logic_temperature, temp);
	else
		return x6_getter(deviceID, &X6_1000::get_logic_temperature_by_reg, temp);
}

#ifdef __cplusplus
}
#endif
<commit_msg>Actually have to return X6_OK in x6_call<commit_after>/*
 * libx6adc.cpp
 *
 *  Created on: Oct 30, 2013
 *      Author: qlab
 */

#include "headings.h"
#include "libx6adc.h"
#include "X6_1000.h"

// globals
map<unsigned, std::unique_ptr<X6_1000>> X6s_;
unsigned numDevices_ = 0;

// initialize the library --contructor hook in header
void init() {
	//Open the logging file
	FILE* pFile = fopen("libx6.log", "a");
	Output2FILE::Stream() = pFile;

	static Innovative::X6_1000M x6;
	numDevices_ = static_cast<unsigned int>(x6.BoardCount());
	FILE_LOG(logINFO) << "Initializing BBN libx6 with " << numDevices_ << " device" << (numDevices_ > 1 ? "s" : "") << " found.";
}

//cleanup on driver unload --destructor hook in header
void cleanup(){
	FILE_LOG(logINFO) << "Cleaning up libx6 before driver unloading." << endl;
	if (Output2FILE::Stream()) {
		fclose(Output2FILE::Stream());
	}
}

//Define a couple of templated wrapper functions to make library calls and catch thrown errors
//First one for void calls
template<typename F, typename... Args>
X6_STATUS x6_call(const unsigned deviceID, F func, Args... args){
	try{
		(X6s_.at(deviceID).get()->*func)(args...); // for some reason the compiler can't infer the correct dereference operator without the get function
		//Nothing thrown then assume OK
		return X6_OK;
	}
	catch (std::out_of_range e) {
		if (X6s_.find(deviceID) == X6s_.end()) {
			return X6_UNCONNECTED;
		} else {
			return X6_UNKNOWN_ERROR;
		}
	}
	catch (X6_STATUS status) {
		return status;
	}
	catch (...) {
		return X6_UNKNOWN_ERROR;
	}
}

//and one for to store getter values in pointer passed to library
template<typename R, typename F, typename... Args>
X6_STATUS x6_getter(const unsigned deviceID, F func, R* resPtr, Args... args){
	try {
		*resPtr = (X6s_.at(deviceID).get()->*func)(args...);
		//Nothing thrown then assume OK
		return X6_OK;
	}
	catch (std::out_of_range e) {
		if (X6s_.find(deviceID) == X6s_.end()) {
			return X6_UNCONNECTED;
		} else {
			return X6_UNKNOWN_ERROR;
		}
	}
	catch (X6_STATUS status) {
		return status;
	}
	catch (...) {
		return X6_UNKNOWN_ERROR;
	}
}

#ifdef __cplusplus
extern "C" {
#endif

X6_STATUS get_num_devices(unsigned* numDevices) {
	*numDevices = numDevices_;
	return X6_OK;
}

X6_STATUS connect_by_ID(int deviceID) {
	if (deviceID >= numDevices_) return X6_NO_DEVICE_FOUND;
	if (X6s_.find(deviceID) == X6s_.end()){
		X6s_[deviceID] = std::unique_ptr<X6_1000>(new X6_1000()); //turn-into make_unique when we can go to gcc 4.9
	}
	return x6_call(deviceID, &X6_1000::open, deviceID);
}

X6_STATUS disconnect(int deviceID) {
	X6_STATUS status = x6_call(deviceID, &X6_1000::close);

	if (status == X6_OK){
		X6s_.erase(deviceID);
	}
	return status;
}

X6_STATUS initX6(int deviceID) {
	return x6_call(deviceID, &X6_1000::init);
}

X6_STATUS read_firmware_version(int deviceID, uint32_t* version) {
	return x6_getter(deviceID, &X6_1000::read_firmware_version, version);
}

X6_STATUS set_digitizer_mode(int deviceID, DigitizerMode mode) {
	return x6_call(deviceID, &X6_1000::set_digitizer_mode, mode);
}

X6_STATUS get_digitizer_mode(int deviceID, DigitizerMode* digitizerMode) {
	return x6_getter(deviceID, &X6_1000::get_digitizer_mode, digitizerMode);
}

X6_STATUS set_sampleRate(int deviceID, double freq){
	//assume for now we'll use the internal clock
	//varadic pack must be last so pass default arguments here too
	return x6_call(deviceID, &X6_1000::set_clock, INTERNAL_CLOCK, freq, FRONT_PANEL);
}

X6_STATUS get_sampleRate(int deviceID, double* freq) {
	return x6_getter(deviceID, &X6_1000::get_pll_frequency, freq);
}

X6_STATUS set_trigger_source(int deviceID, TriggerSource triggerSource) {
	return x6_call(deviceID, &X6_1000::set_trigger_source, triggerSource);
}

X6_STATUS get_trigger_source(int deviceID, TriggerSource* triggerSource) {
	return x6_getter(deviceID, &X6_1000::get_trigger_source, triggerSource);
}

X6_STATUS set_reference(int deviceID, ReferenceSource src) {
	//varadic pack must be last so pass default argument here too
	return x6_call(deviceID, &X6_1000::set_reference, src, 10e6);
}

X6_STATUS get_reference(int deviceID, ReferenceSource* src) {
	return x6_getter(deviceID, &X6_1000::get_reference, src);
}

X6_STATUS enable_stream(int deviceID, int a, int b, int c) {
	return x6_call(deviceID, &X6_1000::enable_stream, a, b, c);
}

X6_STATUS disable_stream(int deviceID, int a, int b, int c) {
	return x6_call(deviceID, &X6_1000::disable_stream, a, b, c);
}

X6_STATUS set_averager_settings(int deviceID, int recordLength, int numSegments, int waveforms, int roundRobins) {
	return x6_call(deviceID, &X6_1000::set_averager_settings, recordLength, numSegments, waveforms, roundRobins);
}

X6_STATUS set_nco_frequency(int deviceID, int a, int b, double freq) {
	return x6_call(deviceID, &X6_1000::set_nco_frequency, a, b, freq);
}

X6_STATUS set_threshold(int deviceID, int a, int b, double threshold) {
	return x6_call(deviceID, &X6_1000::set_threshold, a, b, threshold);
}

X6_STATUS write_kernel(int deviceID, int a, int b, double* kernel, unsigned length) {
	return x6_call(deviceID, &X6_1000::write_kernel, a, b, kernel, length);
}

X6_STATUS acquire(int deviceID) {
	return x6_call(deviceID, &X6_1000::acquire);
}

X6_STATUS wait_for_acquisition(int deviceID, unsigned timeOut) {
	return x6_call(deviceID, &X6_1000::wait_for_acquisition, timeOut);
}

X6_STATUS get_is_running(int deviceID, int* isRunning) {
	return x6_getter(deviceID, &X6_1000::get_is_running, isRunning);
}

X6_STATUS get_has_new_data(int deviceID, int* hasNewData) {
	return x6_getter(deviceID, &X6_1000::get_has_new_data, hasNewData);
}

X6_STATUS stop(int deviceID) {
	return x6_call(deviceID, &X6_1000::stop);
}

X6_STATUS transfer_waveform(int deviceID, ChannelTuple *channelTuples, unsigned numChannels, double* buffer, unsigned bufferLength) {
	// when passed a single ChannelTuple, fills buffer with the corresponding waveform data
	// when passed multple ChannelTuples, fills buffer with the corresponding correlation data
	vector<Channel> channels(numChannels);
	for (int i = 0; i < numChannels; i++) {
		channels[i] = Channel(channelTuples[i].a, channelTuples[i].b, channelTuples[i].c);
	}
	if (numChannels == 1) {
		return x6_call(deviceID, &X6_1000::transfer_waveform, channels[0], buffer, bufferLength);
	} else {
		return x6_call(deviceID, &X6_1000::transfer_correlation, channels, buffer, bufferLength);
	}
}

X6_STATUS transfer_variance(int deviceID, ChannelTuple *channelTuples, unsigned numChannels, double* buffer, unsigned bufferLength) {
	vector<Channel> channels(numChannels);
	for (int i = 0; i < numChannels; i++) {
		channels[i] = Channel(channelTuples[i].a, channelTuples[i].b, channelTuples[i].c);
	}
	if (numChannels == 1) {
		return x6_call(deviceID, &X6_1000::transfer_variance, channels[0], buffer, bufferLength);
	} else {
		return x6_call(deviceID, &X6_1000::transfer_correlation_variance, channels, buffer, bufferLength);
	}
}

X6_STATUS get_buffer_size(int deviceID, ChannelTuple *channelTuples, unsigned numChannels, int* bufferSize) {
	vector<Channel> channels(numChannels);
	for (int i = 0; i < numChannels; i++) {
		channels[i] = Channel(channelTuples[i].a, channelTuples[i].b, channelTuples[i].c);
	}
	return x6_getter(deviceID, &X6_1000::get_buffer_size, bufferSize, channels);
}

X6_STATUS get_variance_buffer_size(int deviceID, ChannelTuple *channelTuples, unsigned numChannels, int* bufferSize) {
	vector<Channel> channels(numChannels);
	for (int i = 0; i < numChannels; i++) {
		channels[i] = Channel(channelTuples[i].a, channelTuples[i].b, channelTuples[i].c);
	}
	return x6_getter(deviceID, &X6_1000::get_variance_buffer_size, bufferSize, channels);
}

//Expects a null-terminated character array
X6_STATUS set_log(char* fileNameArr) {
	string fileName(fileNameArr);
	if (fileName.compare("stdout") == 0){
		return update_log(stdout);
	}
	else if (fileName.compare("stderr") == 0){
		return update_log(stderr);
	}
	else{

		FILE* pFile = fopen(fileName.c_str(), "a");
		if (!pFile) {
			return X6_FILE_ERROR;
		}

		return update_log(pFile);
	}
}

X6_STATUS update_log(FILE* pFile) {
	if (pFile) {
		//Close the current file
		if (Output2FILE::Stream()) fclose(Output2FILE::Stream());
		//Assign the new one
		Output2FILE::Stream() = pFile;
		return X6_OK;
	} else {
		return X6_FILE_ERROR;
	}
}

X6_STATUS set_logging_level(int logLevel) {
	FILELog::ReportingLevel() = TLogLevel(logLevel);
	return X6_OK;
}

X6_STATUS read_register(int deviceID, int wbAddr, int offset, uint32_t* regValue){
	return x6_getter(deviceID, &X6_1000::read_wishbone_register, regValue, wbAddr, offset);
}

X6_STATUS write_register(int deviceID, int wbAddr, int offset, int data){
	return x6_call(deviceID, &X6_1000::write_wishbone_register, wbAddr, offset, data);
}

X6_STATUS get_logic_temperature(int deviceID, int method, float* temp) {
	if (method == 0)
		return x6_getter(deviceID, &X6_1000::get_logic_temperature, temp);
	else
		return x6_getter(deviceID, &X6_1000::get_logic_temperature_by_reg, temp);
}

#ifdef __cplusplus
}
#endif
<|endoftext|>


<commit_before>//index_sequence header
//Copyright (c) 2014 mmYYmmdd

#if !defined MMYYMMDD_INDEX_SEQUENCE_INCLUDED
#define MMYYMMDD_INDEX_SEQUENCE_INCLUDED

#include <type_traits>
#include <utility>

namespace mymd  {
    template <typename T, T...values>
    struct integEr_sequence  {
        using value_type = T;
        static constexpr std::size_t size() { return sizeof...(values); }
    };

    template<std::size_t...indices>
    using indEx_sequence = integEr_sequence<std::size_t, indices...>;
    //------------------------------------------------
    template <typename T1, typename T2>	struct index_cat;

    template <std::size_t... indices1, std::size_t... indices2>
    struct index_cat<indEx_sequence<indices1...>, indEx_sequence<indices2...>>
    { using type = indEx_sequence<indices1..., indices2...>; };

    template <std::size_t N, typename T>    struct index_shift;

    template <std::size_t N, std::size_t... indices>
    struct index_shift<N, indEx_sequence<indices...>> { using type = indEx_sequence<N + indices...>; };
    //------------------------------------------------------------------------
    namespace detail_index_range_i  {
        template <std::size_t first, std::size_t len>
        struct index_range_i
        { using type = typename index_shift<first, typename index_range_i<0, len>::type>::type; };

        template <std::size_t len>
        struct index_range_i<0, len>		{
            static constexpr std::size_t h = len/2;
            using type = typename index_cat<typename index_range_i<0, h>::type, typename index_range_i<h, len-h>::type>::type;
        };

        template <> struct index_range_i<0, 0>	{ using type = indEx_sequence<>; };
        template <> struct index_range_i<0, 1>	{ using type = indEx_sequence<0>; };
        template <> struct index_range_i<0, 2>	{ using type = indEx_sequence<0, 1>; };
    }
    //+**************************************************************
    template <std::size_t first, std::size_t last>
    using index_range = typename detail_index_range_i::index_range_i<first, (first<last)? last - first: 0>::type;

    template <std::size_t last>
    using make_indEx_sequence = typename detail_index_range_i::index_range_i<0, last>::type;
}

namespace mymd  {
    namespace detail_index_at   {

        //  get N_th type of a sequence of types
        template <std::size_t , typename T> struct type_at	{ using type = T; };

        template <typename , typename...>	struct pair_t;
        template <std::size_t... num, typename... types>
        struct pair_t<indEx_sequence<num...>, types...>     :   type_at<num, types>... {};

        template <std::size_t N>
        struct acceptor	{
            template <typename T>
            static type_at<N, T> upcast(const type_at<N, T>&);
        };

        //  get N_th index of a sequence of values
        template <std::size_t, typename> struct att_imple;

        template <std::size_t N, typename T, template <typename U, U...> class value_seq_t, T... values>
        struct att_imple<N, value_seq_t<T, values...>>   {
        private:
            template <T v> struct t_value { static constexpr T value = v; };
            using type_imple = pair_t<make_indEx_sequence<sizeof...(values)>, t_value<values>...>;
        public:
            using type = T;
            constexpr static T value = decltype(acceptor<N>::upcast(type_imple{}))::type::value;
        };

        template <std::size_t N, template <typename...> class tuple_t, typename... T>
        struct att_imple<N, tuple_t<T...>>    {
        private:
            using type_imple = pair_t<make_indEx_sequence<sizeof...(T)>, T...>;
            using type_0    =  decltype(acceptor<N>::upcast(type_imple{}));
        public:
            using type = typename type_0::type;
        };

        template <std::size_t N>
        struct att_imple<N, void>    {
            template <typename T>
            using apply = att_imple<N, T>;
        };

    }   //namespace detail_index_at

    //+**************************************************************
    // get N_th value of a sequence of values  att<N, value_sequence>::value;    att<N>::apply<value_sequence>::value:
    // get N_th type of a sequence of types    att<N, type_sequence>;   att<N>::apply<type_sequence>;
    template <std::size_t N, typename T = void>
    using att = detail_index_at::att_imple<N, T>;

    template <typename T>
    struct tat  {
        template <std::size_t N>
        using at = detail_index_at::att_imple<N, T>;
    };
}

namespace mymd  {
    namespace detail_reverse	{
        template <typename...>	struct reverse_make;

        template <template <typename...> class types, typename...result, typename first, typename... tail>
        struct reverse_make<types<result...>, first, tail...> : reverse_make<types<first, result...>, tail...> {};

        template <template <typename...> class types, typename...result>
        struct reverse_make<types<result...>>   { using type = types<result...>; };

        template <typename T>	struct reverse_imple;
        template <template <typename...> class types, typename...E>
        struct reverse_imple<types<E...>>   { using type = typename reverse_make<types<>, E...>::type; };
    }
    // reverse the order of some tuple type  --  tupleなどの型の集合を逆順にする
    template <typename T>
    using reverse_t = typename detail_reverse::reverse_imple<
        typename std::remove_cv<typename std::remove_reference<T>::type>::type>::type;
}

namespace mymd  {
    namespace detail_count_template_parameters    {
        //　取りうるテンプレートパラメータの数を取得する関数 count<T> を実装したい
        //  例） count<std::is_integral> => 1  ,  count<std::pair> => 2  ,  count<std::tuple> => (size_t)-1(とりあえず...)

        //template <template <typename...F> class>                      エラーになる
          //  constexpr std::size_t count1() { return sizeof...(F); }    NG! こうは書けない。Fを与えてないからしょうがない。
        //手で展開するしかないのか・・・
        template <template <typename> class>
            constexpr std::size_t count1() { return 1; }
        template <template <typename, typename> class>
            constexpr std::size_t count1() { return 2; }
        template <template <typename, typename, typename> class>
            constexpr std::size_t count1() { return 3; }
        template <template <typename, typename, typename, typename> class>
            constexpr std::size_t count1() { return 4; }
        template <template <typename, typename, typename, typename, typename> class>
            constexpr std::size_t count1() { return 5; }
        template <template <typename, typename, typename, typename, typename, typename> class>
            constexpr std::size_t count1() { return 6; }
        template <template <typename, typename, typename, typename, typename, typename, typename> class>
            constexpr std::size_t count1() { return 7; }
        // これ以上のパターンもひたすら定義する（しかし実用的にはここまでで十分のはず・・・？）
        //----------------------------------------------------------------------------

        template <template <typename...> class T>
        constexpr std::size_t count2(decltype(count1<T>())) { return count1<T>(); }

        template <template <typename...> class T>
        constexpr std::size_t count2(...)                   { return (std::size_t)-1; }

    }   //detail_count_template_parameters

    //関数 count
    template <template <typename...> class T>
    constexpr std::size_t	count_template_parameters()
        { return detail_count_template_parameters::count2<T>(0); }

    //variable templateに対してはどう書けばいいの？
    //template <??????????>
    //constexpr std::size_t    count();
}

#endif
<commit_msg>find_type を追加<commit_after>//index_sequence header
//Copyright (c) 2014 mmYYmmdd

#if !defined MMYYMMDD_INDEX_SEQUENCE_INCLUDED
#define MMYYMMDD_INDEX_SEQUENCE_INCLUDED

#include <type_traits>
#include <utility>

namespace mymd  {
    template <typename T, T...values>
    struct integEr_sequence  {
        using value_type = T;
        static const std::size_t size() { return sizeof...(values); }
    };

    template<std::size_t...indices>
    using indEx_sequence = integEr_sequence<std::size_t, indices...>;
    //------------------------------------------------
    template <typename T1, typename T2>	struct index_cat;

    template <std::size_t... indices1, std::size_t... indices2>
    struct index_cat<indEx_sequence<indices1...>, indEx_sequence<indices2...>>
    { using type = indEx_sequence<indices1..., indices2...>; };

    template <std::size_t N, typename T>    struct index_shift;

    template <std::size_t N, std::size_t... indices>
    struct index_shift<N, indEx_sequence<indices...>> { using type = indEx_sequence<N + indices...>; };
    //------------------------------------------------------------------------
    namespace detail_index_range_i  {
        template <std::size_t first, std::size_t len>
        struct index_range_i
        { using type = typename index_shift<first, typename index_range_i<0, len>::type>::type; };

        template <std::size_t len>
        struct index_range_i<0, len>		{
            static const std::size_t h = len/2;
            using type = typename index_cat<typename index_range_i<0, h>::type, typename index_range_i<h, len-h>::type>::type;
        };

        template <> struct index_range_i<0, 0>	{ using type = indEx_sequence<>; };
        template <> struct index_range_i<0, 1>	{ using type = indEx_sequence<0>; };
        template <> struct index_range_i<0, 2>	{ using type = indEx_sequence<0, 1>; };
    }
    //+**************************************************************
    template <std::size_t first, std::size_t last>
    using index_range = typename detail_index_range_i::index_range_i<first, (first<last)? last - first: 0>::type;

    template <std::size_t last>
    using make_indEx_sequence = typename detail_index_range_i::index_range_i<0, last>::type;
}

namespace mymd  {
    namespace detail_index_at   {

        //  get N_th type of a sequence of types
        template <std::size_t , typename T> struct type_at	{ using type = T; };

        template <typename , typename...>	struct pair_t;
        template <std::size_t... num, typename... types>
        struct pair_t<indEx_sequence<num...>, types...>     :   type_at<num, types>... {};

        template <std::size_t N>
        struct acceptor	{
            template <typename T>
            static type_at<N, T> upcast(const type_at<N, T>&);
        };

        //  get N_th index of a sequence of values
        template <std::size_t, typename> struct att_imple;

        template <std::size_t N, typename T, template <typename U, U...> class value_seq_t, T... values>
        struct att_imple<N, value_seq_t<T, values...>>   {
        private:
            template <T v> struct t_value { static const T value = v; };
            using type_imple = pair_t<make_indEx_sequence<sizeof...(values)>, t_value<values>...>;
        public:
            using type = T;
            const static T value = decltype(acceptor<N>::upcast(type_imple{}))::type::value;
        };

        template <std::size_t N, template <typename...> class tuple_t, typename... T>
        struct att_imple<N, tuple_t<T...>>    {
        private:
            using type_imple = pair_t<make_indEx_sequence<sizeof...(T)>, T...>;
            using type_0    =  decltype(acceptor<N>::upcast(type_imple{}));
        public:
            using type = typename type_0::type;
        };

        template <std::size_t N>
        struct att_imple<N, void>    {
            template <typename T>
            using in = att_imple<N, T>;
        };

    }   //namespace detail_index_at

    //+**************************************************************
    // get N_th value of a sequence of values  at_type
    // at_type::at<N>::in<T>,      at_type::in<T>::at<N>
    struct at_type  {
        template <std::size_t N>
        struct at   { template <typename T> using in = typename detail_index_at::template att_imple<N, T>::type; };
        template <typename T>
        struct in   { template <std::size_t N> using at = typename detail_index_at::template att_imple<N, T>::type; };
    };

    // convert the type of integer sequence class     from      seq<T...values>;    ---->    Seq<T, T...values>;
    // from  template <int...values> struct int_sequence;   to  like  template <typename T, T...values> struct Sequence;
    // sequence_generation<int>::gen<int_sequence>;
    template <typename T>
    struct sequence_generation  {
        template <typename, typename> struct gen_imple;
        template <typename U, template <U...> class seq, U...values>
        struct gen_imple<U, seq<values...>> { using type = integEr_sequence<U, values...>; };
        template <typename W>
        using gen = typename gen_imple<T, W>::type;
    };
}

namespace mymd  {
    namespace detail_reverse	{
        template <typename...>	struct reverse_make;

        template <template <typename...> class types, typename...result, typename first, typename... tail>
        struct reverse_make<types<result...>, first, tail...> : reverse_make<types<first, result...>, tail...> {};

        template <template <typename...> class types, typename...result>
        struct reverse_make<types<result...>>   { using type = types<result...>; };

        template <typename T>	struct reverse_imple;
        template <template <typename...> class types, typename...E>
        struct reverse_imple<types<E...>>   { using type = typename reverse_make<types<>, E...>::type; };
    }
    // reverse the order of some tuple type  --  tupleなどの型の集合を逆順にする
    template <typename T>
    using reverse_t = typename detail_reverse::reverse_imple<
        typename std::remove_cv<typename std::remove_reference<T>::type>::type>::type;
}

namespace mymd  {
    namespace detail_count_template_parameters    {
        //　取りうるテンプレートパラメータの数を取得する関数 count<T> を実装したい
        //  例） count<std::is_integral> => 1  ,  count<std::pair> => 2  ,  count<std::tuple> => (size_t)-1(とりあえず...)

        //template <template <typename...F> class>                      エラーになる
          //  constexpr std::size_t count1() { return sizeof...(F); }    NG! こうは書けない。Fを与えてないからしょうがない。
        //手で展開するしかないのか・・・
        template <template <typename> class>
            constexpr std::size_t count1() { return 1; }
        template <template <typename, typename> class>
            constexpr std::size_t count1() { return 2; }
        template <template <typename, typename, typename> class>
            constexpr std::size_t count1() { return 3; }
        template <template <typename, typename, typename, typename> class>
            constexpr std::size_t count1() { return 4; }
        template <template <typename, typename, typename, typename, typename> class>
            constexpr std::size_t count1() { return 5; }
        template <template <typename, typename, typename, typename, typename, typename> class>
            constexpr std::size_t count1() { return 6; }
        template <template <typename, typename, typename, typename, typename, typename, typename> class>
            constexpr std::size_t count1() { return 7; }
        // これ以上のパターンもひたすら定義する（しかし実用的にはここまでで十分のはず・・・？）
        //----------------------------------------------------------------------------

        template <template <typename...> class T>
        constexpr std::size_t count2(decltype(count1<T>())) { return count1<T>(); }

        template <template <typename...> class T>
        constexpr std::size_t count2(...)                   { return (std::size_t)-1; }

    }   //detail_count_template_parameters

    //関数 count
    template <template <typename...> class T>
    constexpr std::size_t	count_template_parameters()
        { return detail_count_template_parameters::count2<T>(0); }

    //variable templateに対してはどう書けばいいの？
    //template <??????????>
    //constexpr std::size_t    count();
}

namespace mymd  {
    namespace detail_find    {
        //a little complicated because of VC++
                template <typename...>     struct allFalse         { static const bool value = false; };
                template <typename...T>    struct allFalse<T*...>  { static const bool value = true;  };
                template <bool...b> struct bool_array     {
                    static const bool all_0 = allFalse<typename std::conditional<b, int, int*>::type...>::value;
                };
                struct set_no_default {};
                template <bool, typename A>  struct type_pair {};
                template <typename A> A upcast(type_pair<true, A>&);

        template <template <typename> class Pr, typename default_t = set_no_default>
        struct find_type_imple     {
            template <typename... elem>
            struct apply0   {
                using b_array = bool_array<Pr<elem>::value...>;
                static const bool use_default = b_array::all_0 && !std::is_same<default_t, set_no_default>::value;
                static_assert(!(b_array::all_0 && std::is_same<default_t, set_no_default>::value), "mymd::find_type : no match");
                template <typename, typename...>  struct D;
                template <bool...b, typename...T> struct D<bool_array<b...>, T...>
                    : type_pair<use_default, default_t>, type_pair<b, T>... {};
                static D<b_array, elem...>& getD();
                using type = decltype(upcast( getD() ));
            };
            //----------------------------------------------
            template <typename Arr> struct Apply0;
            template <template <typename...> class Arr, typename... elem>
            struct Apply0<Arr<elem...>> { using type = typename apply0<elem...>::type; };
        };
    }   //namespace detail_find
    //--------------------------------------------------------------------------------------

    struct find_type    {
        template <template <typename> class Pr>
        struct by {
            template <typename D, typename default_t = detail_find::set_no_default>
                using from = typename detail_find::find_type_imple<Pr, default_t>::template Apply0<D>::type;
            template <typename...elem>
                using in = typename detail_find::find_type_imple<Pr>::template apply0<elem...>::type;
        };
        template <typename D, typename default_t = detail_find::set_no_default>
        struct from  {
            template <template <typename> class Pr>
                using by = typename detail_find::find_type_imple<Pr, default_t>::template Apply0<D>::type;
        };
        template <typename...elem>
        struct in  {
            template <template <typename> class Pr>
                struct vc_workaround  {
                    using type = typename detail_find::find_type_imple<Pr>::template apply0<elem...>::type;
                };
            template <template <typename> class Pr>
                using by = typename vc_workaround<Pr>::type;
        };
    };

}

#endif
<|endoftext|>


<commit_before>//$Id$

#ifndef MECHANICFORCETRANSFORMER_HPP_INCLUDED
#define MECHANICFORCETRANSFORMER_HPP_INCLUDED

#include "../../ComponentEssentials.h"

namespace hopsan {

    //!
    //! @brief
    //! @ingroup MechanicalComponents
    //!
    class MechanicForceTransformer : public ComponentC
    {

    private:
        double f;
        double *mpND_signal, *mpND_f, *mpND_c, *mpND_Zx;
        Port *mpIn, *mpP1;

    public:
        static Component *Creator()
        {
            return new MechanicForceTransformer("ForceTransformer");
        }

        MechanicForceTransformer(const std::string name) : ComponentC(name)
        {
            //Set member attributes
            f = 0.0;

            //Add ports to the component
            mpIn = addReadPort("in", "NodeSignal", Port::NOTREQUIRED);
            mpP1 = addPowerPort("P1", "NodeMechanic");

            //Register changable parameters to the HOPSAN++ core
            registerParameter("F", "Generated force", "[N]", f);

            disableStartValue(mpP1, NodeMechanic::FORCE);
        }

        void initialize()
        {
            mpND_signal = getSafeNodeDataPtr(mpIn, NodeSignal::VALUE, f);

            mpND_f = getSafeNodeDataPtr(mpP1, NodeMechanic::FORCE);
            mpND_c = getSafeNodeDataPtr(mpP1, NodeMechanic::WAVEVARIABLE);
            mpND_Zx = getSafeNodeDataPtr(mpP1, NodeMechanic::CHARIMP);

            (*mpND_f) = f;
            (*mpND_Zx) = 0.0;
        }

        void simulateOneTimestep()
        {
            (*mpND_c) = (*mpND_signal);
//            if(mpIn->isConnected())				//Temporary RT solution
//                (*mpND_c) = (*mpND_signal);
//            else
//                (*mpND_c) = f;
            (*mpND_Zx) = 0.0;
        }
    };
}

#endif // MECHANICFORCETRANSFORMER_HPP_INCLUDED
<commit_msg>fixed bug in initilize<commit_after>//$Id$

#ifndef MECHANICFORCETRANSFORMER_HPP_INCLUDED
#define MECHANICFORCETRANSFORMER_HPP_INCLUDED

#include "../../ComponentEssentials.h"

namespace hopsan {

    //!
    //! @brief
    //! @ingroup MechanicalComponents
    //!
    class MechanicForceTransformer : public ComponentC
    {

    private:
        double f;
        double *mpND_signal, *mpND_f, *mpND_c, *mpND_Zx;
        Port *mpIn, *mpP1;

    public:
        static Component *Creator()
        {
            return new MechanicForceTransformer("ForceTransformer");
        }

        MechanicForceTransformer(const std::string name) : ComponentC(name)
        {
            //Set member attributes
            f = 0.0;

            //Add ports to the component
            mpIn = addReadPort("in", "NodeSignal", Port::NOTREQUIRED);
            mpP1 = addPowerPort("P1", "NodeMechanic");

            //Register changable parameters to the HOPSAN++ core
            registerParameter("F", "Generated force", "[N]", f);

            disableStartValue(mpP1, NodeMechanic::FORCE);
        }

        void initialize()
        {
            mpND_signal = getSafeNodeDataPtr(mpIn, NodeSignal::VALUE, f);

            mpND_f = getSafeNodeDataPtr(mpP1, NodeMechanic::FORCE);
            mpND_c = getSafeNodeDataPtr(mpP1, NodeMechanic::WAVEVARIABLE);
            mpND_Zx = getSafeNodeDataPtr(mpP1, NodeMechanic::CHARIMP);

            (*mpND_f) = (*mpND_signal);
            (*mpND_Zx) = 0.0;
        }

        void simulateOneTimestep()
        {
            (*mpND_c) = (*mpND_signal);
//            if(mpIn->isConnected())				//Temporary RT solution
//                (*mpND_c) = (*mpND_signal);
//            else
//                (*mpND_c) = f;
            (*mpND_Zx) = 0.0;
            std::stringstream ss;
            ss << "C: " << (*mpND_c);
            addInfoMessage(ss.str());
        }
    };
}

#endif // MECHANICFORCETRANSFORMER_HPP_INCLUDED
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <algorithm>
#include <memory>

struct Car {
	int point_start;
	int point_stop;

	Car(int point_start_, int point_stop_): point_start(point_start_), point_stop(point_stop_) {};
	static std::shared_ptr<Car> newCar(int point_start_, int point_stop_) {
		return std::make_shared<Car>(point_start_, point_stop_);
	}
};

void print_matrix(std::vector<std::vector<int>> & matrix) {
	for (auto row: matrix) {
		for (auto elem: row) {
			std::cout << elem;
		}
		std::cout << "\n";
	}

}
int main () {
	int rows = 4;
	int cols = 4;

	std::vector<std::vector<int>> matrix(rows, std::vector<int>(cols, 0));

	auto car = Car::newCar(1,1);

	//std::for_each(std::begin(matrix), std::end(matrix), [] (auto & v) mutable { for (auto& e: v) std::cin >> e;});

}
<commit_msg>Added heuristic feature example<commit_after>#include <iostream>
#include <vector>
#include <algorithm>
#include <memory>
#include <cmath>

struct Car {
	std::vector<int> point_start;
	std::vector<int> point_stop;
	std::vector<int> point_current;

	Car(std::vector<int> point_start_, std::vector<int> point_stop_): point_start(point_start_), point_stop(point_stop_) {};
};

struct EuclideanDistance {
	inline double operator()(std::shared_ptr<Car> car) {
		const double x_diff = car->point_current[0] - car->point_stop[0];
		const double y_diff = car->point_current[1] - car->point_stop[1];
		const double result = std::sqrt(x_diff * x_diff + y_diff * y_diff);
		return result;
	}

};

template <class H> class Map{
	private:
		std::vector<std::shared_ptr<Car>> cars;
		std::vector<std::vector<int>> matrix;
		int rows;
		int cols;
		H heuristic;
	public:
		Map(int rows_ = 10, int cols_ = 10): rows(rows_), cols(cols_){
			this->matrix=std::vector<std::vector<int>>(rows, std::vector<int>(cols, 0));
		};
		void appendCar(std::shared_ptr<Car> car) {
			this->cars.push_back(car);
			matrix[car->point_start[0]][car->point_start[1]] = this->cars.size();
			car->point_current = car->point_start;
		}

		void appendCars(std::vector<std::shared_ptr<Car>> cars){
			this->cars.insert(this->cars.end(), cars.begin(), cars.end());
		}

		void print() {
			for (auto row: matrix) {
				for (auto elem: row) {
					std::cout << elem << " ";
				}
				std::cout << "\n";
			}
		}
		std::vector<std::vector<int>> generate_new_poses(auto point_current) {
			std::vector<std::vector<int>> new_poses;
			for (int i = -1; i++; i < 2) {
				 for (int j = -1; j++; j < 2) {
					if (i >= 0 && i < this->rows && j >= 0 && j < this->cols) {
				 		new_poses.push_back({point_current[0]+i,point_current[1]+j});
					}
				 }
			}
			return new_poses;
		}

		 void update() {
			 for (auto car: this->cars) {
				auto new_poses = generate_new_poses(car->point_current);
				if (new_poses.size() == 0) {
					std::cout<<"We lost the route\n";
					continue;
				}
				for (auto pose: new_poses) {

					 std::cout << heuristic(car) << "\n";

				}
			 }
		}
};

int main () {
	int rows = 10;
	int cols = 10;

	auto car = std::make_shared<Car>(std::vector{0, 0}, std::vector{5, 5});
	auto car2 = std::make_shared<Car>(std::vector{2, 2}, std::vector{7, 7});
	auto map = Map<EuclideanDistance>();
	map.appendCar(car);
	map.appendCar(car2);
	map.print();

	int time_clocks = 30;
	for (int val = 0;  val < time_clocks; val++) {
		std::cout << "clock time="<<val<<"\n";
		map.update();
	}
	//std::for_each(std::begin(matrix), std::end(matrix), [] (auto & v) mutable { for (auto& e: v) std::cin >> e;});

}
<|endoftext|>


<commit_before>// @(#)root/graf:$Name:  $:$Id: TPaveStats.cxx,v 1.10 2002/03/16 18:41:41 rdm Exp $
// Author: Rene Brun   15/03/99

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "Riostream.h"
#include "TPaveStats.h"
#include "TVirtualPad.h"
#include "TStyle.h"
#include "TFile.h"
#include "TClass.h"
#include "TLatex.h"

ClassImp(TPaveStats)

//______________________________________________________________________________
//  A PaveStats is a PaveText to draw histogram statistics
// The type of information printed in the histogram statistics box
//  can be selected via gStyle->SetOptStat(mode).
//  or by editing an existing TPaveStats object via TPaveStats::SetOptStat(mode).
//  The parameter mode can be = ourmen  (default = 001111)
//    n = 1;  name of histogram is printed
//    e = 1;  number of entries printed
//    m = 1;  mean value printed
//    r = 1;  rms printed
//    u = 1;  number of underflows printed
//    o = 1;  number of overflows printed
//  Example: gStyle->SetOptStat(11);
//           print only name of histogram and number of entries.
//
// The type of information about fit parameters printed in the histogram
// statistics box can be selected via the parameter mode.
//  The parameter mode can be = pcev  (default = 0111)
//    v = 1;  print name/values of parameters
//    e = 1;  print errors (if e=1, v must be 1)
//    c = 1;  print Chisquare/Number of degress of freedom
//    p = 1;  print Probability
//  Example: gStyle->SetOptFit(1011);
//        or this->SetOptFit(1011);
//           print fit probability, parameter names/values and errors.
//

//______________________________________________________________________________
TPaveStats::TPaveStats(): TPaveText()
{
   // TPaveStats default constructor
}

//______________________________________________________________________________
TPaveStats::TPaveStats(Double_t x1, Double_t y1,Double_t x2, Double_t  y2, Option_t *option)
           :TPaveText(x1,y1,x2,y2,option)
{
   // TPaveStats normal constructor

   fOptFit  = gStyle->GetOptFit();
   fOptStat = gStyle->GetOptStat();
   SetFitFormat(gStyle->GetFitFormat());
   SetStatFormat(gStyle->GetStatFormat());
}

//______________________________________________________________________________
TPaveStats::~TPaveStats()
{
   // TPaveStats default destructor
}

//______________________________________________________________________________
void TPaveStats::SaveStyle()
{
   //  Save This TPaveStats options in current style

   gStyle->SetOptFit(fOptFit);
   gStyle->SetOptStat(fOptStat);
   gStyle->SetFitFormat(fFitFormat.Data());
   gStyle->SetStatFormat(fStatFormat.Data());
}

//______________________________________________________________________________
void TPaveStats::SetFitFormat(const char *form)
{
   // Change (i.e. set) the format for printing fit parameters in statistics box

   fFitFormat = form;
}

//______________________________________________________________________________
void TPaveStats::SetStatFormat(const char *form)
{
   // Change (i.e. set) the format for printing statistics

   fStatFormat = form;
}

//______________________________________________________________________________
void TPaveStats::Paint(Option_t *option)
{
   TPave::ConvertNDCtoPad();
   TPave::PaintPave(fX1,fY1,fX2,fY2,GetBorderSize(),option);

   if (!fLines) return;
   Double_t dx = fX2 - fX1;
   Double_t titlesize=0;
   Double_t textsize = GetTextSize();
   Int_t nlines = GetSize();
   if (nlines == 0) nlines = 5;

   // Evaluate text size as a function of the number of lines
   Double_t y1       = gPad->GetY1();
   Double_t y2       = gPad->GetY2();
   Float_t margin    = fMargin*(fX2-fX1);
   Double_t yspace   = (fY2 - fY1)/Double_t(nlines);
   Double_t textsave = textsize;
   TObject *line;
   TLatex *latex, *latex_tok;
   TIter next(fLines);
   Double_t longest = 0, titlelength = 0;
   Double_t w, wtok[2];
   char *st, *sl;
   if (textsize == 0)  {
      textsize = 0.85*yspace/(y2 - y1);
      titlesize = textsize;
      wtok[0] = 0; wtok[1] = 0;
      while ((line = (TObject*) next())) {
	 if (line->IsA() == TLatex::Class()) {
            latex = (TLatex*)line;
            sl = new char[strlen(latex->GetTitle())+1];
            strcpy(sl, latex->GetTitle());
            if (strpbrk(sl, "=") !=0) {
               st = strtok(sl, "=");
               Int_t itok = 0;
               while ( st !=0 ) {
                  latex_tok = new TLatex(0.,0.,st);
                  latex_tok->SetTextSize(textsize);
                  w = latex_tok->GetXsize();
                  if (w > wtok[itok]) wtok[itok] = w;
                  st = strtok(0, "=");
                  ++itok;
                  delete latex_tok;
               }
            } else if (strpbrk(sl, "|") !=0) {
            } else {
               latex->SetTextSize(titlesize);
               titlelength = latex->GetXsize()+2.*margin;
               if (titlelength > 0.98*dx) titlesize *= 0.98*dx/titlelength;
            }
         }
      }
      longest = wtok[0]+wtok[1]+2.*margin;
      if (longest > 0.98*dx) textsize *= 0.98*dx/longest;
      SetTextSize(textsize);
   }
   Double_t ytext = fY2 + 0.5*yspace;
   Double_t xtext = 0;

   // Iterate over all lines
   // Copy pavetext attributes to line attributes if line attributes not set
   next.Reset();
   while ((line = (TObject*) next())) {
      if (line->IsA() == TLatex::Class()) {
         latex = (TLatex*)line;
         ytext -= yspace;
         Double_t xl    = latex->GetX();
         Double_t yl    = latex->GetY();
         Short_t talign = latex->GetTextAlign();
         Color_t tcolor = latex->GetTextColor();
         Style_t tfont  = latex->GetTextFont();
         Size_t  tsize  = latex->GetTextSize();
         if (tcolor == 0) latex->SetTextColor(GetTextColor());
         if (tfont  == 0) latex->SetTextFont(GetTextFont());
         if (tsize  == 0) latex->SetTextSize(GetTextSize());

         sl = new char[strlen(latex->GetTitle())+1];
         strcpy(sl, latex->GetTitle());
         // Draw all the histogram stats except the 2D under/overflow
         if (strpbrk(sl, "=") !=0) {
           st = strtok(sl, "=");
           Int_t halign = 12;
           while ( st !=0 ) {
              latex->SetTextAlign(halign);
              if (halign == 12) xtext = fX1 + margin;
              if (halign == 32) {
                 xtext = fX2 - margin;
		 // Clean trailing blanks in case of right alignment.
                 char *stc;
		 stc=st+strlen(st)-1;
		 while (*stc == ' ') {
                    *stc = '\0';
                    --stc;
                 }
              }
              latex->PaintLatex(xtext,ytext,latex->GetTextAngle(),
                                            latex->GetTextSize(),
                                            st);
              st = strtok(0, "=");
              halign = 32;
           }
	 // Draw the 2D under/overflow
         } else if (strpbrk(sl, "|") !=0) {
           Double_t Yline1 = ytext+yspace/2.;
           Double_t Yline2 = ytext-yspace/2.;
           Double_t Xline1 = (fX2-fX1)/3+fX1;
           Double_t Xline2 = 2*(fX2-fX1)/3+fX1;
           gPad->PaintLine(fX1,Yline1,fX2,Yline1);
           gPad->PaintLine(Xline1,Yline1,Xline1,Yline2);
           gPad->PaintLine(Xline2,Yline1,Xline2,Yline2);
           st = strtok(sl, "|");
	   Int_t Index = 0;
           while ( st !=0 ) {
              latex->SetTextAlign(22);
	      if (Index == 0) xtext = 0.5*(fX1+Xline1);
	      if (Index == 1) xtext = 0.5*(fX1+fX2);
	      if (Index == 2) xtext = 0.5*(Xline2+fX2);
              latex->PaintLatex(xtext,ytext,latex->GetTextAngle(),
                                            latex->GetTextSize(),
                                            st);
              Index++;
              st = strtok(0, "|");
           }
	 // Draw the histogram identifier
         } else {
           latex->SetTextAlign(22);
           xtext = 0.5*(fX1+fX2);
           latex->PaintLatex(xtext,ytext,latex->GetTextAngle(),
                                         titlesize,
                                         sl);
           gPad->PaintLine(fX1,fY2-yspace,fX2,fY2-yspace);
         }
         delete [] sl;

         latex->SetTextAlign(talign);
         latex->SetTextColor(tcolor);
         latex->SetTextFont(tfont);
         latex->SetTextSize(tsize);
         latex->SetX(xl);  //paintlatex modifies fX and fY
         latex->SetY(yl);
      }
   }
   SetTextSize(textsave);
}

//______________________________________________________________________________
void TPaveStats::Streamer(TBuffer &R__b)
{
   // Stream an object of class TPaveStats.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         TPaveStats::Class()->ReadBuffer(R__b, this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      TPaveText::Streamer(R__b);
      R__b >> fOptFit;
      R__b >> fOptStat;
      TFile *file = (TFile*)R__b.GetParent();
      if (R__v > 1 || (file && file->GetVersion() == 22304)) {
         fFitFormat.Streamer(R__b);
         fStatFormat.Streamer(R__b);
      } else {
         SetFitFormat();
         SetStatFormat();
      }
      R__b.CheckByteCount(R__s, R__c, TPaveStats::IsA());
      //====end of old versions

   } else {
      TPaveStats::Class()->WriteBuffer(R__b,this);
   }
}
<commit_msg>Fix a memory leak problem introduced by Olivier in a recent version of TPaveStats::Paint. The char* sl array was not deleted in the first loop.<commit_after>// @(#)root/graf:$Name:  $:$Id: TPaveStats.cxx,v 1.11 2002/03/22 15:58:43 brun Exp $
// Author: Rene Brun   15/03/99

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "Riostream.h"
#include "TPaveStats.h"
#include "TVirtualPad.h"
#include "TStyle.h"
#include "TFile.h"
#include "TClass.h"
#include "TLatex.h"

ClassImp(TPaveStats)

//______________________________________________________________________________
//  A PaveStats is a PaveText to draw histogram statistics
// The type of information printed in the histogram statistics box
//  can be selected via gStyle->SetOptStat(mode).
//  or by editing an existing TPaveStats object via TPaveStats::SetOptStat(mode).
//  The parameter mode can be = ourmen  (default = 001111)
//    n = 1;  name of histogram is printed
//    e = 1;  number of entries printed
//    m = 1;  mean value printed
//    r = 1;  rms printed
//    u = 1;  number of underflows printed
//    o = 1;  number of overflows printed
//  Example: gStyle->SetOptStat(11);
//           print only name of histogram and number of entries.
//
// The type of information about fit parameters printed in the histogram
// statistics box can be selected via the parameter mode.
//  The parameter mode can be = pcev  (default = 0111)
//    v = 1;  print name/values of parameters
//    e = 1;  print errors (if e=1, v must be 1)
//    c = 1;  print Chisquare/Number of degress of freedom
//    p = 1;  print Probability
//  Example: gStyle->SetOptFit(1011);
//        or this->SetOptFit(1011);
//           print fit probability, parameter names/values and errors.
//

//______________________________________________________________________________
TPaveStats::TPaveStats(): TPaveText()
{
   // TPaveStats default constructor
}

//______________________________________________________________________________
TPaveStats::TPaveStats(Double_t x1, Double_t y1,Double_t x2, Double_t  y2, Option_t *option)
           :TPaveText(x1,y1,x2,y2,option)
{
   // TPaveStats normal constructor

   fOptFit  = gStyle->GetOptFit();
   fOptStat = gStyle->GetOptStat();
   SetFitFormat(gStyle->GetFitFormat());
   SetStatFormat(gStyle->GetStatFormat());
}

//______________________________________________________________________________
TPaveStats::~TPaveStats()
{
   // TPaveStats default destructor
}

//______________________________________________________________________________
void TPaveStats::SaveStyle()
{
   //  Save This TPaveStats options in current style

   gStyle->SetOptFit(fOptFit);
   gStyle->SetOptStat(fOptStat);
   gStyle->SetFitFormat(fFitFormat.Data());
   gStyle->SetStatFormat(fStatFormat.Data());
}

//______________________________________________________________________________
void TPaveStats::SetFitFormat(const char *form)
{
   // Change (i.e. set) the format for printing fit parameters in statistics box

   fFitFormat = form;
}

//______________________________________________________________________________
void TPaveStats::SetStatFormat(const char *form)
{
   // Change (i.e. set) the format for printing statistics

   fStatFormat = form;
}

//______________________________________________________________________________
void TPaveStats::Paint(Option_t *option)
{
   TPave::ConvertNDCtoPad();
   TPave::PaintPave(fX1,fY1,fX2,fY2,GetBorderSize(),option);

   if (!fLines) return;
   Double_t dx = fX2 - fX1;
   Double_t titlesize=0;
   Double_t textsize = GetTextSize();
   Int_t nlines = GetSize();
   if (nlines == 0) nlines = 5;

   // Evaluate text size as a function of the number of lines
   Double_t y1       = gPad->GetY1();
   Double_t y2       = gPad->GetY2();
   Float_t margin    = fMargin*(fX2-fX1);
   Double_t yspace   = (fY2 - fY1)/Double_t(nlines);
   Double_t textsave = textsize;
   TObject *line;
   TLatex *latex, *latex_tok;
   TIter next(fLines);
   Double_t longest = 0, titlelength = 0;
   Double_t w, wtok[2];
   char *st, *sl=0;
   if (textsize == 0)  {
      textsize = 0.85*yspace/(y2 - y1);
      titlesize = textsize;
      wtok[0] = 0; wtok[1] = 0;
      while ((line = (TObject*) next())) {
	 if (line->IsA() == TLatex::Class()) {
            latex = (TLatex*)line;
            sl = new char[strlen(latex->GetTitle())+1];
            strcpy(sl, latex->GetTitle());
            if (strpbrk(sl, "=") !=0) {
               st = strtok(sl, "=");
               Int_t itok = 0;
               while ( st !=0 ) {
                  latex_tok = new TLatex(0.,0.,st);
                  latex_tok->SetTextSize(textsize);
                  w = latex_tok->GetXsize();
                  if (w > wtok[itok]) wtok[itok] = w;
                  st = strtok(0, "=");
                  ++itok;
                  delete latex_tok;
               }
            } else if (strpbrk(sl, "|") !=0) {
            } else {
               latex->SetTextSize(titlesize);
               titlelength = latex->GetXsize()+2.*margin;
               if (titlelength > 0.98*dx) titlesize *= 0.98*dx/titlelength;
            }
            delete [] sl; sl = 0;
         }
      }
      longest = wtok[0]+wtok[1]+2.*margin;
      if (longest > 0.98*dx) textsize *= 0.98*dx/longest;
      SetTextSize(textsize);
   }
   Double_t ytext = fY2 + 0.5*yspace;
   Double_t xtext = 0;

   // Iterate over all lines
   // Copy pavetext attributes to line attributes if line attributes not set
   next.Reset();
   while ((line = (TObject*) next())) {
      if (line->IsA() == TLatex::Class()) {
         latex = (TLatex*)line;
         ytext -= yspace;
         Double_t xl    = latex->GetX();
         Double_t yl    = latex->GetY();
         Short_t talign = latex->GetTextAlign();
         Color_t tcolor = latex->GetTextColor();
         Style_t tfont  = latex->GetTextFont();
         Size_t  tsize  = latex->GetTextSize();
         if (tcolor == 0) latex->SetTextColor(GetTextColor());
         if (tfont  == 0) latex->SetTextFont(GetTextFont());
         if (tsize  == 0) latex->SetTextSize(GetTextSize());

         sl = new char[strlen(latex->GetTitle())+1];
         strcpy(sl, latex->GetTitle());
         // Draw all the histogram stats except the 2D under/overflow
         if (strpbrk(sl, "=") !=0) {
           st = strtok(sl, "=");
           Int_t halign = 12;
           while ( st !=0 ) {
              latex->SetTextAlign(halign);
              if (halign == 12) xtext = fX1 + margin;
              if (halign == 32) {
                 xtext = fX2 - margin;
		 // Clean trailing blanks in case of right alignment.
                 char *stc;
		 stc=st+strlen(st)-1;
		 while (*stc == ' ') {
                    *stc = '\0';
                    --stc;
                 }
              }
              latex->PaintLatex(xtext,ytext,latex->GetTextAngle(),
                                            latex->GetTextSize(),
                                            st);
              st = strtok(0, "=");
              halign = 32;
           }
	 // Draw the 2D under/overflow
         } else if (strpbrk(sl, "|") !=0) {
           Double_t Yline1 = ytext+yspace/2.;
           Double_t Yline2 = ytext-yspace/2.;
           Double_t Xline1 = (fX2-fX1)/3+fX1;
           Double_t Xline2 = 2*(fX2-fX1)/3+fX1;
           gPad->PaintLine(fX1,Yline1,fX2,Yline1);
           gPad->PaintLine(Xline1,Yline1,Xline1,Yline2);
           gPad->PaintLine(Xline2,Yline1,Xline2,Yline2);
           st = strtok(sl, "|");
	   Int_t Index = 0;
           while ( st !=0 ) {
              latex->SetTextAlign(22);
	      if (Index == 0) xtext = 0.5*(fX1+Xline1);
	      if (Index == 1) xtext = 0.5*(fX1+fX2);
	      if (Index == 2) xtext = 0.5*(Xline2+fX2);
              latex->PaintLatex(xtext,ytext,latex->GetTextAngle(),
                                            latex->GetTextSize(),
                                            st);
              Index++;
              st = strtok(0, "|");
           }
	 // Draw the histogram identifier
         } else {
           latex->SetTextAlign(22);
           xtext = 0.5*(fX1+fX2);
           latex->PaintLatex(xtext,ytext,latex->GetTextAngle(),
                                         titlesize,
                                         sl);
           gPad->PaintLine(fX1,fY2-yspace,fX2,fY2-yspace);
         }
         delete [] sl;

         latex->SetTextAlign(talign);
         latex->SetTextColor(tcolor);
         latex->SetTextFont(tfont);
         latex->SetTextSize(tsize);
         latex->SetX(xl);  //paintlatex modifies fX and fY
         latex->SetY(yl);
      }
   }
   SetTextSize(textsave);
}

//______________________________________________________________________________
void TPaveStats::Streamer(TBuffer &R__b)
{
   // Stream an object of class TPaveStats.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         TPaveStats::Class()->ReadBuffer(R__b, this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      TPaveText::Streamer(R__b);
      R__b >> fOptFit;
      R__b >> fOptStat;
      TFile *file = (TFile*)R__b.GetParent();
      if (R__v > 1 || (file && file->GetVersion() == 22304)) {
         fFitFormat.Streamer(R__b);
         fStatFormat.Streamer(R__b);
      } else {
         SetFitFormat();
         SetStatFormat();
      }
      R__b.CheckByteCount(R__s, R__c, TPaveStats::IsA());
      //====end of old versions

   } else {
      TPaveStats::Class()->WriteBuffer(R__b,this);
   }
}
<|endoftext|>


<commit_before>// @(#)root/gl:$Id$
// Author:  Matevz Tadel, Jun 2007

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TF2GL.h"

#include <TF2.h>
#include <TF3.h>
#include <TH2.h>
#include <TVirtualPad.h>

#include "TGLSurfacePainter.h"
#include "TGLTF3Painter.h"
#include "TGLAxisPainter.h"

#include "TGLRnrCtx.h"

#include "TGLIncludes.h"

//______________________________________________________________________
//
// GL renderer for TF2.
// TGLPlotPainter is used internally.

ClassImp(TF2GL);

//______________________________________________________________________________
TF2GL::TF2GL() : TGLPlot3D(), fM(0), fH(0)
{
   // Constructor.
}

//______________________________________________________________________________
TF2GL::~TF2GL()
{
   // Destructor.

   delete fH;
}

/**************************************************************************/

//______________________________________________________________________________
Bool_t TF2GL::SetModel(TObject* obj, const Option_t* opt)
{
   // Set model object.

   TString option(opt);
   option.ToLower();

   fM = SetModelDynCast<TF2>(obj);

   fH = (TH2*) fM->CreateHistogram();
   fH->GetZaxis()->SetLimits(fH->GetMinimum(), fH->GetMaximum());

   if (dynamic_cast<TF3*>(fM))
      SetPainter( new TGLTF3Painter((TF3*)fM, fH, 0, &fCoord) );
   else
      SetPainter( new TGLSurfacePainter(fH, 0, &fCoord) );

   if (option.Index("sph") != kNPOS)
      fCoord.SetCoordType(kGLSpherical);
   else if (option.Index("pol") != kNPOS)
      fCoord.SetCoordType(kGLPolar);
   else if (option.Index("cyl") != kNPOS)
      fCoord.SetCoordType(kGLCylindrical);

   fPlotPainter->AddOption(option);
   fPlotPainter->InitGeometry();

   return kTRUE;
}

//______________________________________________________________________________
void TF2GL::SetBBox()
{
   // Setup bounding-box.

   fBoundingBox.Set(fPlotPainter->RefBackBox().Get3DBox());
}

//______________________________________________________________________________
void TF2GL::DirectDraw(TGLRnrCtx & rnrCtx) const
{
   // Render the object.

   fPlotPainter->RefBackBox().FindFrontPoint();

   glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT);

   glEnable(GL_NORMALIZE);
   glDisable(GL_COLOR_MATERIAL);

   fPlotPainter->InitGL();
   fPlotPainter->DrawPlot();

   glDisable(GL_CULL_FACE);
   glPopAttrib();

   // Axes
   TGLAxisPainterBox axe_painter;
   axe_painter.SetUseAxisColors(kFALSE);
   axe_painter.SetFontMode(TGLFont::kPixmap);
   axe_painter.PlotStandard(rnrCtx, fH, fBoundingBox);
}
<commit_msg>In SetModel, check if histogram was actually created (coverititis).<commit_after>// @(#)root/gl:$Id$
// Author:  Matevz Tadel, Jun 2007

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TF2GL.h"

#include <TF2.h>
#include <TF3.h>
#include <TH2.h>
#include <TVirtualPad.h>

#include "TGLSurfacePainter.h"
#include "TGLTF3Painter.h"
#include "TGLAxisPainter.h"

#include "TGLRnrCtx.h"

#include "TGLIncludes.h"

//______________________________________________________________________
//
// GL renderer for TF2.
// TGLPlotPainter is used internally.

ClassImp(TF2GL);

//______________________________________________________________________________
TF2GL::TF2GL() : TGLPlot3D(), fM(0), fH(0)
{
   // Constructor.
}

//______________________________________________________________________________
TF2GL::~TF2GL()
{
   // Destructor.

   delete fH;
}

/**************************************************************************/

//______________________________________________________________________________
Bool_t TF2GL::SetModel(TObject* obj, const Option_t* opt)
{
   // Set model object.

   TString option(opt);
   option.ToLower();

   fM = SetModelDynCast<TF2>(obj);

   fH = (TH2*) fM->CreateHistogram();
   if (!fH) return kFALSE;

   fH->GetZaxis()->SetLimits(fH->GetMinimum(), fH->GetMaximum());

   if (dynamic_cast<TF3*>(fM))
      SetPainter( new TGLTF3Painter((TF3*)fM, fH, 0, &fCoord) );
   else
      SetPainter( new TGLSurfacePainter(fH, 0, &fCoord) );

   if (option.Index("sph") != kNPOS)
      fCoord.SetCoordType(kGLSpherical);
   else if (option.Index("pol") != kNPOS)
      fCoord.SetCoordType(kGLPolar);
   else if (option.Index("cyl") != kNPOS)
      fCoord.SetCoordType(kGLCylindrical);

   fPlotPainter->AddOption(option);
   fPlotPainter->InitGeometry();

   return kTRUE;
}

//______________________________________________________________________________
void TF2GL::SetBBox()
{
   // Setup bounding-box.

   fBoundingBox.Set(fPlotPainter->RefBackBox().Get3DBox());
}

//______________________________________________________________________________
void TF2GL::DirectDraw(TGLRnrCtx & rnrCtx) const
{
   // Render the object.

   fPlotPainter->RefBackBox().FindFrontPoint();

   glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT);

   glEnable(GL_NORMALIZE);
   glDisable(GL_COLOR_MATERIAL);

   fPlotPainter->InitGL();
   fPlotPainter->DrawPlot();

   glDisable(GL_CULL_FACE);
   glPopAttrib();

   // Axes
   TGLAxisPainterBox axe_painter;
   axe_painter.SetUseAxisColors(kFALSE);
   axe_painter.SetFontMode(TGLFont::kPixmap);
   axe_painter.PlotStandard(rnrCtx, fH, fBoundingBox);
}
<|endoftext|>