<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 "chrome/browser/ui/webui/ntp/foreign_session_handler.h"

#include <algorithm>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/i18n/time_formatting.h"
#include "base/memory/scoped_vector.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/webui/session_favicon_source.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/browser/ui/webui/web_ui_util.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/time_format.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_ui.h"

namespace browser_sync {

// Maximum number of session we're going to display on the NTP
static const size_t kMaxSessionsToShow = 10;

// Invalid value, used to note that we don't have a tab or window number.
static const int kInvalidId = -1;

namespace {

// Comparator function for use with std::sort that will sort sessions by
// descending modified_time (i.e., most recent first).
bool SortSessionsByRecency(const SyncedSession* s1, const SyncedSession* s2) {
  return s1->modified_time > s2->modified_time;
}

}  // namepace

ForeignSessionHandler::ForeignSessionHandler() {
}

void ForeignSessionHandler::RegisterMessages() {
  Init();
  web_ui()->RegisterMessageCallback("getForeignSessions",
      base::Bind(&ForeignSessionHandler::HandleGetForeignSessions,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("openForeignSession",
      base::Bind(&ForeignSessionHandler::HandleOpenForeignSession,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("deleteForeignSession",
      base::Bind(&ForeignSessionHandler::HandleDeleteForeignSession,
                 base::Unretained(this)));
}

void ForeignSessionHandler::Init() {
  // TODO(dubroy): Change this to only observe this notification on the current
  // profile, rather than all sources (crbug.com/124717).
  registrar_.Add(this, chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
                 content::NotificationService::AllSources());

  Profile* profile = Profile::FromWebUI(web_ui());
  registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED,
                 content::Source<Profile>(profile));
  registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED,
                 content::Source<Profile>(profile));

  // Add the data source for synced favicons.
  ChromeURLDataManager::AddDataSource(profile,
      new SessionFaviconSource(profile));
}

void ForeignSessionHandler::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  ListValue list_value;
  switch (type) {
    case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE:
    case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED:
    case chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED:
      HandleGetForeignSessions(&list_value);
      break;
    default:
      NOTREACHED();
  }
}

SessionModelAssociator* ForeignSessionHandler::GetModelAssociator() {
  Profile* profile = Profile::FromWebUI(web_ui());
  ProfileSyncService* service =
      ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
  if (service == NULL)
    return NULL;

  // Only return the associator if it exists and it is done syncing sessions.
  SessionModelAssociator* model_associator =
      service->GetSessionModelAssociator();
  if (!service->ShouldPushChanges())
    return NULL;
  return model_associator;
}

bool ForeignSessionHandler::IsTabSyncEnabled() {
  Profile* profile = Profile::FromWebUI(web_ui());
  ProfileSyncService* service =
      ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
  return service && service->GetPreferredDataTypes().Has(syncable::SESSIONS);
}

string16 ForeignSessionHandler::FormatSessionTime(const base::Time& time) {
  // Return a time like "1 hour ago", "2 days ago", etc.
  return TimeFormat::TimeElapsed(base::Time::Now() - time);
}

void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) {
  SessionModelAssociator* associator = GetModelAssociator();
  std::vector<const SyncedSession*> sessions;

  ListValue session_list;
  if (associator && associator->GetAllForeignSessions(&sessions)) {
    // Sort sessions from most recent to least recent.
    std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency);

    // Note: we don't own the SyncedSessions themselves.
    for (size_t i = 0; i < sessions.size() && i < kMaxSessionsToShow; ++i) {
      const SyncedSession* session = sessions[i];
      scoped_ptr<DictionaryValue> session_data(new DictionaryValue());
      session_data->SetString("tag", session->session_tag);
      session_data->SetString("name", session->session_name);
      session_data->SetString("modifiedTime",
                              FormatSessionTime(session->modified_time));
      scoped_ptr<ListValue> window_list(new ListValue());
      for (SyncedSession::SyncedWindowMap::const_iterator it =
           session->windows.begin(); it != session->windows.end(); ++it) {
        SessionWindow* window = it->second;
        scoped_ptr<DictionaryValue> window_data(new DictionaryValue());
        if (SessionWindowToValue(*window, window_data.get()))
          window_list->Append(window_data.release());
      }

      session_data->Set("windows", window_list.release());
      session_list.Append(session_data.release());
    }
  }
  base::FundamentalValue tab_sync_enabled(IsTabSyncEnabled());
  web_ui()->CallJavascriptFunction("ntp.setForeignSessions",
                                   session_list,
                                   tab_sync_enabled);
}

void ForeignSessionHandler::HandleOpenForeignSession(const ListValue* args) {
  size_t num_args = args->GetSize();
  // Expect either 1 or 8 args. For restoring an entire session, only
  // one argument is required -- the session tag. To restore a tab,
  // the additional args required are the window id, the tab id,
  // and 4 properties of the event object (button, altKey, ctrlKey,
  // metaKey, shiftKey) for determining how to open the tab.
  if (num_args != 8U && num_args != 1U) {
    LOG(ERROR) << "openForeignSession called with " << args->GetSize()
               << " arguments.";
    return;
  }

  // Extract the session tag (always provided).
  std::string session_string_value;
  if (!args->GetString(0, &session_string_value)) {
    LOG(ERROR) << "Failed to extract session tag.";
    return;
  }

  // Extract window number.
  std::string window_num_str;
  int window_num = kInvalidId;
  if (num_args >= 2 && (!args->GetString(1, &window_num_str) ||
      !base::StringToInt(window_num_str, &window_num))) {
    LOG(ERROR) << "Failed to extract window number.";
    return;
  }

  // Extract tab id.
  std::string tab_id_str;
  SessionID::id_type tab_id = kInvalidId;
  if (num_args >= 3 && (!args->GetString(2, &tab_id_str) ||
      !base::StringToInt(tab_id_str, &tab_id))) {
    LOG(ERROR) << "Failed to extract tab SessionID.";
    return;
  }

  SessionModelAssociator* associator = GetModelAssociator();

  Profile* profile = Profile::FromWebUI(web_ui());
  if (tab_id != kInvalidId) {
    // We don't actually care about |window_num|, this is just a sanity check.
    DCHECK_LT(kInvalidId, window_num);
    const SessionTab* tab;
    if (!associator->GetForeignTab(session_string_value, tab_id, &tab)) {
      LOG(ERROR) << "Failed to load foreign tab.";
      return;
    }
    WindowOpenDisposition disposition =
        web_ui_util::GetDispositionFromClick(args, 3);
    SessionRestore::RestoreForeignSessionTab(profile, *tab, disposition);
  } else {
    std::vector<const SessionWindow*> windows;
    // Note: we don't own the ForeignSessions themselves.
    if (!associator->GetForeignSession(session_string_value, &windows)) {
      LOG(ERROR) << "ForeignSessionHandler failed to get session data from"
          "SessionModelAssociator.";
      return;
    }
    std::vector<const SessionWindow*>::const_iterator iter_begin =
        windows.begin() + ((window_num == kInvalidId) ? 0 : window_num);
    std::vector<const SessionWindow*>::const_iterator iter_end =
        ((window_num == kInvalidId) ?
        std::vector<const SessionWindow*>::const_iterator(windows.end()) :
        iter_begin + 1);
    SessionRestore::RestoreForeignSessionWindows(profile, iter_begin, iter_end);
  }
}

void ForeignSessionHandler::HandleDeleteForeignSession(const ListValue* args) {
  if (args->GetSize() != 1U) {
    LOG(ERROR) << "Wrong number of args to deleteForeignSession";
    return;
  }

  // Get the session tag argument (required).
  std::string session_tag = UTF16ToUTF8(ExtractStringValue(args));

  SessionModelAssociator* associator = GetModelAssociator();
  if (associator)
    associator->DeleteForeignSession(session_tag);
}

bool ForeignSessionHandler::SessionTabToValue(
    const SessionTab& tab,
    DictionaryValue* dictionary) {
  if (tab.navigations.empty())
    return false;
  int selected_index = tab.current_navigation_index;
  selected_index = std::max(
      0,
      std::min(selected_index,
               static_cast<int>(tab.navigations.size() - 1)));
  const TabNavigation& current_navigation =
      tab.navigations.at(selected_index);
  GURL tab_url = current_navigation.virtual_url();
  if (tab_url == GURL(chrome::kChromeUINewTabURL))
    return false;
  NewTabUI::SetURLTitleAndDirection(dictionary, current_navigation.title(),
                                    tab_url);
  dictionary->SetString("type", "tab");
  dictionary->SetDouble("timestamp",
                        static_cast<double>(tab.timestamp.ToInternalValue()));
  dictionary->SetInteger("sessionId", tab.tab_id.id());
  return true;
}

bool ForeignSessionHandler::SessionWindowToValue(
    const SessionWindow& window,
    DictionaryValue* dictionary) {
  if (window.tabs.empty()) {
    NOTREACHED();
    return false;
  }
  scoped_ptr<ListValue> tab_values(new ListValue());
  for (size_t i = 0; i < window.tabs.size(); ++i) {
    scoped_ptr<DictionaryValue> tab_value(new DictionaryValue());
    if (SessionTabToValue(*window.tabs[i], tab_value.get()))
      tab_values->Append(tab_value.release());
  }
  if (tab_values->GetSize() == 0)
    return false;
  dictionary->SetString("type", "window");
  dictionary->SetDouble("timestamp",
      static_cast<double>(window.timestamp.ToInternalValue()));
  dictionary->SetInteger("sessionId", window.window_id.id());
  dictionary->Set("tabs", tab_values.release());
  return true;
}

}  // namespace browser_sync
<commit_msg>NTP: Fix possible segfault in Other Devices menu.<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 "chrome/browser/ui/webui/ntp/foreign_session_handler.h"

#include <algorithm>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/i18n/time_formatting.h"
#include "base/memory/scoped_vector.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/webui/session_favicon_source.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/browser/ui/webui/web_ui_util.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/time_format.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_ui.h"

namespace browser_sync {

// Maximum number of session we're going to display on the NTP
static const size_t kMaxSessionsToShow = 10;

// Invalid value, used to note that we don't have a tab or window number.
static const int kInvalidId = -1;

namespace {

// Comparator function for use with std::sort that will sort sessions by
// descending modified_time (i.e., most recent first).
bool SortSessionsByRecency(const SyncedSession* s1, const SyncedSession* s2) {
  return s1->modified_time > s2->modified_time;
}

}  // namepace

ForeignSessionHandler::ForeignSessionHandler() {
}

void ForeignSessionHandler::RegisterMessages() {
  Init();
  web_ui()->RegisterMessageCallback("getForeignSessions",
      base::Bind(&ForeignSessionHandler::HandleGetForeignSessions,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("openForeignSession",
      base::Bind(&ForeignSessionHandler::HandleOpenForeignSession,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("deleteForeignSession",
      base::Bind(&ForeignSessionHandler::HandleDeleteForeignSession,
                 base::Unretained(this)));
}

void ForeignSessionHandler::Init() {
  // TODO(dubroy): Change this to only observe this notification on the current
  // profile, rather than all sources (crbug.com/124717).
  registrar_.Add(this, chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
                 content::NotificationService::AllSources());

  Profile* profile = Profile::FromWebUI(web_ui());
  registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED,
                 content::Source<Profile>(profile));
  registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED,
                 content::Source<Profile>(profile));

  // Add the data source for synced favicons.
  ChromeURLDataManager::AddDataSource(profile,
      new SessionFaviconSource(profile));
}

void ForeignSessionHandler::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  ListValue list_value;
  switch (type) {
    case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE:
    case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED:
    case chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED:
      HandleGetForeignSessions(&list_value);
      break;
    default:
      NOTREACHED();
  }
}

SessionModelAssociator* ForeignSessionHandler::GetModelAssociator() {
  Profile* profile = Profile::FromWebUI(web_ui());
  ProfileSyncService* service =
      ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
  if (service == NULL)
    return NULL;

  // Only return the associator if it exists and it is done syncing sessions.
  SessionModelAssociator* model_associator =
      service->GetSessionModelAssociator();
  if (!service->ShouldPushChanges())
    return NULL;
  return model_associator;
}

bool ForeignSessionHandler::IsTabSyncEnabled() {
  Profile* profile = Profile::FromWebUI(web_ui());
  ProfileSyncService* service =
      ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
  return service && service->GetPreferredDataTypes().Has(syncable::SESSIONS);
}

string16 ForeignSessionHandler::FormatSessionTime(const base::Time& time) {
  // Return a time like "1 hour ago", "2 days ago", etc.
  return TimeFormat::TimeElapsed(base::Time::Now() - time);
}

void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) {
  SessionModelAssociator* associator = GetModelAssociator();
  std::vector<const SyncedSession*> sessions;

  ListValue session_list;
  if (associator && associator->GetAllForeignSessions(&sessions)) {
    // Sort sessions from most recent to least recent.
    std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency);

    // Note: we don't own the SyncedSessions themselves.
    for (size_t i = 0; i < sessions.size() && i < kMaxSessionsToShow; ++i) {
      const SyncedSession* session = sessions[i];
      scoped_ptr<DictionaryValue> session_data(new DictionaryValue());
      session_data->SetString("tag", session->session_tag);
      session_data->SetString("name", session->session_name);
      session_data->SetString("modifiedTime",
                              FormatSessionTime(session->modified_time));
      scoped_ptr<ListValue> window_list(new ListValue());
      for (SyncedSession::SyncedWindowMap::const_iterator it =
           session->windows.begin(); it != session->windows.end(); ++it) {
        SessionWindow* window = it->second;
        scoped_ptr<DictionaryValue> window_data(new DictionaryValue());
        if (SessionWindowToValue(*window, window_data.get()))
          window_list->Append(window_data.release());
      }

      session_data->Set("windows", window_list.release());
      session_list.Append(session_data.release());
    }
  }
  base::FundamentalValue tab_sync_enabled(IsTabSyncEnabled());
  web_ui()->CallJavascriptFunction("ntp.setForeignSessions",
                                   session_list,
                                   tab_sync_enabled);
}

void ForeignSessionHandler::HandleOpenForeignSession(const ListValue* args) {
  size_t num_args = args->GetSize();
  // Expect either 1 or 8 args. For restoring an entire session, only
  // one argument is required -- the session tag. To restore a tab,
  // the additional args required are the window id, the tab id,
  // and 4 properties of the event object (button, altKey, ctrlKey,
  // metaKey, shiftKey) for determining how to open the tab.
  if (num_args != 8U && num_args != 1U) {
    LOG(ERROR) << "openForeignSession called with " << args->GetSize()
               << " arguments.";
    return;
  }

  // Extract the session tag (always provided).
  std::string session_string_value;
  if (!args->GetString(0, &session_string_value)) {
    LOG(ERROR) << "Failed to extract session tag.";
    return;
  }

  // Extract window number.
  std::string window_num_str;
  int window_num = kInvalidId;
  if (num_args >= 2 && (!args->GetString(1, &window_num_str) ||
      !base::StringToInt(window_num_str, &window_num))) {
    LOG(ERROR) << "Failed to extract window number.";
    return;
  }

  // Extract tab id.
  std::string tab_id_str;
  SessionID::id_type tab_id = kInvalidId;
  if (num_args >= 3 && (!args->GetString(2, &tab_id_str) ||
      !base::StringToInt(tab_id_str, &tab_id))) {
    LOG(ERROR) << "Failed to extract tab SessionID.";
    return;
  }

  SessionModelAssociator* associator = GetModelAssociator();
  if (!associator)
    return;

  Profile* profile = Profile::FromWebUI(web_ui());
  if (tab_id != kInvalidId) {
    // We don't actually care about |window_num|, this is just a sanity check.
    DCHECK_LT(kInvalidId, window_num);
    const SessionTab* tab;
    if (!associator->GetForeignTab(session_string_value, tab_id, &tab)) {
      LOG(ERROR) << "Failed to load foreign tab.";
      return;
    }
    WindowOpenDisposition disposition =
        web_ui_util::GetDispositionFromClick(args, 3);
    SessionRestore::RestoreForeignSessionTab(profile, *tab, disposition);
  } else {
    std::vector<const SessionWindow*> windows;
    // Note: we don't own the ForeignSessions themselves.
    if (!associator->GetForeignSession(session_string_value, &windows)) {
      LOG(ERROR) << "ForeignSessionHandler failed to get session data from"
          "SessionModelAssociator.";
      return;
    }
    std::vector<const SessionWindow*>::const_iterator iter_begin =
        windows.begin() + ((window_num == kInvalidId) ? 0 : window_num);
    std::vector<const SessionWindow*>::const_iterator iter_end =
        ((window_num == kInvalidId) ?
        std::vector<const SessionWindow*>::const_iterator(windows.end()) :
        iter_begin + 1);
    SessionRestore::RestoreForeignSessionWindows(profile, iter_begin, iter_end);
  }
}

void ForeignSessionHandler::HandleDeleteForeignSession(const ListValue* args) {
  if (args->GetSize() != 1U) {
    LOG(ERROR) << "Wrong number of args to deleteForeignSession";
    return;
  }

  // Get the session tag argument (required).
  std::string session_tag = UTF16ToUTF8(ExtractStringValue(args));

  SessionModelAssociator* associator = GetModelAssociator();
  if (associator)
    associator->DeleteForeignSession(session_tag);
}

bool ForeignSessionHandler::SessionTabToValue(
    const SessionTab& tab,
    DictionaryValue* dictionary) {
  if (tab.navigations.empty())
    return false;
  int selected_index = tab.current_navigation_index;
  selected_index = std::max(
      0,
      std::min(selected_index,
               static_cast<int>(tab.navigations.size() - 1)));
  const TabNavigation& current_navigation =
      tab.navigations.at(selected_index);
  GURL tab_url = current_navigation.virtual_url();
  if (tab_url == GURL(chrome::kChromeUINewTabURL))
    return false;
  NewTabUI::SetURLTitleAndDirection(dictionary, current_navigation.title(),
                                    tab_url);
  dictionary->SetString("type", "tab");
  dictionary->SetDouble("timestamp",
                        static_cast<double>(tab.timestamp.ToInternalValue()));
  dictionary->SetInteger("sessionId", tab.tab_id.id());
  return true;
}

bool ForeignSessionHandler::SessionWindowToValue(
    const SessionWindow& window,
    DictionaryValue* dictionary) {
  if (window.tabs.empty()) {
    NOTREACHED();
    return false;
  }
  scoped_ptr<ListValue> tab_values(new ListValue());
  for (size_t i = 0; i < window.tabs.size(); ++i) {
    scoped_ptr<DictionaryValue> tab_value(new DictionaryValue());
    if (SessionTabToValue(*window.tabs[i], tab_value.get()))
      tab_values->Append(tab_value.release());
  }
  if (tab_values->GetSize() == 0)
    return false;
  dictionary->SetString("type", "window");
  dictionary->SetDouble("timestamp",
      static_cast<double>(window.timestamp.ToInternalValue()));
  dictionary->SetInteger("sessionId", window.window_id.id());
  dictionary->Set("tabs", tab_values.release());
  return true;
}

}  // namespace browser_sync
<|endoftext|>


<commit_before>/**
 * \file TypedBaseFilter.hxx
 */

#include <ATK/Core/TypedBaseFilter.h>
#include <ATK/Core/Utilities.h>

#include <complex>
#include <cstdint>
#include <type_traits>

#include <boost/mpl/contains.hpp>
#include <boost/mpl/distance.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>

#if USE_SIMD
#include <simdpp/simd.h>
#endif

namespace
{
  const size_t alignment = 32;

  typedef boost::mpl::vector<std::int16_t, std::int32_t, int64_t, float, double, std::complex<float>, std::complex<double> > ConversionTypes;

  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::mpl::empty<Vector>::type, void>::type
    convert_scalar_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    throw std::runtime_error("Cannot convert types for these filters");
  }

  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::is_arithmetic<typename boost::mpl::front<Vector>::type>::type, typename boost::disable_if<typename boost::mpl::empty<Vector>::type, void>::type>::type
  convert_scalar_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    convert_scalar_array<typename boost::mpl::pop_front<Vector>::type, DataType>(filter, port, converted_input, size, type - 1);
  }

  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::is_arithmetic<typename boost::mpl::front<Vector>::type>::type, typename boost::disable_if<typename boost::mpl::empty<Vector>::type, void>::type>::type
    convert_scalar_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    if(type != 0)
    {
      convert_scalar_array<typename boost::mpl::pop_front<Vector>::type, DataType>(filter, port, converted_input, size, type - 1);
    }
    else
    {
      typedef typename boost::mpl::front<Vector>::type InputOriginalType;
      InputOriginalType* original_input_array = static_cast<ATK::TypedBaseFilter<InputOriginalType>*>(filter)->get_output_array(port);
      ATK::ConversionUtilities<InputOriginalType, DataType>::convert_array(original_input_array, converted_input, size);
    }
  }

  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::mpl::empty<Vector>::type, void>::type
    convert_complex_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    throw std::runtime_error("Can't convert types");
  }

  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::mpl::empty<Vector>::type, void>::type
    convert_complex_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    assert(type >= 0);
    if (type != 0)
    {
      convert_complex_array<typename boost::mpl::pop_front<Vector>::type, DataType>(filter, port, converted_input, size, type - 1);
    }
    else
    {
      typedef typename boost::mpl::front<Vector>::type InputOriginalType;
      InputOriginalType* original_input_array = static_cast<ATK::TypedBaseFilter<InputOriginalType>*>(filter)->get_output_array(port);
      ATK::ConversionUtilities<InputOriginalType, DataType>::convert_array(original_input_array, converted_input, size);
    }
  }

  /// Conversion function for arithmetic types
  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::is_arithmetic<DataType>::type, void>::type convert_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    convert_scalar_array<Vector, DataType>(filter, port, converted_input, size, type);
  }

  /// Conversion function for other types not contained in ConversionTypes (no conversion in that case, just copy)
  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::is_arithmetic<DataType>::type, typename boost::disable_if<typename boost::mpl::contains<Vector, DataType>::type, void>::type>::type convert_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    assert(dynamic_cast<ATK::TypedBaseFilter<DataType>*>(filter));
    DataType* original_input_array = static_cast<ATK::TypedBaseFilter<DataType>*>(filter)->get_output_array(port);
    ATK::ConversionUtilities<DataType, DataType>::convert_array(original_input_array, converted_input, size);
  }

  /// Conversion function for std::complex contained in ConversionTypes
  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::is_arithmetic<DataType>::type, typename boost::enable_if<typename boost::mpl::contains<Vector, DataType>::type, void>::type>::type convert_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    convert_complex_array<Vector, DataType>(filter, port, converted_input, size, type);
  }

  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::mpl::contains<Vector, DataType>::type, int>::type get_type()
  {
    return boost::mpl::distance<boost::mpl::begin<ConversionTypes>::type, typename boost::mpl::find<ConversionTypes, DataType>::type >::value;
  }

  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::mpl::contains<Vector, DataType>::type, int>::type get_type()
  {
    return -1;
  }
}

namespace ATK
{
  template<typename DataType_, typename DataType__>
  TypedBaseFilter<DataType_, DataType__>::TypedBaseFilter(std::size_t nb_input_ports, std::size_t nb_output_ports)
  :Parent(nb_input_ports, nb_output_ports), converted_inputs_delay(nb_input_ports), converted_inputs(nb_input_ports, nullptr), converted_inputs_size(nb_input_ports, 0), outputs_delay(nb_output_ports), outputs(nb_output_ports, nullptr), outputs_size(nb_output_ports, 0), default_input(nb_input_ports, TypeTraits<DataType_>::Zero()), default_output(nb_output_ports, TypeTraits<DataType__>::Zero())
  {
  }

  template<typename DataType_, typename DataType__>
  TypedBaseFilter<DataType_, DataType__>::TypedBaseFilter(TypedBaseFilter&& other)
    : Parent(std::move(other)), converted_inputs_delay(std::move(other.converted_inputs_delay)), converted_inputs(std::move(other.converted_inputs)), converted_inputs_size(std::move(other.converted_inputs_size)), outputs_delay(std::move(other.outputs_delay)), outputs(std::move(other.outputs)), outputs_size(std::move(other.outputs_size)), default_input(std::move(other.default_input)), default_output(std::move(other.default_output))
  {
  }

  template<typename DataType_, typename DataType__>
  TypedBaseFilter<DataType_, DataType__>::~TypedBaseFilter()
  {
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::set_nb_input_ports(std::size_t nb_ports)
  {
    if(nb_ports == nb_input_ports)
      return;
    Parent::set_nb_input_ports(nb_ports);
    converted_inputs_delay = std::vector<std::unique_ptr<DataTypeInput[]> >(nb_ports);
    converted_inputs.assign(nb_ports, nullptr);
    converted_inputs_size.assign(nb_ports, 0);
    default_input.assign(nb_ports, TypeTraits<DataTypeInput>::Zero());
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::set_nb_output_ports(std::size_t nb_ports)
  {
    if(nb_ports == nb_output_ports)
      return;
    Parent::set_nb_output_ports(nb_ports);
    outputs_delay = std::vector<std::unique_ptr<DataTypeOutput[]> >(nb_ports);
    outputs.assign(nb_ports, nullptr);
    outputs_size.assign(nb_ports, 0);
    default_output.assign(nb_ports, TypeTraits<DataTypeOutput>::Zero());
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::process_impl(std::size_t size) const
  {
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::prepare_process(std::size_t size)
  {
    convert_inputs(size);
  }

  template<typename DataType_, typename DataType__>
  int TypedBaseFilter<DataType_, DataType__>::get_type() const
  {
    return ::get_type<ConversionTypes, DataType__>();
  }

  template<typename DataType_, typename DataType__>
  DataType__* TypedBaseFilter<DataType_, DataType__>::get_output_array(std::size_t port) const
  {
    return outputs[port];
  }

  template<typename DataType_, typename DataType__>
  std::size_t TypedBaseFilter<DataType_, DataType__>::get_output_array_size() const
  {
    return outputs_size.front();
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::convert_inputs(std::size_t size)
  {
    for(unsigned int i = 0; i < nb_input_ports; ++i)
    {
      // if the input delay is smaller than the preceding filter output delay, we may have overlap
      // if the types are identical and if the type is not -1 (an unknown type)
      // if we have overlap, don't copy anything at all
      if((input_delay <= connections[i].second->get_output_delay()) && (connections[i].second->get_type() == get_type()) && (get_type() != -1))
      {
        converted_inputs[i] = reinterpret_cast<const TypedBaseFilter<DataTypeInput>* >(connections[i].second)->get_output_array(connections[i].first);
        converted_inputs_size[i] = size;
        continue;
      }
      auto input_size = converted_inputs_size[i];
      if(input_size < size)
      {
        std::unique_ptr<DataTypeInput[]> temp(new DataTypeInput[static_cast<unsigned int>(input_delay + size + (alignment - 1) / sizeof(DataTypeInput))]);
        auto my_temp_ptr = reinterpret_cast<void*>(temp.get());
        size_t space;
        std::align(alignment, sizeof(DataTypeInput), my_temp_ptr, space);
        auto temp_ptr = reinterpret_cast<DataTypeInput*>(my_temp_ptr);
        if(input_size == 0)
        {
          for(unsigned int j = 0; j < input_delay; ++j)
          {
            temp_ptr[j] = default_input[i];
          }
        }
        else
        {
          const auto input_ptr = converted_inputs[i];
          for(int j = 0; j < static_cast<int>(input_delay); ++j)
          {
            temp_ptr[j] = input_ptr[last_size + j - input_delay];
          }
        }

        converted_inputs_delay[i] = std::move(temp);
        converted_inputs[i] = temp_ptr + input_delay;
        converted_inputs_size[i] = size;
      }
      else
      {
        auto my_last_size = static_cast<int64_t>(last_size) * input_sampling_rate / output_sampling_rate;
        const auto input_ptr = converted_inputs[i];
        for(int j = 0; j < static_cast<int>(input_delay); ++j)
        {
          input_ptr[j - input_delay] = input_ptr[my_last_size + j - input_delay];
        }
      }
      convert_array<ConversionTypes, DataTypeInput>(connections[i].second, connections[i].first, converted_inputs[i], size, connections[i].second->get_type());
    }
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::prepare_outputs(std::size_t size)
  {
    for(unsigned int i = 0; i < nb_output_ports; ++i)
    {
      auto output_size = outputs_size[i];
      if(output_size < size)
      {
        std::unique_ptr<DataTypeOutput[]> temp(new DataTypeOutput[static_cast<unsigned int>(output_delay + size + (alignment - 1) / sizeof(DataTypeOutput))]);
        auto my_temp_ptr = reinterpret_cast<void*>(temp.get());
        size_t space;
        std::align(alignment, sizeof(DataTypeOutput), my_temp_ptr, space);
        auto temp_ptr = reinterpret_cast<DataTypeOutput*>(my_temp_ptr);
        if(output_size == 0)
        {
          for(unsigned int j = 0; j < output_delay; ++j)
          {
            temp_ptr[j] = default_output[i];
          }
        }
        else
        {
          const auto output_ptr = outputs[i];
          for(int j = 0; j < static_cast<int>(output_delay); ++j)
          {
            temp_ptr[j] = output_ptr[last_size + j - output_delay];
          }
        }

        outputs_delay[i] = std::move(temp);
        outputs[i] = temp_ptr + output_delay;
        outputs_size[i] = size;
      }
      else
      {
        const auto output_ptr = outputs[i];
        for(int j = 0; j < static_cast<int>(output_delay); ++j)
        {
          output_ptr[j - output_delay] = output_ptr[last_size + j - output_delay];
        }
      }
    }
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::full_setup()
  {
    // Reset input arrays
    converted_inputs_delay = std::vector<std::unique_ptr<DataTypeInput[]> >(nb_input_ports);
    converted_inputs.assign(nb_input_ports, nullptr);
    converted_inputs_size.assign(nb_input_ports, 0);

    // Reset output arrays
    outputs_delay = std::vector<std::unique_ptr<DataTypeOutput[]> >(nb_output_ports);
    outputs.assign(nb_output_ports, nullptr);
    outputs_size.assign(nb_output_ports, 0);

    Parent::full_setup();
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::set_input_port(std::size_t input_port, BaseFilter* filter, std::size_t output_port)
  {
    Parent::set_input_port(input_port, filter, output_port);
    converted_inputs_size[input_port] = 0;
  }
}
<commit_msg>OK, the dynamic cast is wrong. Not sure yet how to make it proper, although the static cast works by shear luck.<commit_after>/**
 * \file TypedBaseFilter.hxx
 */

#include <ATK/Core/TypedBaseFilter.h>
#include <ATK/Core/Utilities.h>

#include <complex>
#include <cstdint>
#include <type_traits>

#include <boost/mpl/contains.hpp>
#include <boost/mpl/distance.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>

#if USE_SIMD
#include <simdpp/simd.h>
#endif

namespace
{
  const size_t alignment = 32;

  typedef boost::mpl::vector<std::int16_t, std::int32_t, int64_t, float, double, std::complex<float>, std::complex<double> > ConversionTypes;

  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::mpl::empty<Vector>::type, void>::type
    convert_scalar_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    throw std::runtime_error("Cannot convert types for these filters");
  }

  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::is_arithmetic<typename boost::mpl::front<Vector>::type>::type, typename boost::disable_if<typename boost::mpl::empty<Vector>::type, void>::type>::type
  convert_scalar_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    convert_scalar_array<typename boost::mpl::pop_front<Vector>::type, DataType>(filter, port, converted_input, size, type - 1);
  }

  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::is_arithmetic<typename boost::mpl::front<Vector>::type>::type, typename boost::disable_if<typename boost::mpl::empty<Vector>::type, void>::type>::type
    convert_scalar_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    if(type != 0)
    {
      convert_scalar_array<typename boost::mpl::pop_front<Vector>::type, DataType>(filter, port, converted_input, size, type - 1);
    }
    else
    {
      typedef typename boost::mpl::front<Vector>::type InputOriginalType;
      InputOriginalType* original_input_array = static_cast<ATK::TypedBaseFilter<InputOriginalType>*>(filter)->get_output_array(port);
      ATK::ConversionUtilities<InputOriginalType, DataType>::convert_array(original_input_array, converted_input, size);
    }
  }

  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::mpl::empty<Vector>::type, void>::type
    convert_complex_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    throw std::runtime_error("Can't convert types");
  }

  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::mpl::empty<Vector>::type, void>::type
    convert_complex_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    assert(type >= 0);
    if (type != 0)
    {
      convert_complex_array<typename boost::mpl::pop_front<Vector>::type, DataType>(filter, port, converted_input, size, type - 1);
    }
    else
    {
      typedef typename boost::mpl::front<Vector>::type InputOriginalType;
      InputOriginalType* original_input_array = static_cast<ATK::TypedBaseFilter<InputOriginalType>*>(filter)->get_output_array(port);
      ATK::ConversionUtilities<InputOriginalType, DataType>::convert_array(original_input_array, converted_input, size);
    }
  }

  /// Conversion function for arithmetic types
  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::is_arithmetic<DataType>::type, void>::type convert_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    convert_scalar_array<Vector, DataType>(filter, port, converted_input, size, type);
  }

  /// Conversion function for other types not contained in ConversionTypes (no conversion in that case, just copy)
  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::is_arithmetic<DataType>::type, typename boost::disable_if<typename boost::mpl::contains<Vector, DataType>::type, void>::type>::type convert_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    //assert(dynamic_cast<ATK::TypedBaseFilter<DataType>*>(filter)); OK, this is wrong for now
    DataType* original_input_array = static_cast<ATK::TypedBaseFilter<DataType>*>(filter)->get_output_array(port);
    ATK::ConversionUtilities<DataType, DataType>::convert_array(original_input_array, converted_input, size);
  }

  /// Conversion function for std::complex contained in ConversionTypes
  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::is_arithmetic<DataType>::type, typename boost::enable_if<typename boost::mpl::contains<Vector, DataType>::type, void>::type>::type convert_array(ATK::BaseFilter* filter, unsigned int port, DataType* converted_input, std::size_t size, int type)
  {
    convert_complex_array<Vector, DataType>(filter, port, converted_input, size, type);
  }

  template<typename Vector, typename DataType>
  typename boost::enable_if<typename boost::mpl::contains<Vector, DataType>::type, int>::type get_type()
  {
    return boost::mpl::distance<boost::mpl::begin<ConversionTypes>::type, typename boost::mpl::find<ConversionTypes, DataType>::type >::value;
  }

  template<typename Vector, typename DataType>
  typename boost::disable_if<typename boost::mpl::contains<Vector, DataType>::type, int>::type get_type()
  {
    return -1;
  }
}

namespace ATK
{
  template<typename DataType_, typename DataType__>
  TypedBaseFilter<DataType_, DataType__>::TypedBaseFilter(std::size_t nb_input_ports, std::size_t nb_output_ports)
  :Parent(nb_input_ports, nb_output_ports), converted_inputs_delay(nb_input_ports), converted_inputs(nb_input_ports, nullptr), converted_inputs_size(nb_input_ports, 0), outputs_delay(nb_output_ports), outputs(nb_output_ports, nullptr), outputs_size(nb_output_ports, 0), default_input(nb_input_ports, TypeTraits<DataType_>::Zero()), default_output(nb_output_ports, TypeTraits<DataType__>::Zero())
  {
  }

  template<typename DataType_, typename DataType__>
  TypedBaseFilter<DataType_, DataType__>::TypedBaseFilter(TypedBaseFilter&& other)
    : Parent(std::move(other)), converted_inputs_delay(std::move(other.converted_inputs_delay)), converted_inputs(std::move(other.converted_inputs)), converted_inputs_size(std::move(other.converted_inputs_size)), outputs_delay(std::move(other.outputs_delay)), outputs(std::move(other.outputs)), outputs_size(std::move(other.outputs_size)), default_input(std::move(other.default_input)), default_output(std::move(other.default_output))
  {
  }

  template<typename DataType_, typename DataType__>
  TypedBaseFilter<DataType_, DataType__>::~TypedBaseFilter()
  {
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::set_nb_input_ports(std::size_t nb_ports)
  {
    if(nb_ports == nb_input_ports)
      return;
    Parent::set_nb_input_ports(nb_ports);
    converted_inputs_delay = std::vector<std::unique_ptr<DataTypeInput[]> >(nb_ports);
    converted_inputs.assign(nb_ports, nullptr);
    converted_inputs_size.assign(nb_ports, 0);
    default_input.assign(nb_ports, TypeTraits<DataTypeInput>::Zero());
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::set_nb_output_ports(std::size_t nb_ports)
  {
    if(nb_ports == nb_output_ports)
      return;
    Parent::set_nb_output_ports(nb_ports);
    outputs_delay = std::vector<std::unique_ptr<DataTypeOutput[]> >(nb_ports);
    outputs.assign(nb_ports, nullptr);
    outputs_size.assign(nb_ports, 0);
    default_output.assign(nb_ports, TypeTraits<DataTypeOutput>::Zero());
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::process_impl(std::size_t size) const
  {
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::prepare_process(std::size_t size)
  {
    convert_inputs(size);
  }

  template<typename DataType_, typename DataType__>
  int TypedBaseFilter<DataType_, DataType__>::get_type() const
  {
    return ::get_type<ConversionTypes, DataType__>();
  }

  template<typename DataType_, typename DataType__>
  DataType__* TypedBaseFilter<DataType_, DataType__>::get_output_array(std::size_t port) const
  {
    return outputs[port];
  }

  template<typename DataType_, typename DataType__>
  std::size_t TypedBaseFilter<DataType_, DataType__>::get_output_array_size() const
  {
    return outputs_size.front();
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::convert_inputs(std::size_t size)
  {
    for(unsigned int i = 0; i < nb_input_ports; ++i)
    {
      // if the input delay is smaller than the preceding filter output delay, we may have overlap
      // if the types are identical and if the type is not -1 (an unknown type)
      // if we have overlap, don't copy anything at all
      if((input_delay <= connections[i].second->get_output_delay()) && (connections[i].second->get_type() == get_type()) && (get_type() != -1))
      {
        converted_inputs[i] = reinterpret_cast<const TypedBaseFilter<DataTypeInput>* >(connections[i].second)->get_output_array(connections[i].first);
        converted_inputs_size[i] = size;
        continue;
      }
      auto input_size = converted_inputs_size[i];
      if(input_size < size)
      {
        std::unique_ptr<DataTypeInput[]> temp(new DataTypeInput[static_cast<unsigned int>(input_delay + size + (alignment - 1) / sizeof(DataTypeInput))]);
        auto my_temp_ptr = reinterpret_cast<void*>(temp.get());
        size_t space;
        std::align(alignment, sizeof(DataTypeInput), my_temp_ptr, space);
        auto temp_ptr = reinterpret_cast<DataTypeInput*>(my_temp_ptr);
        if(input_size == 0)
        {
          for(unsigned int j = 0; j < input_delay; ++j)
          {
            temp_ptr[j] = default_input[i];
          }
        }
        else
        {
          const auto input_ptr = converted_inputs[i];
          for(int j = 0; j < static_cast<int>(input_delay); ++j)
          {
            temp_ptr[j] = input_ptr[last_size + j - input_delay];
          }
        }

        converted_inputs_delay[i] = std::move(temp);
        converted_inputs[i] = temp_ptr + input_delay;
        converted_inputs_size[i] = size;
      }
      else
      {
        auto my_last_size = static_cast<int64_t>(last_size) * input_sampling_rate / output_sampling_rate;
        const auto input_ptr = converted_inputs[i];
        for(int j = 0; j < static_cast<int>(input_delay); ++j)
        {
          input_ptr[j - input_delay] = input_ptr[my_last_size + j - input_delay];
        }
      }
      convert_array<ConversionTypes, DataTypeInput>(connections[i].second, connections[i].first, converted_inputs[i], size, connections[i].second->get_type());
    }
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::prepare_outputs(std::size_t size)
  {
    for(unsigned int i = 0; i < nb_output_ports; ++i)
    {
      auto output_size = outputs_size[i];
      if(output_size < size)
      {
        std::unique_ptr<DataTypeOutput[]> temp(new DataTypeOutput[static_cast<unsigned int>(output_delay + size + (alignment - 1) / sizeof(DataTypeOutput))]);
        auto my_temp_ptr = reinterpret_cast<void*>(temp.get());
        size_t space;
        std::align(alignment, sizeof(DataTypeOutput), my_temp_ptr, space);
        auto temp_ptr = reinterpret_cast<DataTypeOutput*>(my_temp_ptr);
        if(output_size == 0)
        {
          for(unsigned int j = 0; j < output_delay; ++j)
          {
            temp_ptr[j] = default_output[i];
          }
        }
        else
        {
          const auto output_ptr = outputs[i];
          for(int j = 0; j < static_cast<int>(output_delay); ++j)
          {
            temp_ptr[j] = output_ptr[last_size + j - output_delay];
          }
        }

        outputs_delay[i] = std::move(temp);
        outputs[i] = temp_ptr + output_delay;
        outputs_size[i] = size;
      }
      else
      {
        const auto output_ptr = outputs[i];
        for(int j = 0; j < static_cast<int>(output_delay); ++j)
        {
          output_ptr[j - output_delay] = output_ptr[last_size + j - output_delay];
        }
      }
    }
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::full_setup()
  {
    // Reset input arrays
    converted_inputs_delay = std::vector<std::unique_ptr<DataTypeInput[]> >(nb_input_ports);
    converted_inputs.assign(nb_input_ports, nullptr);
    converted_inputs_size.assign(nb_input_ports, 0);

    // Reset output arrays
    outputs_delay = std::vector<std::unique_ptr<DataTypeOutput[]> >(nb_output_ports);
    outputs.assign(nb_output_ports, nullptr);
    outputs_size.assign(nb_output_ports, 0);

    Parent::full_setup();
  }

  template<typename DataType_, typename DataType__>
  void TypedBaseFilter<DataType_, DataType__>::set_input_port(std::size_t input_port, BaseFilter* filter, std::size_t output_port)
  {
    Parent::set_input_port(input_port, filter, output_port);
    converted_inputs_size[input_port] = 0;
  }
}
<|endoftext|>


<commit_before>/*
 * Process.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/system/Process.hpp>

#include <iostream>

#include <boost/bind.hpp>
#include <boost/foreach.hpp>

#include <core/Scope.hpp>
#include <core/Error.hpp>
#include <core/Log.hpp>
#include <core/BoostThread.hpp>

#include <core/PerformanceTimer.hpp>

#include "ChildProcess.hpp"

namespace rstudio {
namespace core {
namespace system {

Error runProgram(const std::string& executable,
                 const std::vector<std::string>& args,
                 const std::string& input,
                 const ProcessOptions& options,
                 ProcessResult* pResult)
{
   SyncChildProcess child(executable, args, options);
   return child.run(input, pResult);
}

Error runCommand(const std::string& command,
                 const ProcessOptions& options,
                 ProcessResult* pResult)
{
   return runCommand(command, "", options, pResult);
}

Error runCommand(const std::string& command,
                 const std::string& input,
                 const ProcessOptions& options,
                 ProcessResult* pResult)
{
   SyncChildProcess child(command, options);
   return child.run(input, pResult);
}

struct ProcessSupervisor::Impl
{
   Impl() : isPolling(false) {}
   bool isPolling;
   std::vector<boost::shared_ptr<AsyncChildProcess> > children;
};

ProcessSupervisor::ProcessSupervisor()
   : pImpl_(new Impl())
{
}

ProcessSupervisor::~ProcessSupervisor()
{
}

namespace {

Error runChild(boost::shared_ptr<AsyncChildProcess> pChild,
               std::vector<boost::shared_ptr<AsyncChildProcess> >* pChildren,
               const ProcessCallbacks& callbacks)
{
   // run the child
   Error error = pChild->run(callbacks);
   if (error)
      return error;

   // add to the list of children
   pChildren->push_back(pChild);

   // success
   return Success();
}

} // anonymous namespace

Error ProcessSupervisor::runProgram(const std::string& executable,
                                    const std::vector<std::string>& args,
                                    const ProcessOptions& options,
                                    const ProcessCallbacks& callbacks)
{
   // create the child
   boost::shared_ptr<AsyncChildProcess> pChild(
                                 new AsyncChildProcess(executable,
                                                       args,
                                                       options));

   // run the child
   return runChild(pChild, &(pImpl_->children), callbacks);
}

Error ProcessSupervisor::runCommand(const std::string& command,
                                    const ProcessOptions& options,
                                    const ProcessCallbacks& callbacks)
{
   // create the child
   boost::shared_ptr<AsyncChildProcess> pChild(
                                 new AsyncChildProcess(command, options));

   // run the child
   return runChild(pChild, &(pImpl_->children), callbacks);
}

namespace {

// class which implements all of the callbacks
struct ChildCallbacks
{
   ChildCallbacks(const std::string& input,
                  const boost::function<void(const ProcessResult&)>& onCompleted,
                  const boost::function<void(const Error&)>& onErrored)
      : input(input), onCompleted(onCompleted), onErrored(onErrored)
   {
   }

   void onStarted(ProcessOperations& operations)
   {
      if (!input.empty())
      {
         Error error = operations.writeToStdin(input, true);
         if (error)
         {
            LOG_ERROR(error);

            error = operations.terminate();
            if (error)
               LOG_ERROR(error);
         }
      }
   }

   void onStdout(ProcessOperations&, const std::string& output)
   {
      stdOut.append(output);
   }

   void onStderr(ProcessOperations&, const std::string& output)
   {
      stdErr.append(output);
   }

   void onError(ProcessOperations&, const Error& error)
   {
      onErrored(error);
   }

   void onConsoleOutputSnapshot(ProcessOperations&,
                                const std::vector<char>& output)
   {
      consoleOutputSnapshot = output;
   }

   void onExit(int exitStatus)
   {
      ProcessResult result;
      result.exitStatus = exitStatus;
      result.stdOut = stdOut;
      result.stdErr = stdErr;
      onCompleted(result);
   }

   std::string input;
   std::string stdOut;
   std::string stdErr;
   std::vector<char> consoleOutputSnapshot;
   boost::function<void(const ProcessResult&)> onCompleted;
   boost::function<void(const Error&)> onErrored;
};

} // anonymous namespace

ProcessCallbacks createProcessCallbacks(
               const std::string& input,
               const boost::function<void(const ProcessResult&)>& onCompleted,
               const boost::function<void(const Error&)>& onError)
{
   // create a shared_ptr to the ChildCallbacks. it will stay alive
   // as long as one of its members is referenced in a bind context
   boost::shared_ptr<ChildCallbacks> pCC(new ChildCallbacks(input,
                                                            onCompleted,
                                                            onError));

   // bind in the callbacks
   using boost::bind;
   ProcessCallbacks cb;
   cb.onStarted = bind(&ChildCallbacks::onStarted, pCC, _1);
   cb.onStdout = bind(&ChildCallbacks::onStdout, pCC, _1, _2);
   cb.onStderr = bind(&ChildCallbacks::onStderr, pCC, _1, _2);
   cb.onConsoleOutputSnapshot =
         bind(&ChildCallbacks::onConsoleOutputSnapshot, pCC, _1, _2);
   cb.onExit = bind(&ChildCallbacks::onExit, pCC, _1);
   cb.onError = bind(&ChildCallbacks::onError, pCC, _1, _2);

   // return it
   return cb;
}

Error ProcessSupervisor::runProgram(
            const std::string& executable,
            const std::vector<std::string>& args,
            const std::string& input,
            const ProcessOptions& options,
            const boost::function<void(const ProcessResult&)>& onCompleted)
{
   // create proces callbacks
   ProcessCallbacks cb = createProcessCallbacks(
            input, onCompleted, boost::function<void(const Error&)>());

   // run the child
   return runProgram(executable, args, options, cb);
}

Error ProcessSupervisor::runCommand(
             const std::string& command,
             const ProcessOptions& options,
             const boost::function<void(const ProcessResult&)>& onCompleted)
{
   return runCommand(command, "", options, onCompleted);
}

Error ProcessSupervisor::runCommand(
             const std::string& command,
             const std::string& input,
             const ProcessOptions& options,
             const boost::function<void(const ProcessResult&)>& onCompleted)
{
   // create proces callbacks
   ProcessCallbacks cb = createProcessCallbacks(input, onCompleted);

   // run the child
   return runCommand(command, options, cb);
}

bool ProcessSupervisor::hasRunningChildren()
{
   return !pImpl_->children.empty();
}

bool ProcessSupervisor::poll()
{
   // bail immediately if we have no children
   if (!hasRunningChildren())
      return false;

   // never allow re-entrancy (could occur if one of the output
   // handlers called from poll executes a waitForMethod which
   // results in additional polling during idle/wait time)
   if (pImpl_->isPolling)
      return true;

   // set isPolling then clear it on exit
   pImpl_->isPolling = true;
   scope::SetOnExit<bool> setOnExit(&pImpl_->isPolling, false);

   // call poll on all of our children
   std::for_each(pImpl_->children.begin(),
                 pImpl_->children.end(),
                 boost::bind(&AsyncChildProcess::poll, _1));

   // remove any children who have exited from our list
   pImpl_->children.erase(std::remove_if(
                             pImpl_->children.begin(),
                             pImpl_->children.end(),
                             boost::bind(&AsyncChildProcess::exited, _1)),
                          pImpl_->children.end());

   // return status
   return hasRunningChildren();
}

void ProcessSupervisor::terminateAll()
{
   // call terminate on all of our children
   BOOST_FOREACH(boost::shared_ptr<AsyncChildProcess> pChild,
                 pImpl_->children)
   {
      Error error = pChild->terminate();
      if (error)
         LOG_ERROR(error);
   }
}

bool ProcessSupervisor::wait(
      const boost::posix_time::time_duration& pollingInterval,
      const boost::posix_time::time_duration& maxWait)
{
   boost::posix_time::ptime timeoutTime(boost::posix_time::not_a_date_time);
   if (!maxWait.is_not_a_date_time())
      timeoutTime = boost::get_system_time() + maxWait;

   while (poll())
   {
      // wait the specified polling interval
      boost::this_thread::sleep(pollingInterval);

      // check for timeout if appropriate
      if (!timeoutTime.is_not_a_date_time())
      {
         if (boost::get_system_time() > timeoutTime)
            return false;
      }
   }

   return true;
}

} // namespace system
} // namespace core
} // namespace rstudio

<commit_msg>make a copy of child process vector before calling poll<commit_after>/*
 * Process.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/system/Process.hpp>

#include <iostream>

#include <boost/bind.hpp>
#include <boost/foreach.hpp>

#include <core/Scope.hpp>
#include <core/Error.hpp>
#include <core/Log.hpp>
#include <core/BoostThread.hpp>

#include <core/PerformanceTimer.hpp>

#include "ChildProcess.hpp"

namespace rstudio {
namespace core {
namespace system {

Error runProgram(const std::string& executable,
                 const std::vector<std::string>& args,
                 const std::string& input,
                 const ProcessOptions& options,
                 ProcessResult* pResult)
{
   SyncChildProcess child(executable, args, options);
   return child.run(input, pResult);
}

Error runCommand(const std::string& command,
                 const ProcessOptions& options,
                 ProcessResult* pResult)
{
   return runCommand(command, "", options, pResult);
}

Error runCommand(const std::string& command,
                 const std::string& input,
                 const ProcessOptions& options,
                 ProcessResult* pResult)
{
   SyncChildProcess child(command, options);
   return child.run(input, pResult);
}

struct ProcessSupervisor::Impl
{
   Impl() : isPolling(false) {}
   bool isPolling;
   std::vector<boost::shared_ptr<AsyncChildProcess> > children;
};

ProcessSupervisor::ProcessSupervisor()
   : pImpl_(new Impl())
{
}

ProcessSupervisor::~ProcessSupervisor()
{
}

namespace {

Error runChild(boost::shared_ptr<AsyncChildProcess> pChild,
               std::vector<boost::shared_ptr<AsyncChildProcess> >* pChildren,
               const ProcessCallbacks& callbacks)
{
   // run the child
   Error error = pChild->run(callbacks);
   if (error)
      return error;

   // add to the list of children
   pChildren->push_back(pChild);

   // success
   return Success();
}

} // anonymous namespace

Error ProcessSupervisor::runProgram(const std::string& executable,
                                    const std::vector<std::string>& args,
                                    const ProcessOptions& options,
                                    const ProcessCallbacks& callbacks)
{
   // create the child
   boost::shared_ptr<AsyncChildProcess> pChild(
                                 new AsyncChildProcess(executable,
                                                       args,
                                                       options));

   // run the child
   return runChild(pChild, &(pImpl_->children), callbacks);
}

Error ProcessSupervisor::runCommand(const std::string& command,
                                    const ProcessOptions& options,
                                    const ProcessCallbacks& callbacks)
{
   // create the child
   boost::shared_ptr<AsyncChildProcess> pChild(
                                 new AsyncChildProcess(command, options));

   // run the child
   return runChild(pChild, &(pImpl_->children), callbacks);
}

namespace {

// class which implements all of the callbacks
struct ChildCallbacks
{
   ChildCallbacks(const std::string& input,
                  const boost::function<void(const ProcessResult&)>& onCompleted,
                  const boost::function<void(const Error&)>& onErrored)
      : input(input), onCompleted(onCompleted), onErrored(onErrored)
   {
   }

   void onStarted(ProcessOperations& operations)
   {
      if (!input.empty())
      {
         Error error = operations.writeToStdin(input, true);
         if (error)
         {
            LOG_ERROR(error);

            error = operations.terminate();
            if (error)
               LOG_ERROR(error);
         }
      }
   }

   void onStdout(ProcessOperations&, const std::string& output)
   {
      stdOut.append(output);
   }

   void onStderr(ProcessOperations&, const std::string& output)
   {
      stdErr.append(output);
   }

   void onError(ProcessOperations&, const Error& error)
   {
      onErrored(error);
   }

   void onConsoleOutputSnapshot(ProcessOperations&,
                                const std::vector<char>& output)
   {
      consoleOutputSnapshot = output;
   }

   void onExit(int exitStatus)
   {
      ProcessResult result;
      result.exitStatus = exitStatus;
      result.stdOut = stdOut;
      result.stdErr = stdErr;
      onCompleted(result);
   }

   std::string input;
   std::string stdOut;
   std::string stdErr;
   std::vector<char> consoleOutputSnapshot;
   boost::function<void(const ProcessResult&)> onCompleted;
   boost::function<void(const Error&)> onErrored;
};

} // anonymous namespace

ProcessCallbacks createProcessCallbacks(
               const std::string& input,
               const boost::function<void(const ProcessResult&)>& onCompleted,
               const boost::function<void(const Error&)>& onError)
{
   // create a shared_ptr to the ChildCallbacks. it will stay alive
   // as long as one of its members is referenced in a bind context
   boost::shared_ptr<ChildCallbacks> pCC(new ChildCallbacks(input,
                                                            onCompleted,
                                                            onError));

   // bind in the callbacks
   using boost::bind;
   ProcessCallbacks cb;
   cb.onStarted = bind(&ChildCallbacks::onStarted, pCC, _1);
   cb.onStdout = bind(&ChildCallbacks::onStdout, pCC, _1, _2);
   cb.onStderr = bind(&ChildCallbacks::onStderr, pCC, _1, _2);
   cb.onConsoleOutputSnapshot =
         bind(&ChildCallbacks::onConsoleOutputSnapshot, pCC, _1, _2);
   cb.onExit = bind(&ChildCallbacks::onExit, pCC, _1);
   cb.onError = bind(&ChildCallbacks::onError, pCC, _1, _2);

   // return it
   return cb;
}

Error ProcessSupervisor::runProgram(
            const std::string& executable,
            const std::vector<std::string>& args,
            const std::string& input,
            const ProcessOptions& options,
            const boost::function<void(const ProcessResult&)>& onCompleted)
{
   // create proces callbacks
   ProcessCallbacks cb = createProcessCallbacks(
            input, onCompleted, boost::function<void(const Error&)>());

   // run the child
   return runProgram(executable, args, options, cb);
}

Error ProcessSupervisor::runCommand(
             const std::string& command,
             const ProcessOptions& options,
             const boost::function<void(const ProcessResult&)>& onCompleted)
{
   return runCommand(command, "", options, onCompleted);
}

Error ProcessSupervisor::runCommand(
             const std::string& command,
             const std::string& input,
             const ProcessOptions& options,
             const boost::function<void(const ProcessResult&)>& onCompleted)
{
   // create proces callbacks
   ProcessCallbacks cb = createProcessCallbacks(input, onCompleted);

   // run the child
   return runCommand(command, options, cb);
}

bool ProcessSupervisor::hasRunningChildren()
{
   return !pImpl_->children.empty();
}

bool ProcessSupervisor::poll()
{
   // bail immediately if we have no children
   if (!hasRunningChildren())
      return false;

   // never allow re-entrancy (could occur if one of the output
   // handlers called from poll executes a waitForMethod which
   // results in additional polling during idle/wait time)
   if (pImpl_->isPolling)
      return true;

   // set isPolling then clear it on exit
   pImpl_->isPolling = true;
   scope::SetOnExit<bool> setOnExit(&pImpl_->isPolling, false);

   // call poll on all of our children via a copy of the std::vector that
   // holds all of the children. we do this because 'poll' can end up
   // executing R code (e.g. via onContinue) which can in term end up
   // executing background tasks that result in a call to processSupervisor
   // runProgram or runCommand. This would then result in a push_back on
   // the children vector and if this requried a realloc would invalidate
   // all of the iterators currently pointing into the container
   std::vector<boost::shared_ptr<AsyncChildProcess> > children = pImpl_->children;
   std::for_each(children.begin(),
                 children.end(),
                 boost::bind(&AsyncChildProcess::poll, _1));

   // remove any children who have exited from our list. note that it's safe
   // in this case to use pImpl_->children directly because the call to
   // AsyncChildProcess::exited just checks a member variable rather than
   // executing code that could cause re-entry
   pImpl_->children.erase(std::remove_if(
                             pImpl_->children.begin(),
                             pImpl_->children.end(),
                             boost::bind(&AsyncChildProcess::exited, _1)),
                          pImpl_->children.end());

   // return status
   return hasRunningChildren();
}

void ProcessSupervisor::terminateAll()
{
   // call terminate on all of our children
   BOOST_FOREACH(boost::shared_ptr<AsyncChildProcess> pChild,
                 pImpl_->children)
   {
      Error error = pChild->terminate();
      if (error)
         LOG_ERROR(error);
   }
}

bool ProcessSupervisor::wait(
      const boost::posix_time::time_duration& pollingInterval,
      const boost::posix_time::time_duration& maxWait)
{
   boost::posix_time::ptime timeoutTime(boost::posix_time::not_a_date_time);
   if (!maxWait.is_not_a_date_time())
      timeoutTime = boost::get_system_time() + maxWait;

   while (poll())
   {
      // wait the specified polling interval
      boost::this_thread::sleep(pollingInterval);

      // check for timeout if appropriate
      if (!timeoutTime.is_not_a_date_time())
      {
         if (boost::get_system_time() > timeoutTime)
            return false;
      }
   }

   return true;
}

} // namespace system
} // namespace core
} // namespace rstudio

<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>

int main()
{
    std::ifstream file("data.txt");
    std::string line;
    // See: https://stackoverflow.com/q/7219062/496459
    // std::getline has no buffer-size limitation, per the standard.
    while(std::getline(file, line))
    {
        std::cout << line << '\n';
    }

    return 0;
}

<commit_msg>Include <string> for std::getline<commit_after>#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream file("data.txt");
    std::string line;
    // See: https://stackoverflow.com/q/7219062/496459
    // std::getline has no buffer-size limitation, per the standard.
    while(std::getline(file, line))
    {
        std::cout << line << '\n';
    }

    return 0;
}

<|endoftext|>


<commit_before>/******************************************************************************\
* File:          process.cpp
* Purpose:       Implementation of class 'wxExProcess'
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/regex.h>
#include <wx/tokenzr.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/extension/configdlg.h>
#include <wx/extension/frame.h>
#include <wx/extension/log.h>
#include <wx/extension/util.h>
#include <wx/extension/report/process.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/frame.h>
#include <wx/extension/report/listitem.h>
#include <wx/extension/report/listview.h>

BEGIN_EVENT_TABLE(wxExProcess, wxProcess)
  EVT_TIMER(-1, wxExProcess::OnTimer)
END_EVENT_TABLE()

wxString wxExProcess::m_Command;
wxString wxExProcess::m_WorkingDirKey = _("Process folder");

wxExProcess::wxExProcess(
  wxExFrameWithHistory* frame,
  const wxString& command)
  : wxProcess(NULL, -1)
  , m_Frame(frame)
  , m_ListView(NULL)
  , m_Timer(this)
{
  if (!command.empty())
  {
    m_Command = command;
  }

  Redirect();
}

bool wxExProcess::CheckInput()
{
  if (m_ListView == NULL)
  {
    return false;
  }

  bool hasInput = false;

  // This assumes that the output is always line buffered.
  wxString line;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());
    line << tis.ReadLine();
    hasInput = true;
  }
  else if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());
    line << tis.ReadLine();
    hasInput = true;
  }

  if (hasInput && !line.empty())
  {
    wxString lineno;
    wxString path;

    // Check on error in php script output.
    const wxRegEx regex(".*in \\(.*\\) on line \\(.*\\)", wxRE_ADVANCED);

    if (regex.Matches(line))
    {
      size_t start, len;

      if (regex.GetMatch(&start, &len, 1))
      {
        path = line.substr(start, len);
      }

      if (regex.GetMatch(&start, &len, 2))
      {
        lineno = line.substr(start, len);
      }
    }
    else
    {
      // Check on error in gcc output (and some others).
      wxStringTokenizer tkz(line, ':');
      path = tkz.GetNextToken();

      if (tkz.HasMoreTokens())
      {
        const wxString number = tkz.GetNextToken();
        long val;
        if (number.ToLong(&val)) lineno = number;
      }
    }

    wxFileName fn(path);

    fn.Normalize();

    if (fn.FileExists())
    {
      wxExListItem item(m_ListView, fn);
      item.Insert();
      item.SetItem(_("Line"), line);
      item.SetItem(_("Line No"), lineno);
    }
    else
    {
      m_ListView->InsertItem(m_ListView->GetItemCount(), line, -1);
    }

    // If nothing selected, then ensure last line is visible.
    // Otherwise you are busy inspecting some line, and
    // it would be irritating to get it out of view.
    if (m_ListView->GetSelectedItemCount() == 0)
    {
      m_ListView->EnsureVisible(m_ListView->GetItemCount() - 1);
    }

#if wxUSE_STATUSBAR
    m_ListView->UpdateStatusBar();
#endif
  }

  return hasInput;
}

int wxExProcess::ConfigDialog(
  wxWindow* parent,
  const wxString& title)
{
  std::vector<wxExConfigItem> v;

  v.push_back(wxExConfigItem(
    _("Process"),
    CONFIG_COMBOBOX,
    wxEmptyString));

  v.push_back(wxExConfigItem(
    m_WorkingDirKey,
    CONFIG_COMBOBOXDIR,
    wxEmptyString,
    true,
    1000));

  const auto result = wxExConfigDialog(parent,
    v,
    title).ShowModal();

  if (result == wxID_OK)
  {
    m_Command = wxExConfigFirstOf(_("Process"));
  }

  return result;
}

long wxExProcess::Execute()
{
  if (m_Command.empty())
  {
    if (ConfigDialog(m_ListView) == wxID_CANCEL)
    {
      return 0;
    }
  }

  wxString cwd;
  const wxString dir = wxExConfigFirstOf(m_WorkingDirKey);

  if (!dir.empty())
  {
    cwd = wxGetCwd();
    if (!wxSetWorkingDirectory(dir))
    {
      wxLogError(_("Cannot set working directory"));
      return 0;
    }
  }

  m_ListView = m_Frame->Activate(wxExListViewStandard::LIST_PROCESS);

  if (m_ListView == NULL)
  {
    // Only show a message, and continue,
    // easier for testing.
    wxLogMessage(_("No listview to collect output"));
  }

  const long pid = wxExecute(m_Command, wxEXEC_ASYNC, this);

  if (pid > 0)
  {
    SetPid(pid);

#if wxUSE_STATUSBAR
    wxExFrame::StatusText(m_Command);
#endif
    wxExLog::Get()->Log(m_Command);

    m_Timer.Start(1000); // each 1000 milliseconds
  }
  else
  {
    wxLogError(_("Cannot execute") + ": " + m_Command);
  }

  if (!cwd.empty())
  {
    wxSetWorkingDirectory(cwd);
  }

  return pid;
}

bool wxExProcess::IsRunning() const
{
  if (GetPid() < 0)
  {
    return false;
  }

  return Exists(GetPid());
}

wxKillError wxExProcess::Kill(wxSignal sig)
{
  if (!IsRunning())
  {
    return wxKILL_NO_PROCESS;
  }

  m_Timer.Stop();

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(_("Stopped"));
#endif

  DeletePendingEvents();

  delete this;

  return wxProcess::Kill(GetPid(), sig);
}

void wxExProcess::OnTerminate(
  int WXUNUSED(pid),
  int WXUNUSED(status))
{
  m_Timer.Stop();

  // Collect remaining input.
  while (CheckInput())
  {
    // Do nothing.
  }

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(_("Ready"));
#endif

  wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_TERMINATED_PROCESS);
  wxPostEvent(wxTheApp->GetTopWindow(), event);
}

void wxExProcess::OnTimer(wxTimerEvent& event)
{
  while (CheckInput())
  {
    // Do nothing.
  }
}
<commit_msg>minor update<commit_after>/******************************************************************************\
* File:          process.cpp
* Purpose:       Implementation of class 'wxExProcess'
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/regex.h>
#include <wx/tokenzr.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/extension/configdlg.h>
#include <wx/extension/log.h>
#include <wx/extension/util.h> // for wxExConfigFirstOf
#include <wx/extension/report/process.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/frame.h>
#include <wx/extension/report/listitem.h>
#include <wx/extension/report/listview.h>

BEGIN_EVENT_TABLE(wxExProcess, wxProcess)
  EVT_TIMER(-1, wxExProcess::OnTimer)
END_EVENT_TABLE()

wxString wxExProcess::m_Command;
wxString wxExProcess::m_WorkingDirKey = _("Process folder");

wxExProcess::wxExProcess(
  wxExFrameWithHistory* frame,
  const wxString& command)
  : wxProcess(NULL, -1)
  , m_Frame(frame)
  , m_ListView(NULL)
  , m_Timer(this)
{
  if (!command.empty())
  {
    m_Command = command;
  }

  Redirect();
}

bool wxExProcess::CheckInput()
{
  if (m_ListView == NULL)
  {
    return false;
  }

  bool hasInput = false;

  // This assumes that the output is always line buffered.
  wxString line;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());
    line << tis.ReadLine();
    hasInput = true;
  }
  else if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());
    line << tis.ReadLine();
    hasInput = true;
  }

  if (hasInput && !line.empty())
  {
    wxString lineno;
    wxString path;

    // Check on error in php script output.
    const wxRegEx regex(".*in \\(.*\\) on line \\(.*\\)", wxRE_ADVANCED);

    if (regex.Matches(line))
    {
      size_t start, len;

      if (regex.GetMatch(&start, &len, 1))
      {
        path = line.substr(start, len);
      }

      if (regex.GetMatch(&start, &len, 2))
      {
        lineno = line.substr(start, len);
      }
    }
    else
    {
      // Check on error in gcc output (and some others).
      wxStringTokenizer tkz(line, ':');
      path = tkz.GetNextToken();

      if (tkz.HasMoreTokens())
      {
        const wxString number = tkz.GetNextToken();
        long val;
        if (number.ToLong(&val)) lineno = number;
      }
    }

    wxFileName fn(path);

    fn.Normalize();

    if (fn.FileExists())
    {
      wxExListItem item(m_ListView, fn);
      item.Insert();
      item.SetItem(_("Line"), line);
      item.SetItem(_("Line No"), lineno);
    }
    else
    {
      m_ListView->InsertItem(m_ListView->GetItemCount(), line, -1);
    }

    // If nothing selected, then ensure last line is visible.
    // Otherwise you are busy inspecting some line, and
    // it would be irritating to get it out of view.
    if (m_ListView->GetSelectedItemCount() == 0)
    {
      m_ListView->EnsureVisible(m_ListView->GetItemCount() - 1);
    }

#if wxUSE_STATUSBAR
    m_ListView->UpdateStatusBar();
#endif
  }

  return hasInput;
}

int wxExProcess::ConfigDialog(
  wxWindow* parent,
  const wxString& title)
{
  std::vector<wxExConfigItem> v;

  v.push_back(wxExConfigItem(
    _("Process"),
    CONFIG_COMBOBOX,
    wxEmptyString));

  v.push_back(wxExConfigItem(
    m_WorkingDirKey,
    CONFIG_COMBOBOXDIR,
    wxEmptyString,
    true,
    1000));

  const auto result = wxExConfigDialog(parent,
    v,
    title).ShowModal();

  if (result == wxID_OK)
  {
    m_Command = wxExConfigFirstOf(_("Process"));
  }

  return result;
}

long wxExProcess::Execute()
{
  if (m_Command.empty())
  {
    if (ConfigDialog(m_ListView) == wxID_CANCEL)
    {
      return 0;
    }
  }

  wxString cwd;
  const wxString dir = wxExConfigFirstOf(m_WorkingDirKey);

  if (!dir.empty())
  {
    cwd = wxGetCwd();
    if (!wxSetWorkingDirectory(dir))
    {
      wxLogError(_("Cannot set working directory"));
      return 0;
    }
  }

  m_ListView = m_Frame->Activate(wxExListViewStandard::LIST_PROCESS);

  if (m_ListView == NULL)
  {
    // Only show a message, and continue,
    // easier for testing.
    wxLogMessage(_("No listview to collect output"));
  }

  const long pid = wxExecute(m_Command, wxEXEC_ASYNC, this);

  if (pid > 0)
  {
    SetPid(pid);

#if wxUSE_STATUSBAR
    wxExFrame::StatusText(m_Command);
#endif
    wxExLog::Get()->Log(m_Command);

    m_Timer.Start(1000); // each 1000 milliseconds
  }
  else
  {
    wxLogError(_("Cannot execute") + ": " + m_Command);
  }

  if (!cwd.empty())
  {
    wxSetWorkingDirectory(cwd);
  }

  return pid;
}

bool wxExProcess::IsRunning() const
{
  if (GetPid() < 0)
  {
    return false;
  }

  return Exists(GetPid());
}

wxKillError wxExProcess::Kill(wxSignal sig)
{
  if (!IsRunning())
  {
    return wxKILL_NO_PROCESS;
  }

  m_Timer.Stop();

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(_("Stopped"));
#endif

  DeletePendingEvents();

  delete this;

  return wxProcess::Kill(GetPid(), sig);
}

void wxExProcess::OnTerminate(
  int WXUNUSED(pid),
  int WXUNUSED(status))
{
  m_Timer.Stop();

  // Collect remaining input.
  while (CheckInput())
  {
    // Do nothing.
  }

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(_("Ready"));
#endif

  wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_TERMINATED_PROCESS);
  wxPostEvent(wxTheApp->GetTopWindow(), event);
}

void wxExProcess::OnTimer(wxTimerEvent& event)
{
  while (CheckInput())
  {
    // Do nothing.
  }
}
<|endoftext|>


<commit_before>/******************************************************************************\
* File:          process.cpp
* Purpose:       Implementation of class 'wxExProcessWithListView' and support classes
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/tokenzr.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/extension/app.h>
#include <wx/extension/configdialog.h>
#include <wx/extension/report/process.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/listitem.h>
#include <wx/extension/report/listview.h>

BEGIN_EVENT_TABLE(wxExProcessWithListView, wxProcess)
  EVT_TIMER(-1, wxExProcessWithListView::OnTimer)
END_EVENT_TABLE()

wxString wxExProcessWithListView::m_Command = "";

wxExProcessWithListView::wxExProcessWithListView(
  wxExListViewFile* listview,
  const wxString& command)
  : wxProcess(listview, -1)
  , m_Owner(listview)
  , m_Timer(this)
{
  if (!command.empty())
  {
    m_Command = command;
  }

  Redirect();
}

bool wxExProcessWithListView::CheckInput()
{
  bool hasInput = false;

  // This assumes that the output is always line buffered.
  wxString line;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());
    line << tis.ReadLine();
    hasInput = true;
  }
  else if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());
    line << tis.ReadLine();
    hasInput = true;
  }

  if (hasInput && !line.empty())
  {
    wxString lineno;
    wxString path;

    // Check on error in php script output.
    wxRegEx regex(".*in \\(.*\\) on line \\(.*\\)");

    if (regex.Matches(line))
    {
      size_t start, len;

      if (regex.GetMatch(&start, &len, 1))
      {
        path = line.substr(start, len);
      }

      if (regex.GetMatch(&start, &len, 2))
      {
        lineno = line.substr(start, len);
      }
    }
    else
    {
      // Check on error in gcc output (and some others).
      wxStringTokenizer tkz(line, ':');
      path = tkz.GetNextToken();

      if (tkz.HasMoreTokens())
      {
        const wxString number = tkz.GetNextToken();
        long val;
        if (number.ToLong(&val)) lineno = number;
      }
    }

    wxFileName fn(path);
    fn.Normalize();

    if (fn.FileExists())
    {
      wxExListItemWithFileName item(m_Owner, fn.GetFullPath());
      item.Insert();
      item.SetColumnText(_("Line"), line);
      item.SetColumnText(_("Line No"), lineno);
    }
    else
    {
      wxExListItemWithFileName item(m_Owner, wxEmptyString); // wxExListItem gives incorrect image
      item.Insert();
      item.SetColumnText(_("Line"), line);
    }

    // If nothing selected, then ensure last line is visible.
    // Otherwise you are busy inspecting some line, and
    // it would be irritating to get it out of view.
    if (m_Owner->GetSelectedItemCount() == 0)
    {
      m_Owner->EnsureVisible(m_Owner->GetItemCount() - 1);
    }

    m_Owner->UpdateStatusBar();
  }

  return hasInput;
}

int wxExProcessWithListView::ConfigDialog()
{
  std::vector<wxExConfigItem> v;
  v.push_back(wxExConfigItem(_("Process"), CONFIG_COMBOBOX, wxEmptyString, true));
  v.push_back(wxExConfigItem(_("In folder"), CONFIG_COMBOBOXDIR, wxEmptyString, true));

  const int result = wxExConfigDialog(NULL,
    wxExApp::GetConfig(),
    v,
    _("Select Process")).ShowModal();

  if (result == wxID_OK)
  {
    wxSetWorkingDirectory(wxExApp::GetConfig(_("In folder")));
    m_Command = wxExApp::GetConfig(_("Process"));
  }

  return result;
}

long wxExProcessWithListView::Execute()
{
  long pid;

  if ((pid = wxExecute(m_Command, wxEXEC_ASYNC, this)) > 0)
  {
    SetPid(pid);

    wxExFrame::StatusText(m_Command);
    wxExApp::Log(_("Running process") + ": " + m_Command);

    m_Timer.Start(100); // each 100 milliseconds
  }
  else
  {
    wxLogError(_("Cannot run process") + ": " + m_Command);
  }

  return pid;
}

wxKillError wxExProcessWithListView::Kill(wxSignal sig)
{
  m_Timer.Stop();

  wxExFrame::StatusText(_("Stopped"));

  return wxProcess::Kill(GetPid(), sig);
}

void wxExProcessWithListView::OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
{
  m_Timer.Stop();

  // Collect remaining input.
  while (CheckInput())
  {
    // Do nothing.
  }

  wxExFrame::StatusText(_("Ready"));

  wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_TERMINATED_PROCESS);
  wxPostEvent(m_Owner, event);
}

void wxExProcessWithListView::OnTimer(wxTimerEvent& event)
{
  while (CheckInput())
  {
    // Do nothing.
  }
}
<commit_msg>updated header<commit_after>/******************************************************************************\
* File:          process.cpp
* Purpose:       Implementation of class 'wxExProcessWithListView'
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/tokenzr.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/extension/app.h>
#include <wx/extension/configdialog.h>
#include <wx/extension/report/process.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/listitem.h>
#include <wx/extension/report/listview.h>

BEGIN_EVENT_TABLE(wxExProcessWithListView, wxProcess)
  EVT_TIMER(-1, wxExProcessWithListView::OnTimer)
END_EVENT_TABLE()

wxString wxExProcessWithListView::m_Command = "";

wxExProcessWithListView::wxExProcessWithListView(
  wxExListViewFile* listview,
  const wxString& command)
  : wxProcess(listview, -1)
  , m_Owner(listview)
  , m_Timer(this)
{
  if (!command.empty())
  {
    m_Command = command;
  }

  Redirect();
}

bool wxExProcessWithListView::CheckInput()
{
  bool hasInput = false;

  // This assumes that the output is always line buffered.
  wxString line;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());
    line << tis.ReadLine();
    hasInput = true;
  }
  else if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());
    line << tis.ReadLine();
    hasInput = true;
  }

  if (hasInput && !line.empty())
  {
    wxString lineno;
    wxString path;

    // Check on error in php script output.
    wxRegEx regex(".*in \\(.*\\) on line \\(.*\\)");

    if (regex.Matches(line))
    {
      size_t start, len;

      if (regex.GetMatch(&start, &len, 1))
      {
        path = line.substr(start, len);
      }

      if (regex.GetMatch(&start, &len, 2))
      {
        lineno = line.substr(start, len);
      }
    }
    else
    {
      // Check on error in gcc output (and some others).
      wxStringTokenizer tkz(line, ':');
      path = tkz.GetNextToken();

      if (tkz.HasMoreTokens())
      {
        const wxString number = tkz.GetNextToken();
        long val;
        if (number.ToLong(&val)) lineno = number;
      }
    }

    wxFileName fn(path);
    fn.Normalize();

    if (fn.FileExists())
    {
      wxExListItemWithFileName item(m_Owner, fn.GetFullPath());
      item.Insert();
      item.SetColumnText(_("Line"), line);
      item.SetColumnText(_("Line No"), lineno);
    }
    else
    {
      wxExListItemWithFileName item(m_Owner, wxEmptyString); // wxExListItem gives incorrect image
      item.Insert();
      item.SetColumnText(_("Line"), line);
    }

    // If nothing selected, then ensure last line is visible.
    // Otherwise you are busy inspecting some line, and
    // it would be irritating to get it out of view.
    if (m_Owner->GetSelectedItemCount() == 0)
    {
      m_Owner->EnsureVisible(m_Owner->GetItemCount() - 1);
    }

    m_Owner->UpdateStatusBar();
  }

  return hasInput;
}

int wxExProcessWithListView::ConfigDialog()
{
  std::vector<wxExConfigItem> v;
  v.push_back(wxExConfigItem(_("Process"), CONFIG_COMBOBOX, wxEmptyString, true));
  v.push_back(wxExConfigItem(_("In folder"), CONFIG_COMBOBOXDIR, wxEmptyString, true));

  const int result = wxExConfigDialog(NULL,
    wxExApp::GetConfig(),
    v,
    _("Select Process")).ShowModal();

  if (result == wxID_OK)
  {
    wxSetWorkingDirectory(wxExApp::GetConfig(_("In folder")));
    m_Command = wxExApp::GetConfig(_("Process"));
  }

  return result;
}

long wxExProcessWithListView::Execute()
{
  long pid;

  if ((pid = wxExecute(m_Command, wxEXEC_ASYNC, this)) > 0)
  {
    SetPid(pid);

    wxExFrame::StatusText(m_Command);
    wxExApp::Log(_("Running process") + ": " + m_Command);

    m_Timer.Start(100); // each 100 milliseconds
  }
  else
  {
    wxLogError(_("Cannot run process") + ": " + m_Command);
  }

  return pid;
}

wxKillError wxExProcessWithListView::Kill(wxSignal sig)
{
  m_Timer.Stop();

  wxExFrame::StatusText(_("Stopped"));

  return wxProcess::Kill(GetPid(), sig);
}

void wxExProcessWithListView::OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
{
  m_Timer.Stop();

  // Collect remaining input.
  while (CheckInput())
  {
    // Do nothing.
  }

  wxExFrame::StatusText(_("Ready"));

  wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_TERMINATED_PROCESS);
  wxPostEvent(m_Owner, event);
}

void wxExProcessWithListView::OnTimer(wxTimerEvent& event)
{
  while (CheckInput())
  {
    // Do nothing.
  }
}
<|endoftext|>


<commit_before>/**
 * Sorting integers - bubble method.
 */
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void bubblesort(vector<int> &v)
{
	int i, change;

	do
	{
		change = 0;
		i = v.size() - 1;

		do
		{
			if (v[i] < v[--i])
			{
				swap(v[i], v[i + 1]);
				change = 1;
			}
		}
		while (i != 0);
	}
	while (change != 0);
}

int main(int argc, char const *argv[])
{
	int count, i, n;
	vector<int> v;

	srand(time(NULL));

	cout << "How many: ";
	cin >> count;

	for (i = 0; i < count; ++i)
	{
		v.push_back(rand() % count);
	}

	cout << endl << "Before: ";
	for (i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	bubblesort(v);

	cout << endl << endl << "After: ";
	for (i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	return 0;
}<commit_msg>refactoring<commit_after>/**
 * Sorting integers - bubble method.
 */
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void bubblesort(vector<int> &v)
{
	int i, change;

	do
	{
		change = 0;
		i = v.size() - 1;

		do
		{
			if (v[i] < v[--i])
			{
				swap(v[i], v[i + 1]);
				change = 1;
			}
		}
		while (i != 0);
	}
	while (change != 0);
}

int main(int argc, char const *argv[])
{
	int count, i, n;
	vector<int> v;

	srand(time(0));

	cout << "How many: ";
	cin >> count;

	for (i = 0; i < count; ++i)
	{
		v.push_back(rand() % count);
	}

	cout << endl << "Before: ";
	for (i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	bubblesort(v);

	cout << endl << endl << "After: ";
	for (i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	return 0;
}<|endoftext|>