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

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

#include "base/memory/scoped_ptr.h"
#include "chrome/common/guid.h"

namespace {

const char* kIsLocalKey = "is_local";
const char* kGuidKey = "guid";
const char* kExtensionIdKey = "extension_id";
const char* kTitleKey = "title";
const char* kBodyKey = "body";
const char* kLinkUrlKey = "link_url";
const char* kLinkTextKey = "link_text";

}  // namespace

AppNotification::AppNotification(bool is_local,
                                 const std::string& guid,
                                 const std::string& extension_id,
                                 const std::string& title,
                                 const std::string& body)
    : is_local_(is_local),
      extension_id_(extension_id),
      title_(title),
      body_(body) {
  guid_ = guid.empty() ? guid::GenerateGUID() : guid;
}

AppNotification::~AppNotification() {}

AppNotification* AppNotification::Copy() {
  AppNotification* copy = new AppNotification(
      this->is_local(), this->guid(), this->extension_id(),
      this->title(), this->body());
  copy->set_link_url(this->link_url());
  copy->set_link_text(this->link_text());
  return copy;
}

void AppNotification::ToDictionaryValue(DictionaryValue* result) {
  CHECK(result);
  result->SetBoolean(kIsLocalKey, is_local_);
  if (!guid_.empty())
    result->SetString(kGuidKey, guid_);
  if (!extension_id_.empty())
    result->SetString(kExtensionIdKey, extension_id_);
  if (!title_.empty())
    result->SetString(kTitleKey, title_);
  if (!body_.empty())
    result->SetString(kBodyKey, body_);
  if (!link_url_.is_empty()) {
    result->SetString(kLinkUrlKey, link_url_.possibly_invalid_spec());
    result->SetString(kLinkTextKey, link_text_);
  }
}

// static
AppNotification* AppNotification::FromDictionaryValue(
    const DictionaryValue& value) {
  scoped_ptr<AppNotification> result(new AppNotification(true, "", "", "", ""));

  if (value.HasKey(kIsLocalKey) && !value.GetBoolean(
      kIsLocalKey, &result->is_local_)) {
    return NULL;
  }
  if (value.HasKey(kGuidKey) && !value.GetString(kGuidKey, &result->guid_))
    return NULL;
  if (value.HasKey(kExtensionIdKey) &&
      !value.GetString(kExtensionIdKey, &result->extension_id_))
    return NULL;
  if (value.HasKey(kTitleKey) && !value.GetString(kTitleKey, &result->title_))
    return NULL;
  if (value.HasKey(kBodyKey) && !value.GetString(kBodyKey, &result->body_))
    return NULL;
  if (value.HasKey(kLinkUrlKey)) {
    if (!value.HasKey(kLinkTextKey))
      return NULL;
    std::string url;
    if (!value.GetString(kLinkUrlKey, &url) ||
        !value.GetString(kLinkTextKey, &result->link_text_))
      return NULL;
    GURL gurl(url);
    if (!gurl.is_valid())
      return NULL;
    result->set_link_url(gurl);
  }

  return result.release();
}

bool AppNotification::Equals(const AppNotification& other) const {
  return (is_local_ == other.is_local_ &&
          guid_ == other.guid_ &&
          extension_id_ == other.extension_id_ &&
          title_ == other.title_ &&
          body_ == other.body_ &&
          link_url_ == other.link_url_ &&
          link_text_ == other.link_text_);
}

AppNotificationList* CopyAppNotificationList(
    const AppNotificationList& source) {
  AppNotificationList* copy = new AppNotificationList();

  for (AppNotificationList::const_iterator iter = source.begin();
      iter != source.end(); ++iter) {
    copy->push_back(linked_ptr<AppNotification>(iter->get()->Copy()));
  }
  return copy;
}
<commit_msg>always read and write link url and link text independently without enforcing any semantics on them. If we load link url only if link text is not empty (and vice versa) when writing notifications JSON file then we get out of sync with sync database for a given notification. This can fail the model association when browser starts up next time and halt syncing of notifications in retail builds and crash in debug builds. Review URL: http://codereview.chromium.org/8474008<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

#include "base/memory/scoped_ptr.h"
#include "chrome/common/guid.h"

namespace {

const char* kIsLocalKey = "is_local";
const char* kGuidKey = "guid";
const char* kExtensionIdKey = "extension_id";
const char* kTitleKey = "title";
const char* kBodyKey = "body";
const char* kLinkUrlKey = "link_url";
const char* kLinkTextKey = "link_text";

}  // namespace

AppNotification::AppNotification(bool is_local,
                                 const std::string& guid,
                                 const std::string& extension_id,
                                 const std::string& title,
                                 const std::string& body)
    : is_local_(is_local),
      extension_id_(extension_id),
      title_(title),
      body_(body) {
  guid_ = guid.empty() ? guid::GenerateGUID() : guid;
}

AppNotification::~AppNotification() {}

AppNotification* AppNotification::Copy() {
  AppNotification* copy = new AppNotification(
      this->is_local(), this->guid(), this->extension_id(),
      this->title(), this->body());
  copy->set_link_url(this->link_url());
  copy->set_link_text(this->link_text());
  return copy;
}

void AppNotification::ToDictionaryValue(DictionaryValue* result) {
  CHECK(result);
  result->SetBoolean(kIsLocalKey, is_local_);
  if (!guid_.empty())
    result->SetString(kGuidKey, guid_);
  if (!extension_id_.empty())
    result->SetString(kExtensionIdKey, extension_id_);
  if (!title_.empty())
    result->SetString(kTitleKey, title_);
  if (!body_.empty())
    result->SetString(kBodyKey, body_);
  if (!link_url_.is_empty())
    result->SetString(kLinkUrlKey, link_url_.possibly_invalid_spec());
  if (!link_text_.empty())
    result->SetString(kLinkTextKey, link_text_);
}

// static
AppNotification* AppNotification::FromDictionaryValue(
    const DictionaryValue& value) {
  scoped_ptr<AppNotification> result(new AppNotification(true, "", "", "", ""));

  if (value.HasKey(kIsLocalKey) && !value.GetBoolean(
      kIsLocalKey, &result->is_local_)) {
    return NULL;
  }
  if (value.HasKey(kGuidKey) && !value.GetString(kGuidKey, &result->guid_))
    return NULL;
  if (value.HasKey(kExtensionIdKey) &&
      !value.GetString(kExtensionIdKey, &result->extension_id_))
    return NULL;
  if (value.HasKey(kTitleKey) && !value.GetString(kTitleKey, &result->title_))
    return NULL;
  if (value.HasKey(kBodyKey) && !value.GetString(kBodyKey, &result->body_))
    return NULL;
  if (value.HasKey(kLinkUrlKey)) {
    std::string url;
    if (!value.GetString(kLinkUrlKey, &url))
      return NULL;
    GURL gurl(url);
    if (!gurl.is_valid())
      return NULL;
    result->set_link_url(gurl);
  }
  if (value.HasKey(kLinkTextKey) &&
      !value.GetString(kLinkTextKey, &result->link_text_)) {
    return NULL;
  }

  return result.release();
}

bool AppNotification::Equals(const AppNotification& other) const {
  return (is_local_ == other.is_local_ &&
          guid_ == other.guid_ &&
          extension_id_ == other.extension_id_ &&
          title_ == other.title_ &&
          body_ == other.body_ &&
          link_url_ == other.link_url_ &&
          link_text_ == other.link_text_);
}

AppNotificationList* CopyAppNotificationList(
    const AppNotificationList& source) {
  AppNotificationList* copy = new AppNotificationList();

  for (AppNotificationList::const_iterator iter = source.begin();
      iter != source.end(); ++iter) {
    copy->push_back(linked_ptr<AppNotification>(iter->get()->Copy()));
  }
  return copy;
}
<|endoftext|>


<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/instant/instant_field_trial.h"

#include "base/command_line.h"
#include "base/metrics/field_trial.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"

namespace {

// Field trial IDs of the control and experiment groups. Though they are not
// literally "const", they are set only once, in Activate() below. See the .h
// file for what these groups represent.
int g_inactive = -1;
int g_instant = 0;
int g_suggest = 0;
int g_hidden  = 0;
int g_silent  = 0;
int g_control = 0;

}

// static
void InstantFieldTrial::Activate() {
  scoped_refptr<base::FieldTrial> trial(
      base::FieldTrialList::FactoryGetFieldTrial(
          "Instant", 1000, "Inactive", 2013, 7, 1, &g_inactive));

  // Try to give the user a consistent experience, if possible.
  if (base::FieldTrialList::IsOneTimeRandomizationEnabled())
    trial->UseOneTimeRandomization();

  g_instant = trial->AppendGroup("Instant",  10);  //  1%
  g_suggest = trial->AppendGroup("Suggest",  10);  //  1%
  g_hidden  = trial->AppendGroup("Hidden",  960);  // 96%
  g_silent  = trial->AppendGroup("Silent",   10);  //  1%
  g_control = trial->AppendGroup("Control",  10);  //  1%

  int group = 0;
  if (trial->group() == g_instant)
    group = 1;
  else if (trial->group() == g_suggest)
    group = 2;
  else if (trial->group() == g_hidden)
    group = 3;
  else if (trial->group() == g_silent)
    group = 4;
  else if (trial->group() == g_control)
    group = 5;
  UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Size", group, 6);
}

// static
InstantFieldTrial::Group InstantFieldTrial::GetGroup(Profile* profile) {
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kInstantFieldTrial)) {
    UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 1, 10);
    std::string switch_value =
        command_line->GetSwitchValueASCII(switches::kInstantFieldTrial);
    if (switch_value == switches::kInstantFieldTrialInstant)
      return INSTANT;
    if (switch_value == switches::kInstantFieldTrialSuggest)
      return SUGGEST;
    if (switch_value == switches::kInstantFieldTrialHidden)
      return HIDDEN;
    if (switch_value == switches::kInstantFieldTrialSilent)
      return SILENT;
    if (switch_value == switches::kInstantFieldTrialControl)
      return CONTROL;
    return INACTIVE;
  }

  const int group = base::FieldTrialList::FindValue("Instant");
  if (group == base::FieldTrial::kNotFinalized || group == g_inactive) {
    UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 2, 10);
    return INACTIVE;
  }

  const PrefService* prefs = profile ? profile->GetPrefs() : NULL;
  if (!prefs) {
    UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 3, 10);
    return INACTIVE;
  }

  if (profile->IsOffTheRecord()) {
    UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 4, 10);
    return INACTIVE;
  }

  if (prefs->GetBoolean(prefs::kInstantEnabledOnce)) {
    UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 5, 10);
    return INACTIVE;
  }

  if (!prefs->GetBoolean(prefs::kSearchSuggestEnabled)) {
    UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 6, 10);
    return INACTIVE;
  }

  if (prefs->IsManagedPreference(prefs::kInstantEnabled)) {
    UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 7, 10);
    return INACTIVE;
  }

  if (!MetricsServiceHelper::IsMetricsReportingEnabled()) {
    UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 8, 10);
    return INACTIVE;
  }

  UMA_HISTOGRAM_ENUMERATION("Instant.FieldTrial.Reason", 0, 10);

  if (group == g_instant)
    return INSTANT;
  if (group == g_suggest)
    return SUGGEST;
  if (group == g_hidden)
    return HIDDEN;
  if (group == g_silent)
    return SILENT;
  if (group == g_control)
    return CONTROL;

  NOTREACHED();
  return INACTIVE;
}

// static
bool InstantFieldTrial::IsInstantExperiment(Profile* profile) {
  Group group = GetGroup(profile);
  return group == INSTANT || group == SUGGEST || group == HIDDEN ||
         group == SILENT;
}

// static
bool InstantFieldTrial::IsHiddenExperiment(Profile* profile) {
  Group group = GetGroup(profile);
  return group == SUGGEST || group == HIDDEN || group == SILENT;
}

// static
bool InstantFieldTrial::IsSilentExperiment(Profile* profile) {
  Group group = GetGroup(profile);
  return group == SILENT;
}

// static
std::string InstantFieldTrial::GetGroupName(Profile* profile) {
  switch (GetGroup(profile)) {
    case INACTIVE: return std::string();
    case INSTANT:  return "_Instant";
    case SUGGEST:  return "_Suggest";
    case HIDDEN:   return "_Hidden";
    case SILENT:   return "_Silent";
    case CONTROL:  return "_Control";
  }

  NOTREACHED();
  return std::string();
}

// static
std::string InstantFieldTrial::GetGroupAsUrlParam(Profile* profile) {
  switch (GetGroup(profile)) {
    case INACTIVE: return std::string();
    case INSTANT:  return "ix=i9&";
    case SUGGEST:  return "ix=t9&";
    case HIDDEN:   return "ix=h9&";
    case SILENT:   return "ix=s9&";
    case CONTROL:  return "ix=c9&";
  }

  NOTREACHED();
  return std::string();
}

// static
bool InstantFieldTrial::ShouldSetSuggestedText(Profile* profile) {
  Group group = GetGroup(profile);
  return group != HIDDEN && group != SILENT;
}
<commit_msg>Enable the HIDDEN mode for most users.<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/instant/instant_field_trial.h"

#include "base/command_line.h"
#include "base/metrics/field_trial.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"

namespace {

// Field trial IDs of the control and experiment groups. Though they are not
// literally "const", they are set only once, in Activate() below. See the .h
// file for what these groups represent.
int g_inactive = -1;
int g_instant = 0;
int g_suggest = 0;
int g_hidden  = 0;
int g_silent  = 0;
int g_control = 0;

}

// static
void InstantFieldTrial::Activate() {
  scoped_refptr<base::FieldTrial> trial(
      base::FieldTrialList::FactoryGetFieldTrial(
          "Instant", 1000, "Inactive", 2013, 7, 1, &g_inactive));

  // Try to give the user a consistent experience, if possible.
  if (base::FieldTrialList::IsOneTimeRandomizationEnabled())
    trial->UseOneTimeRandomization();

  g_instant = trial->AppendGroup("Instant",  10);  //  1%
  g_suggest = trial->AppendGroup("Suggest",  10);  //  1%
  g_hidden  = trial->AppendGroup("Hidden",  960);  // 96%
  g_silent  = trial->AppendGroup("Silent",   10);  //  1%
  g_control = trial->AppendGroup("Control",  10);  //  1%
}

// static
InstantFieldTrial::Group InstantFieldTrial::GetGroup(Profile* profile) {
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kInstantFieldTrial)) {
    std::string switch_value =
        command_line->GetSwitchValueASCII(switches::kInstantFieldTrial);
    if (switch_value == switches::kInstantFieldTrialInstant)
      return INSTANT;
    if (switch_value == switches::kInstantFieldTrialSuggest)
      return SUGGEST;
    if (switch_value == switches::kInstantFieldTrialHidden)
      return HIDDEN;
    if (switch_value == switches::kInstantFieldTrialSilent)
      return SILENT;
    if (switch_value == switches::kInstantFieldTrialControl)
      return CONTROL;
    return INACTIVE;
  }

  const int group = base::FieldTrialList::FindValue("Instant");
  if (group == base::FieldTrial::kNotFinalized || group == g_inactive)
    return INACTIVE;

  // CONTROL and SILENT are unconstrained.
  if (group == g_control)
    return CONTROL;
  if (group == g_silent)
    return SILENT;

  // HIDDEN, SUGGEST and INSTANT need non-incognito, suggest-enabled profiles.
  const PrefService* prefs = profile ? profile->GetPrefs() : NULL;
  if (!prefs || profile->IsOffTheRecord() ||
      !prefs->GetBoolean(prefs::kSearchSuggestEnabled)) {
    return INACTIVE;
  }

  if (group == g_hidden)
    return HIDDEN;

  // SUGGEST and INSTANT require UMA opt-in.
  if (!MetricsServiceHelper::IsMetricsReportingEnabled())
    return INACTIVE;

  if (group == g_suggest)
    return SUGGEST;

  // Disable INSTANT for group policy overrides and explicit opt-out.
  if (prefs->IsManagedPreference(prefs::kInstantEnabled) ||
      prefs->GetBoolean(prefs::kInstantEnabledOnce)) {
    return INACTIVE;
  }

  if (group == g_instant)
    return INSTANT;

  NOTREACHED();
  return INACTIVE;
}

// static
bool InstantFieldTrial::IsInstantExperiment(Profile* profile) {
  Group group = GetGroup(profile);
  return group == INSTANT || group == SUGGEST || group == HIDDEN ||
         group == SILENT;
}

// static
bool InstantFieldTrial::IsHiddenExperiment(Profile* profile) {
  Group group = GetGroup(profile);
  return group == SUGGEST || group == HIDDEN || group == SILENT;
}

// static
bool InstantFieldTrial::IsSilentExperiment(Profile* profile) {
  Group group = GetGroup(profile);
  return group == SILENT;
}

// static
std::string InstantFieldTrial::GetGroupName(Profile* profile) {
  switch (GetGroup(profile)) {
    case INACTIVE: return std::string();
    case INSTANT:  return "_Instant";
    case SUGGEST:  return "_Suggest";
    case HIDDEN:   return "_Hidden";
    case SILENT:   return "_Silent";
    case CONTROL:  return "_Control";
  }

  NOTREACHED();
  return std::string();
}

// static
std::string InstantFieldTrial::GetGroupAsUrlParam(Profile* profile) {
  switch (GetGroup(profile)) {
    case INACTIVE: return std::string();
    case INSTANT:  return "ix=i9&";
    case SUGGEST:  return "ix=t9&";
    case HIDDEN:   return "ix=h9&";
    case SILENT:   return "ix=s9&";
    case CONTROL:  return "ix=c9&";
  }

  NOTREACHED();
  return std::string();
}

// static
bool InstantFieldTrial::ShouldSetSuggestedText(Profile* profile) {
  Group group = GetGroup(profile);
  return group != HIDDEN && group != SILENT;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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/policy/device_token_fetcher.h"

#include <algorithm>

#include "base/message_loop.h"
#include "chrome/browser/policy/cloud_policy_cache_base.h"
#include "chrome/browser/policy/device_management_service.h"
#include "chrome/browser/policy/proto/device_management_constants.h"
#include "chrome/browser/policy/proto/device_management_local.pb.h"

namespace {

// Retry after 5 minutes (with exponential backoff) after token fetch errors.
const int64 kTokenFetchErrorDelayMilliseconds = 5 * 60 * 1000;
// Retry after max 3 hours after token fetch errors.
const int64 kTokenFetchErrorMaxDelayMilliseconds = 3 * 60 * 60 * 1000;
// For unmanaged devices, check once per day whether they're still unmanaged.
const int64 kUnmanagedDeviceRefreshRateMilliseconds = 24 * 60 * 60 * 1000;

}  // namespace

namespace policy {

namespace em = enterprise_management;

DeviceTokenFetcher::DeviceTokenFetcher(
    DeviceManagementService* service,
    CloudPolicyCacheBase* cache,
    PolicyNotifier* notifier)
    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
  Initialize(service,
             cache,
             notifier,
             kTokenFetchErrorDelayMilliseconds,
             kTokenFetchErrorMaxDelayMilliseconds,
             kUnmanagedDeviceRefreshRateMilliseconds);
}

DeviceTokenFetcher::DeviceTokenFetcher(
    DeviceManagementService* service,
    CloudPolicyCacheBase* cache,
    PolicyNotifier* notifier,
    int64 token_fetch_error_delay_ms,
    int64 token_fetch_error_max_delay_ms,
    int64 unmanaged_device_refresh_rate_ms)
    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
  Initialize(service,
             cache,
             notifier,
             token_fetch_error_delay_ms,
             token_fetch_error_max_delay_ms,
             unmanaged_device_refresh_rate_ms);
}

DeviceTokenFetcher::~DeviceTokenFetcher() {
  CancelRetryTask();
}

void DeviceTokenFetcher::FetchToken(
    const std::string& auth_token,
    const std::string& device_id,
    em::DeviceRegisterRequest_Type policy_type,
    const std::string& machine_id,
    const std::string& machine_model) {
  SetState(STATE_INACTIVE);
  auth_token_ = auth_token;
  device_id_ = device_id;
  policy_type_ = policy_type;
  machine_id_ = machine_id;
  machine_model_ = machine_model;
  FetchTokenInternal();
}

void DeviceTokenFetcher::FetchTokenInternal() {
  DCHECK(state_ != STATE_TOKEN_AVAILABLE);
  if (auth_token_.empty() || device_id_.empty()) {
    // Maybe this device is unmanaged, just exit. The CloudPolicyController
    // will call FetchToken() again if something changes.
    return;
  }
  // Construct a new backend, which will discard any previous requests.
  backend_.reset(service_->CreateBackend());
  em::DeviceRegisterRequest request;
  request.set_type(policy_type_);
  if (!machine_id_.empty())
    request.set_machine_id(machine_id_);
  if (!machine_model_.empty())
    request.set_machine_model(machine_model_);
  backend_->ProcessRegisterRequest(auth_token_, device_id_, request, this);
}

void DeviceTokenFetcher::SetUnmanagedState() {
  // The call to |cache_->SetUnmanaged()| has to happen first because it sets
  // the timestamp that |SetState()| needs to determine the correct refresh
  // time.
  cache_->SetUnmanaged();
  SetState(STATE_UNMANAGED);
}

const std::string& DeviceTokenFetcher::GetDeviceToken() {
  return device_token_;
}

void DeviceTokenFetcher::StopAutoRetry() {
  CancelRetryTask();
  backend_.reset();
  device_token_.clear();
  auth_token_.clear();
  device_id_.clear();
}

void DeviceTokenFetcher::AddObserver(DeviceTokenFetcher::Observer* observer) {
  observer_list_.AddObserver(observer);
}

void DeviceTokenFetcher::RemoveObserver(
    DeviceTokenFetcher::Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

void DeviceTokenFetcher::HandleRegisterResponse(
    const em::DeviceRegisterResponse& response) {
  if (response.has_device_management_token()) {
    device_token_ = response.device_management_token();
    SetState(STATE_TOKEN_AVAILABLE);
  } else {
    NOTREACHED();
    SetState(STATE_ERROR);
  }
}

void DeviceTokenFetcher::OnError(DeviceManagementBackend::ErrorCode code) {
  switch (code) {
    case DeviceManagementBackend::kErrorServiceManagementNotSupported:
      cache_->SetUnmanaged();
      SetState(STATE_UNMANAGED);
      break;
    case DeviceManagementBackend::kErrorRequestFailed:
    case DeviceManagementBackend::kErrorTemporaryUnavailable:
    case DeviceManagementBackend::kErrorServiceDeviceNotFound:
      SetState(STATE_TEMPORARY_ERROR);
      break;
    case DeviceManagementBackend::kErrorServiceManagementTokenInvalid:
      // Most probably the GAIA auth cookie has expired. We can not do anything
      // until the user logs-in again.
      SetState(STATE_BAD_AUTH);
      break;
    default:
      SetState(STATE_ERROR);
  }
}

void DeviceTokenFetcher::Initialize(DeviceManagementService* service,
                                    CloudPolicyCacheBase* cache,
                                    PolicyNotifier* notifier,
                                    int64 token_fetch_error_delay_ms,
                                    int64 token_fetch_error_max_delay_ms,
                                    int64 unmanaged_device_refresh_rate_ms) {
  service_ = service;
  cache_ = cache;
  notifier_ = notifier;
  token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
  token_fetch_error_max_delay_ms_ = token_fetch_error_max_delay_ms;
  effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
  unmanaged_device_refresh_rate_ms_ = unmanaged_device_refresh_rate_ms;
  state_ = STATE_INACTIVE;
  retry_task_ = NULL;

  if (cache_->is_unmanaged())
    SetState(STATE_UNMANAGED);
}

void DeviceTokenFetcher::SetState(FetcherState state) {
  state_ = state;
  if (state_ != STATE_ERROR)
    effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms_;

  base::Time delayed_work_at;
  switch (state_) {
    case STATE_INACTIVE:
      device_token_.clear();
      auth_token_.clear();
      device_id_.clear();
      notifier_->Inform(CloudPolicySubsystem::UNENROLLED,
                        CloudPolicySubsystem::NO_DETAILS,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_TOKEN_AVAILABLE:
      FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceTokenAvailable());
      notifier_->Inform(CloudPolicySubsystem::SUCCESS,
                        CloudPolicySubsystem::NO_DETAILS,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_UNMANAGED:
      delayed_work_at = cache_->last_policy_refresh_time() +
          base::TimeDelta::FromMilliseconds(unmanaged_device_refresh_rate_ms_);
      notifier_->Inform(CloudPolicySubsystem::UNMANAGED,
                        CloudPolicySubsystem::NO_DETAILS,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_TEMPORARY_ERROR:
      delayed_work_at = base::Time::Now() +
          base::TimeDelta::FromMilliseconds(
              effective_token_fetch_error_delay_ms_);
      effective_token_fetch_error_delay_ms_ =
          std::min(effective_token_fetch_error_delay_ms_ * 2,
                   token_fetch_error_max_delay_ms_);
      notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
                        CloudPolicySubsystem::DMTOKEN_NETWORK_ERROR,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_ERROR:
      effective_token_fetch_error_delay_ms_ = token_fetch_error_max_delay_ms_;
      delayed_work_at = base::Time::Now() +
          base::TimeDelta::FromMilliseconds(
              effective_token_fetch_error_delay_ms_);
      notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
                        CloudPolicySubsystem::DMTOKEN_NETWORK_ERROR,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_BAD_AUTH:
      // Can't do anything, need to wait for new credentials.
      notifier_->Inform(CloudPolicySubsystem::BAD_GAIA_TOKEN,
                        CloudPolicySubsystem::NO_DETAILS,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
  }

  CancelRetryTask();
  if (!delayed_work_at.is_null()) {
    base::Time now(base::Time::Now());
    int64 delay = std::max<int64>((delayed_work_at - now).InMilliseconds(), 0);
    retry_task_ = method_factory_.NewRunnableMethod(
            &DeviceTokenFetcher::ExecuteRetryTask);
    MessageLoop::current()->PostDelayedTask(FROM_HERE, retry_task_,
                                            delay);
  }
}

void DeviceTokenFetcher::ExecuteRetryTask() {
  DCHECK(retry_task_);
  retry_task_ = NULL;

  switch (state_) {
    case STATE_INACTIVE:
    case STATE_TOKEN_AVAILABLE:
      break;
    case STATE_UNMANAGED:
    case STATE_ERROR:
    case STATE_TEMPORARY_ERROR:
    case STATE_BAD_AUTH:
      FetchTokenInternal();
      break;
  }
}

void DeviceTokenFetcher::CancelRetryTask() {
  if (retry_task_) {
    retry_task_->Cancel();
    retry_task_ = NULL;
  }
}

}  // namespace policy
<commit_msg>Fix the backing off in case of temp network errors in DeviceTokenFetcher.<commit_after>// Copyright (c) 2011 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/policy/device_token_fetcher.h"

#include <algorithm>

#include "base/message_loop.h"
#include "chrome/browser/policy/cloud_policy_cache_base.h"
#include "chrome/browser/policy/device_management_service.h"
#include "chrome/browser/policy/proto/device_management_constants.h"
#include "chrome/browser/policy/proto/device_management_local.pb.h"

namespace {

// Retry after 5 minutes (with exponential backoff) after token fetch errors.
const int64 kTokenFetchErrorDelayMilliseconds = 5 * 60 * 1000;
// Retry after max 3 hours after token fetch errors.
const int64 kTokenFetchErrorMaxDelayMilliseconds = 3 * 60 * 60 * 1000;
// For unmanaged devices, check once per day whether they're still unmanaged.
const int64 kUnmanagedDeviceRefreshRateMilliseconds = 24 * 60 * 60 * 1000;

}  // namespace

namespace policy {

namespace em = enterprise_management;

DeviceTokenFetcher::DeviceTokenFetcher(
    DeviceManagementService* service,
    CloudPolicyCacheBase* cache,
    PolicyNotifier* notifier)
    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
  Initialize(service,
             cache,
             notifier,
             kTokenFetchErrorDelayMilliseconds,
             kTokenFetchErrorMaxDelayMilliseconds,
             kUnmanagedDeviceRefreshRateMilliseconds);
}

DeviceTokenFetcher::DeviceTokenFetcher(
    DeviceManagementService* service,
    CloudPolicyCacheBase* cache,
    PolicyNotifier* notifier,
    int64 token_fetch_error_delay_ms,
    int64 token_fetch_error_max_delay_ms,
    int64 unmanaged_device_refresh_rate_ms)
    : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
  Initialize(service,
             cache,
             notifier,
             token_fetch_error_delay_ms,
             token_fetch_error_max_delay_ms,
             unmanaged_device_refresh_rate_ms);
}

DeviceTokenFetcher::~DeviceTokenFetcher() {
  CancelRetryTask();
}

void DeviceTokenFetcher::FetchToken(
    const std::string& auth_token,
    const std::string& device_id,
    em::DeviceRegisterRequest_Type policy_type,
    const std::string& machine_id,
    const std::string& machine_model) {
  SetState(STATE_INACTIVE);
  auth_token_ = auth_token;
  device_id_ = device_id;
  policy_type_ = policy_type;
  machine_id_ = machine_id;
  machine_model_ = machine_model;
  FetchTokenInternal();
}

void DeviceTokenFetcher::FetchTokenInternal() {
  DCHECK(state_ != STATE_TOKEN_AVAILABLE);
  if (auth_token_.empty() || device_id_.empty()) {
    // Maybe this device is unmanaged, just exit. The CloudPolicyController
    // will call FetchToken() again if something changes.
    return;
  }
  // Construct a new backend, which will discard any previous requests.
  backend_.reset(service_->CreateBackend());
  em::DeviceRegisterRequest request;
  request.set_type(policy_type_);
  if (!machine_id_.empty())
    request.set_machine_id(machine_id_);
  if (!machine_model_.empty())
    request.set_machine_model(machine_model_);
  backend_->ProcessRegisterRequest(auth_token_, device_id_, request, this);
}

void DeviceTokenFetcher::SetUnmanagedState() {
  // The call to |cache_->SetUnmanaged()| has to happen first because it sets
  // the timestamp that |SetState()| needs to determine the correct refresh
  // time.
  cache_->SetUnmanaged();
  SetState(STATE_UNMANAGED);
}

const std::string& DeviceTokenFetcher::GetDeviceToken() {
  return device_token_;
}

void DeviceTokenFetcher::StopAutoRetry() {
  CancelRetryTask();
  backend_.reset();
  device_token_.clear();
  auth_token_.clear();
  device_id_.clear();
}

void DeviceTokenFetcher::AddObserver(DeviceTokenFetcher::Observer* observer) {
  observer_list_.AddObserver(observer);
}

void DeviceTokenFetcher::RemoveObserver(
    DeviceTokenFetcher::Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

void DeviceTokenFetcher::HandleRegisterResponse(
    const em::DeviceRegisterResponse& response) {
  if (response.has_device_management_token()) {
    device_token_ = response.device_management_token();
    SetState(STATE_TOKEN_AVAILABLE);
  } else {
    NOTREACHED();
    SetState(STATE_ERROR);
  }
}

void DeviceTokenFetcher::OnError(DeviceManagementBackend::ErrorCode code) {
  switch (code) {
    case DeviceManagementBackend::kErrorServiceManagementNotSupported:
      cache_->SetUnmanaged();
      SetState(STATE_UNMANAGED);
      break;
    case DeviceManagementBackend::kErrorRequestFailed:
    case DeviceManagementBackend::kErrorTemporaryUnavailable:
    case DeviceManagementBackend::kErrorServiceDeviceNotFound:
      SetState(STATE_TEMPORARY_ERROR);
      break;
    case DeviceManagementBackend::kErrorServiceManagementTokenInvalid:
      // Most probably the GAIA auth cookie has expired. We can not do anything
      // until the user logs-in again.
      SetState(STATE_BAD_AUTH);
      break;
    default:
      SetState(STATE_ERROR);
  }
}

void DeviceTokenFetcher::Initialize(DeviceManagementService* service,
                                    CloudPolicyCacheBase* cache,
                                    PolicyNotifier* notifier,
                                    int64 token_fetch_error_delay_ms,
                                    int64 token_fetch_error_max_delay_ms,
                                    int64 unmanaged_device_refresh_rate_ms) {
  service_ = service;
  cache_ = cache;
  notifier_ = notifier;
  token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
  token_fetch_error_max_delay_ms_ = token_fetch_error_max_delay_ms;
  effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
  unmanaged_device_refresh_rate_ms_ = unmanaged_device_refresh_rate_ms;
  state_ = STATE_INACTIVE;
  retry_task_ = NULL;

  if (cache_->is_unmanaged())
    SetState(STATE_UNMANAGED);
}

void DeviceTokenFetcher::SetState(FetcherState state) {
  state_ = state;
  if (state_ != STATE_TEMPORARY_ERROR)
    effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms_;

  base::Time delayed_work_at;
  switch (state_) {
    case STATE_INACTIVE:
      device_token_.clear();
      auth_token_.clear();
      device_id_.clear();
      notifier_->Inform(CloudPolicySubsystem::UNENROLLED,
                        CloudPolicySubsystem::NO_DETAILS,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_TOKEN_AVAILABLE:
      FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceTokenAvailable());
      notifier_->Inform(CloudPolicySubsystem::SUCCESS,
                        CloudPolicySubsystem::NO_DETAILS,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_UNMANAGED:
      delayed_work_at = cache_->last_policy_refresh_time() +
          base::TimeDelta::FromMilliseconds(unmanaged_device_refresh_rate_ms_);
      notifier_->Inform(CloudPolicySubsystem::UNMANAGED,
                        CloudPolicySubsystem::NO_DETAILS,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_TEMPORARY_ERROR:
      delayed_work_at = base::Time::Now() +
          base::TimeDelta::FromMilliseconds(
              effective_token_fetch_error_delay_ms_);
      effective_token_fetch_error_delay_ms_ =
          std::min(effective_token_fetch_error_delay_ms_ * 2,
                   token_fetch_error_max_delay_ms_);
      notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
                        CloudPolicySubsystem::DMTOKEN_NETWORK_ERROR,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_ERROR:
      effective_token_fetch_error_delay_ms_ = token_fetch_error_max_delay_ms_;
      delayed_work_at = base::Time::Now() +
          base::TimeDelta::FromMilliseconds(
              effective_token_fetch_error_delay_ms_);
      notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
                        CloudPolicySubsystem::DMTOKEN_NETWORK_ERROR,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
    case STATE_BAD_AUTH:
      // Can't do anything, need to wait for new credentials.
      notifier_->Inform(CloudPolicySubsystem::BAD_GAIA_TOKEN,
                        CloudPolicySubsystem::NO_DETAILS,
                        PolicyNotifier::TOKEN_FETCHER);
      break;
  }

  CancelRetryTask();
  if (!delayed_work_at.is_null()) {
    base::Time now(base::Time::Now());
    int64 delay = std::max<int64>((delayed_work_at - now).InMilliseconds(), 0);
    retry_task_ = method_factory_.NewRunnableMethod(
            &DeviceTokenFetcher::ExecuteRetryTask);
    MessageLoop::current()->PostDelayedTask(FROM_HERE, retry_task_,
                                            delay);
  }
}

void DeviceTokenFetcher::ExecuteRetryTask() {
  DCHECK(retry_task_);
  retry_task_ = NULL;

  switch (state_) {
    case STATE_INACTIVE:
    case STATE_TOKEN_AVAILABLE:
      break;
    case STATE_UNMANAGED:
    case STATE_ERROR:
    case STATE_TEMPORARY_ERROR:
    case STATE_BAD_AUTH:
      FetchTokenInternal();
      break;
  }
}

void DeviceTokenFetcher::CancelRetryTask() {
  if (retry_task_) {
    retry_task_->Cancel();
    retry_task_ = NULL;
  }
}

}  // namespace policy
<|endoftext|>


<commit_before>/// PrecompData_test.cpp

/** Test the PrecompData class
 */

#include "PrecompData.h"
#include "PrecompData_test.h"
#include <cmath>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

float TestFunc(float x) {
	return sin(x);
}

float TestFuncLin(float x) {            //   y = 2x
    return 2*x;
}

float TestFuncNonLin1(float x) {        //   y = |x|
    return fabs(x);
}

float TestFuncNonLin2(float x) {        //   y = 1/(|x-2| + 0.1)
    return 1/(fabs(x - 2.0) + 0.1);
}

namespace Utilities {

PrecompData_test::PrecompData_test()
{
	using namespace Utilities;

    const int nValues = 10;

	{ // Test 1 - Interpolation
        cout << "\n\nTest 1: Zero-degree (nearest-neighbor/point sampling/Voronoi) interpolation:" << endl;
		const string funcName = "TestFunc";
		PrecompData<float> itp(funcName);
		itp.SetComment("TestFunc approximation");
		const float x0 = 0.0f, x1 = 6.28f;
		const float step = 0.5*(x1 - x0)/nValues;
		itp.Set(&TestFunc, x0, x1, nValues);
		float x = x0;
        float err = 0.0;
		for(int i = 0; i < nValues; ++i) {
            const float y = itp(x);
            err += fabs(TestFunc(x) - y);
			cout << i << ":\t" << funcName << "(" << x << ") = " << TestFunc(x) << " ~ " << y << endl;
			x += step;
		}
        cout << "Total error = " << err << endl;
	}

    { // Test 2 - Interpolation
        cout << "\n\nTest 2: Linear interpolation:" << endl;
        const string funcName = "TestFunc";
        PrecompData<float> itp(funcName);
        const float x0 = 0.0f, x1 = 6.28f;
        const float step = 0.5*(x1 - x0)/nValues;
        itp.Set(&TestFunc, x0, x1, nValues);
        float x = x0;
        float err = 0.0;
        itp.Interpolation(1);
        cout << "Interpolation: " << itp.Interpolation() << endl;
        for(int i = 0; i < nValues; ++i) {
            const float y = itp.Interpolate(x);
            err += fabs(TestFunc(x) - y);
            cout << i << ":\t" << funcName << "(" << x << ") = " << TestFunc(x) << " ~ " << y << endl;
            x += step;
        }
        cout << "Total error = " << err << endl;
    }

    if(0) { // Test 3 - AutoSet:  y = 2x
        cout << "\n\nTest 3: Automatic irregular grid:    y = 2x" << endl;
        const string funcName = "y = 2x";
        PrecompData<float> itp(funcName);
        const float x0 = 0.0f, x1 = 6.28f;
        itp.AutoSet(&TestFuncLin, x0, x1, nValues);
        cerr << "x0 = " << x0 << "  x1 = " << x1 << "  nValues = " << nValues << endl;  //+T+
        std::vector<float> vx, vy;
        itp.Get(vx, vy);
        cout << "Sizes:  x = " << vx.size() << ";  y = " << vy.size() << endl;
        for(size_t i = 0; i < nValues; ++i) {
            cout << i << ":  " << vx[i] << ", " << vy[i] << endl;
        }
    }

    if(0) { // Test 4 - AutoSet:  y = 1/(|x-2| + 0.1)
        cout << "\n\nTest 4: Automatic irregular grid:    y = 1/(|x-2| + 0.1)" << endl;
        const string funcName = "y = 1/(|x-2| + 0.1)";
        PrecompData<float> itp(funcName);
        const float x0 = 0.0f, x1 = 6.28f;
        itp.AutoSet(&TestFuncNonLin2, x0, x1, nValues);
        cerr << "x0 = " << x0 << "  x1 = " << x1 << "  nValues = " << nValues << endl;  //+T+
        std::vector<float> vx, vy;
        itp.Get(vx, vy);
        cout << "Sizes:  x = " << vx.size() << ";  y = " << vy.size() << endl;
        for(size_t i = 0; i < nValues; ++i) {
            cout << i << ":  " << vx[i] << ", " << vy[i] << endl;
        }
    }

    { // Test 5 - Derivatives
        cout << "\n\nTest 5: Derivatives" << endl;
        const string funcName = "Derivatives";
        float x1, y1, x2, y2, x3, y3, der1, der2, expRes;
        PrecompData<float> test;

        // First derivative
        x1 = 0.0; y1 = 0.0; x2 = 1.0; y2 = 0.0; expRes = 0.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        if(fabs(der1 - expRes) > 0.0001) {
            cerr << "Error - First derivative 1" << endl;
        }
        x1 = 0.0; y1 = 0.0; x2 = 1.0; y2 = 1.0; expRes = 1.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        if(fabs(der1 - expRes) > 0.0001) {
            cerr << "Error - First derivative 2" << endl;
        }
        x1 = 1.0; y1 = 0.0; x2 = 0.0; y2 = 1.0; expRes = -1.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        if(fabs(der1 - expRes) > 0.0001) {
            cerr << "Error - First derivative 3" << endl;
        }
        x1 = 0.0; y1 = 0.0; x2 = 2.0; y2 = 1.0; expRes = 0.5;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        if(fabs(der1 - expRes) > 0.0001) {
            cerr << "Error - First derivative 4" << endl;
        }
        x1 = 0.0; y1 = -1.0; x2 = 1.0; y2 = 1.0; expRes = 2.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        if(fabs(der1 - expRes) > 0.0001) {
            cerr << "Error - First derivative 5" << endl;
        }
        x1 = 0.0; y1 = 1.0; x2 = 1.0; y2 = 1.0; expRes = 0.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        if(fabs(der1 - expRes) > 0.0001) {
            cerr << "Error - First derivative 6" << endl;
        }

        // Second derivative

    }
}

} // Utilities

int main()
{
    using namespace Utilities;

    PrecompData_test test;

    return 0;
}
<commit_msg>- Count number of tests and number of failures.<commit_after>/// PrecompData_test.cpp

/** Test the PrecompData class
 */

#include "PrecompData.h"
#include "PrecompData_test.h"
#include <cmath>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

float TestFunc(float x) {
	return sin(x);
}

float TestFuncLin(float x) {            //   y = 2x
    return 2*x;
}

float TestFuncNonLin1(float x) {        //   y = |x|
    return fabs(x);
}

float TestFuncNonLin2(float x) {        //   y = 1/(|x-2| + 0.1)
    return 1/(fabs(x - 2.0) + 0.1);
}

namespace Utilities {

PrecompData_test::PrecompData_test()
{
	using namespace Utilities;

    const int nValues = 10;

	{ // Test 1 - Interpolation
        cout << "\n\nTest 1: Zero-degree (nearest-neighbor/point sampling/Voronoi) interpolation:" << endl;
		const string funcName = "TestFunc";
		PrecompData<float> itp(funcName);
		itp.SetComment("TestFunc approximation");
		const float x0 = 0.0f, x1 = 6.28f;
		const float step = 0.5*(x1 - x0)/nValues;
		itp.Set(&TestFunc, x0, x1, nValues);
		float x = x0;
        float err = 0.0;
		for(int i = 0; i < nValues; ++i) {
            const float y = itp(x);
            err += fabs(TestFunc(x) - y);
			cout << i << ":\t" << funcName << "(" << x << ") = " << TestFunc(x) << " ~ " << y << endl;
			x += step;
		}
        cout << "Total error = " << err << endl;
	}

    { // Test 2 - Interpolation
        cout << "\n\nTest 2: Linear interpolation:" << endl;
        const string funcName = "TestFunc";
        PrecompData<float> itp(funcName);
        const float x0 = 0.0f, x1 = 6.28f;
        const float step = 0.5*(x1 - x0)/nValues;
        itp.Set(&TestFunc, x0, x1, nValues);
        float x = x0;
        float err = 0.0;
        itp.Interpolation(1);
        cout << "Interpolation: " << itp.Interpolation() << endl;
        for(int i = 0; i < nValues; ++i) {
            const float y = itp.Interpolate(x);
            err += fabs(TestFunc(x) - y);
            cout << i << ":\t" << funcName << "(" << x << ") = " << TestFunc(x) << " ~ " << y << endl;
            x += step;
        }
        cout << "Total error = " << err << endl;
    }

    if(0) { // Test 3 - AutoSet:  y = 2x
        cout << "\n\nTest 3: Automatic irregular grid:    y = 2x" << endl;
        const string funcName = "y = 2x";
        PrecompData<float> itp(funcName);
        const float x0 = 0.0f, x1 = 6.28f;
        itp.AutoSet(&TestFuncLin, x0, x1, nValues);
        cerr << "x0 = " << x0 << "  x1 = " << x1 << "  nValues = " << nValues << endl;  //+T+
        std::vector<float> vx, vy;
        itp.Get(vx, vy);
        cout << "Sizes:  x = " << vx.size() << ";  y = " << vy.size() << endl;
        for(size_t i = 0; i < nValues; ++i) {
            cout << i << ":  " << vx[i] << ", " << vy[i] << endl;
        }
    }

    if(0) { // Test 4 - AutoSet:  y = 1/(|x-2| + 0.1)
        cout << "\n\nTest 4: Automatic irregular grid:    y = 1/(|x-2| + 0.1)" << endl;
        const string funcName = "y = 1/(|x-2| + 0.1)";
        PrecompData<float> itp(funcName);
        const float x0 = 0.0f, x1 = 6.28f;
        itp.AutoSet(&TestFuncNonLin2, x0, x1, nValues);
        cerr << "x0 = " << x0 << "  x1 = " << x1 << "  nValues = " << nValues << endl;  //+T+
        std::vector<float> vx, vy;
        itp.Get(vx, vy);
        cout << "Sizes:  x = " << vx.size() << ";  y = " << vy.size() << endl;
        for(size_t i = 0; i < nValues; ++i) {
            cout << i << ":  " << vx[i] << ", " << vy[i] << endl;
        }
    }

    { // Test 5 - Derivatives
        cout << "\n\nTest 5: Derivatives" << endl;
        int nTests = 0, nFailed = 0;
        const string funcName = "Derivatives";
        float x1, y1, x2, y2, x3, y3, der1, der2, expRes;
        PrecompData<float> test;

        // First derivative
        x1 = 0.0; y1 = 0.0; x2 = 1.0; y2 = 0.0; expRes = 0.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        ++nTests;
        if(fabs(der1 - expRes) > 0.0001) {
            ++nFailed;
            cerr << "Error - First derivative 1" << endl;
        }
        x1 = 0.0; y1 = 0.0; x2 = 1.0; y2 = 1.0; expRes = 1.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        ++nTests;
        if(fabs(der1 - expRes) > 0.0001) {
            ++nFailed;
            cerr << "Error - First derivative 2" << endl;
        }
        x1 = 1.0; y1 = 0.0; x2 = 0.0; y2 = 1.0; expRes = -1.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        ++nTests;
        if(fabs(der1 - expRes) > 0.0001) {
            ++nFailed;
            cerr << "Error - First derivative 3" << endl;
        }
        x1 = 0.0; y1 = 0.0; x2 = 2.0; y2 = 1.0; expRes = 0.5;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        ++nTests;
        if(fabs(der1 - expRes) > 0.0001) {
            ++nFailed;
            cerr << "Error - First derivative 4" << endl;
        }
        x1 = 0.0; y1 = -1.0; x2 = 1.0; y2 = 1.0; expRes = 2.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        ++nTests;
        if(fabs(der1 - expRes) > 0.0001) {
            ++nFailed;
            cerr << "Error - First derivative 5" << endl;
        }
        x1 = 0.0; y1 = 1.0; x2 = 1.0; y2 = 1.0; expRes = 0.0;
        der1 = test.FirstDerivative(x1, y1, x2, y2);
        ++nTests;
        if(fabs(der1 - expRes) > 0.0001) {
            ++nFailed;
            cerr << "Error - First derivative 6" << endl;
        }

        // Second derivative

        cout << "Derivatives:  Number of tests = " << nTests << ";  Number of failures = " << nFailed << endl;
    }
}

} // Utilities

int main()
{
    using namespace Utilities;

    PrecompData_test test;

    return 0;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * *****************************************************************************/

/*****
 * Author: Sergey Shekyan sshekyan@qualys.com
 *
 * Slow HTTP attack  vulnerability test tool
 *  http://code.google.com/p/slowhttptest/
 *****/

#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <string>

#include <openssl/ssl.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "slowlog.h"
#include "slowsocket.h"
#include "slowurl.h"

namespace slowhttptest {
SlowSocket::SlowSocket()
    : sockfd_(-1), requests_to_send_(0),
      followups_to_send_(0), last_followup_timing_(0),
      offset_(0), ssl_(0), buf_(0) {
}

SlowSocket::~SlowSocket() {
  close();
}

int SlowSocket::set_nonblocking() {
  int flags;

  if(-1 == (flags = fcntl(sockfd_, F_GETFL, 0))) {
    flags = 0;
  }
  return fcntl(sockfd_, F_SETFL, flags | O_NONBLOCK);
}

bool SlowSocket::init(addrinfo* addr, const Url* url, int& maxfd,
                      int followups_to_send) {
  addrinfo* res;
  bool connected = false;
  for (res = addr; !connected && res; res = res->ai_next) {
    sockfd_ = socket(res->ai_family, res->ai_socktype,
     res->ai_protocol);
    if(-1 == sockfd_) {
      slowlog(LOG_ERROR, "%s: Failed to create socket\n", __FUNCTION__);
      return false;
    }

    if(-1 == set_nonblocking()) {
      slowlog(LOG_ERROR, "%s: Failed to set socket %d to non-blocking \n", __FUNCTION__,
       sockfd_);
      return false;
    }
    connected = url->isSSL() ? connect_ssl(addr) : connect_plain(addr);
  }

  followups_to_send_ = followups_to_send;
  requests_to_send_ = 1;

  if(sockfd_ > maxfd) {
    maxfd = sockfd_;
  }
  return true;
}

bool SlowSocket::connect_plain(addrinfo* addr) {
  errno = 0;

  if (connect(sockfd_, addr->ai_addr, addr->ai_addrlen) < 0
      && EINPROGRESS != errno) {
    slowlog(LOG_ERROR, "%s: Cannot connect qsocket: %s %d \n", __FUNCTION__,
            strerror(errno), sockfd_);
    close();
    return false;
  }
  return true;
}

bool SlowSocket::connect_ssl(addrinfo* addr) {
  // Establish regular connection.
  if(!connect_plain(addr))  return false;

  // Init SSL related stuff.
  // TODO(vagababov): this is not thread safe of pretty.
  static bool ssl_is_initialized = false;
  if (!ssl_is_initialized) {
    SSL_library_init();
    ssl_is_initialized = true;
  }
  SSL_METHOD* method = NULL;
  SSL_CTX* ssl_ctx = NULL;
  method = SSLv23_client_method();
  ssl_ctx = SSL_CTX_new(method);
  if(!ssl_ctx) {
    slowlog(LOG_ERROR, "%s: Cannot create new SSL context\n", __FUNCTION__);
    close();
    return false;
  }
  ssl_ = SSL_new(ssl_ctx);
  if(!ssl_) {
    slowlog(LOG_ERROR, "%s: Cannot create SSL structure for a connection\n",
            __FUNCTION__);
    close();
    return false;
  }
  SSL_set_fd(ssl_, sockfd_);
  int ret = SSL_connect(ssl_);
  if(ret <= 0) {
    int err = SSL_get_error(ssl_, ret);
    slowlog(LOG_ERROR, "%s: SSL connect error: %d\n", __FUNCTION__, err);
    if(SSL_ERROR_WANT_READ != err && SSL_ERROR_WANT_WRITE != err) {
      close();
      return false;
    }
  }
  slowlog(LOG_DEBUG, "%s: SSL connection is using %s\n", __FUNCTION__,
          SSL_get_cipher(ssl_));
  return true;
}

int SlowSocket::recv_slow(void *buf, size_t len) {
  return ssl_ ? SSL_read(ssl_, buf, len)
              : recv(sockfd_, buf, len, 0);
}

int SlowSocket::send_slow(const void* buf, size_t len, const SendType type) {
  // VA: this is not good. create a "prepare" method.
  // initial send
  if(buf_ == 0) {
    buf_ = buf;
    offset_ = len;
  }

  int ret = ssl_ ? SSL_write(ssl_, buf_, offset_)
                 : send(sockfd_, buf_, offset_, 0);

  // entire data was sent
  if(ret > 0 && ret == offset_) {
    if(eInitialSend == type) {
      --requests_to_send_;
    } else if(eFollowUpSend == type) {
      --followups_to_send_;
    }
    buf_ = 0;
    offset_ = 0;
  } else if(ret > 0 && ret < offset_) {
    buf_ = static_cast<const char*>(buf_) + ret;
    offset_ -= ret;
  }
  return ret;
}

void SlowSocket::close() {
  if (-1 == sockfd_) return;

  slowlog(LOG_DEBUG, "closing slow, sock is %d\n", sockfd_);
  if(ssl_) {
    SSL_free(ssl_);
    ssl_ = NULL;
  }
  requests_to_send_ = 0;
  followups_to_send_ = 0;
  ::close(sockfd_);
  sockfd_ = -1;
}

}  // namespace slowhttptest
<commit_msg>fix warning on newer g++<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * *****************************************************************************/

/*****
 * Author: Sergey Shekyan sshekyan@qualys.com
 *
 * Slow HTTP attack  vulnerability test tool
 *  http://code.google.com/p/slowhttptest/
 *****/

#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <string>

#include <openssl/ssl.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "slowlog.h"
#include "slowsocket.h"
#include "slowurl.h"

namespace slowhttptest {
SlowSocket::SlowSocket()
    : sockfd_(-1), requests_to_send_(0),
      followups_to_send_(0), last_followup_timing_(0),
      offset_(0), ssl_(0), buf_(0) {
}

SlowSocket::~SlowSocket() {
  close();
}

int SlowSocket::set_nonblocking() {
  int flags;

  if(-1 == (flags = fcntl(sockfd_, F_GETFL, 0))) {
    flags = 0;
  }
  return fcntl(sockfd_, F_SETFL, flags | O_NONBLOCK);
}

bool SlowSocket::init(addrinfo* addr, const Url* url, int& maxfd,
                      int followups_to_send) {
  addrinfo* res;
  bool connected = false;
  for (res = addr; !connected && res; res = res->ai_next) {
    sockfd_ = socket(res->ai_family, res->ai_socktype,
     res->ai_protocol);
    if(-1 == sockfd_) {
      slowlog(LOG_ERROR, "%s: Failed to create socket\n", __FUNCTION__);
      return false;
    }

    if(-1 == set_nonblocking()) {
      slowlog(LOG_ERROR, "%s: Failed to set socket %d to non-blocking \n", __FUNCTION__,
       sockfd_);
      return false;
    }
    connected = url->isSSL() ? connect_ssl(addr) : connect_plain(addr);
  }

  followups_to_send_ = followups_to_send;
  requests_to_send_ = 1;

  if(sockfd_ > maxfd) {
    maxfd = sockfd_;
  }
  return true;
}

bool SlowSocket::connect_plain(addrinfo* addr) {
  errno = 0;

  if (connect(sockfd_, addr->ai_addr, addr->ai_addrlen) < 0
      && EINPROGRESS != errno) {
    slowlog(LOG_ERROR, "%s: Cannot connect qsocket: %s %d \n", __FUNCTION__,
            strerror(errno), sockfd_);
    close();
    return false;
  }
  return true;
}

bool SlowSocket::connect_ssl(addrinfo* addr) {
  // Establish regular connection.
  if(!connect_plain(addr))  return false;

  // Init SSL related stuff.
  // TODO(vagababov): this is not thread safe of pretty.
  static bool ssl_is_initialized = false;
  if (!ssl_is_initialized) {
    SSL_library_init();
    ssl_is_initialized = true;
  }
  SSL_METHOD* method = NULL;
  SSL_CTX* ssl_ctx = NULL;
  method = (SSL_METHOD*)SSLv23_client_method();
  ssl_ctx = SSL_CTX_new(method);
  if(!ssl_ctx) {
    slowlog(LOG_ERROR, "%s: Cannot create new SSL context\n", __FUNCTION__);
    close();
    return false;
  }
  ssl_ = SSL_new(ssl_ctx);
  if(!ssl_) {
    slowlog(LOG_ERROR, "%s: Cannot create SSL structure for a connection\n",
            __FUNCTION__);
    close();
    return false;
  }
  SSL_set_fd(ssl_, sockfd_);
  int ret = SSL_connect(ssl_);
  if(ret <= 0) {
    int err = SSL_get_error(ssl_, ret);
    slowlog(LOG_ERROR, "%s: SSL connect error: %d\n", __FUNCTION__, err);
    if(SSL_ERROR_WANT_READ != err && SSL_ERROR_WANT_WRITE != err) {
      close();
      return false;
    }
  }
  slowlog(LOG_DEBUG, "%s: SSL connection is using %s\n", __FUNCTION__,
          SSL_get_cipher(ssl_));
  return true;
}

int SlowSocket::recv_slow(void *buf, size_t len) {
  return ssl_ ? SSL_read(ssl_, buf, len)
              : recv(sockfd_, buf, len, 0);
}

int SlowSocket::send_slow(const void* buf, size_t len, const SendType type) {
  // VA: this is not good. create a "prepare" method.
  // initial send
  if(buf_ == 0) {
    buf_ = buf;
    offset_ = len;
  }

  int ret = ssl_ ? SSL_write(ssl_, buf_, offset_)
                 : send(sockfd_, buf_, offset_, 0);

  // entire data was sent
  if(ret > 0 && ret == offset_) {
    if(eInitialSend == type) {
      --requests_to_send_;
    } else if(eFollowUpSend == type) {
      --followups_to_send_;
    }
    buf_ = 0;
    offset_ = 0;
  } else if(ret > 0 && ret < offset_) {
    buf_ = static_cast<const char*>(buf_) + ret;
    offset_ -= ret;
  }
  return ret;
}

void SlowSocket::close() {
  if (-1 == sockfd_) return;

  slowlog(LOG_DEBUG, "closing slow, sock is %d\n", sockfd_);
  if(ssl_) {
    SSL_free(ssl_);
    ssl_ = NULL;
  }
  requests_to_send_ = 0;
  followups_to_send_ = 0;
  ::close(sockfd_);
  sockfd_ = -1;
}

}  // namespace slowhttptest
<|endoftext|>


<commit_before>/*$TET$odrhandling$!cpp-copyright!*/
/*--------------------------------------------------------------------------*/
/*  Copyright 2015 Sergey Vostokin                                          */
/*                                                                          */
/*  Licensed under the Apache License, Version 2.0 (the "License");         */
/*  you may not use this file except in compliance with the License.        */
/*  You may obtain a copy of the License at                                 */
/*                                                                          */
/*  http://www.apache.org/licenses/LICENSE-2.0                              */
/*                                                                          */
/*  Unless required by applicable law or agreed to in writing, software     */
/*  distributed under the License is distributed on an "AS IS" BASIS,       */
/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*/
/*  See the License for the specific language governing permissions and     */
/*  limitations under the License.                                          */
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*	Business process model : Customer Order procedure                       */
/*                                                                          */
/*	A Customer prepares an Order.                                           */
/*	He / she sends the order to Order Handling.                             */
/*	Order Handling checks the order.                                        */
/*	It sends an order confirmation to the Customer.                         */
/*	The Customer receives the order confirmation.                           */
/*	The Customer waits for the product.                                     */
/*	Order Handling sends a delivery request to Shipment. Shipment receives  */
/*	the request and sends the product delivery to the Customer.             */
/*	The Customer receives the product delivery and checks the delivery.     */
/*                                                                          */
/*	Source: S-BPM in the Wild.Practical Value Creation                      */
/*			http://www.springer.com/de/book/9783319175416 (page 280)        */
/*--------------------------------------------------------------------------*/
/*$TET$*/

/*$TET$odrhandling$!templet!*/
/*
~Customer_Order_handling=
+	PREPARES? order -> CHECKS;
	CHECKS! order_conformation -> RECEIVES; RECEIVES?.

~Order_handling_Shipment=
+	SENDS? delivery_request -> RECIEVES; RECIEVES!.

~Shipment_Customer=
+	SEND? product_delivery -> RECIEVES_AND_CHECKS; RECIEVES_AND_CHECKS!.

*Customer=
	order_handling:Customer_Order_handling ! order_conformation->receive;
	shipment:Shipment_Customer ? product_delivery->recieves_and_checks;

+	prepare()->send; send(order_handling!order);
	receive(order_handling?order_conformation);
	recieves_and_checks(shipment?product_delivery).

*Order_handling=
	customer:Customer_Order_handling ? order->check;
	shipment:Order_handling_Shipment !;

	check(customer?order, customer!order_conformation)->send;
	send(shipment!delivery_request).

*Shipment=
	order_handling:Order_handling_Shipment ?
	delivery_request -> receive;
	customer:Shipment_Customer !;

	receive(order_handling?delivery_request) -> deliver;
	deliver(customer!product_delivery).
*/
/*$TET$*/

#include "odrhandling.h"

/*$TET$odrhandling$!cpp-prologue!*/
#include <iostream>
using namespace std;
#include <math.h>
#include <time.h>
/*$TET$*/
//////////////////////class Customer_Order_handling////////////////////
Customer_Order_handling::Customer_Order_handling(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Channel(a)
{
/*$TET$Customer_Order_handling$!constructor!*/
/*$TET$*/
}

Customer_Order_handling::~Customer_Order_handling()
{
/*$TET$Customer_Order_handling$!destructor!*/
/*$TET$*/
}

//////////////////////class Order_handling_Shipment////////////////////
Order_handling_Shipment::Order_handling_Shipment(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Channel(a)
{
/*$TET$Order_handling_Shipment$!constructor!*/
/*$TET$*/
}

Order_handling_Shipment::~Order_handling_Shipment()
{
/*$TET$Order_handling_Shipment$!destructor!*/
/*$TET$*/
}

//////////////////////class Shipment_Customer////////////////////
Shipment_Customer::Shipment_Customer(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Channel(a)
{
/*$TET$Shipment_Customer$!constructor!*/
/*$TET$*/
}

Shipment_Customer::~Shipment_Customer()
{
/*$TET$Shipment_Customer$!destructor!*/
/*$TET$*/
}

//////////////////////class Customer////////////////////
Customer::Customer(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Process(a)
{
/*$TET$Customer$!constructor!*/
/*$TET$*/
}

Customer::~Customer()
{
/*$TET$Customer$!destructor!*/
/*$TET$*/
}

/*$TET$Customer$!usercode!*/
/*$TET$*/

bool Customer::prepare()
{
/*$TET$Customer$prepare*/
		cout << "\tA Customer prepares an Order." << endl;
		return true;
/*$TET$*/
}

bool Customer::send(/*out*/Customer_Order_handling::order*p1)
{
/*$TET$Customer$send*/
		cout << "\tHe/she sends the order to Order Handling." << endl;
		return true;
/*$TET$*/
}

bool Customer::receive(/*in*/Customer_Order_handling::order_conformation*p1)
{
/*$TET$Customer$receive*/
		cout << "\tThe Customer receives the order confirmation." << endl;
		return true;
/*$TET$*/
}

bool Customer::recieves_and_checks(/*in*/Shipment_Customer::product_delivery*p1)
{
/*$TET$Customer$recieves_and_checks*/
		cout << "\tThe Customer receives the product delivery and checks the delivery." << endl;
		return true;
/*$TET$*/
}

void Customer::_run(int _selector,TEMPLET_DBG::Channel*_channel)
{
	bool res;
/*$TET$Customer$!run!*/
		cout << "Customer:" << endl;
/*$TET$*/

}

//////////////////////class Order_handling////////////////////
Order_handling::Order_handling(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Process(a)
{
/*$TET$Order_handling$!constructor!*/
/*$TET$*/
}

Order_handling::~Order_handling()
{
/*$TET$Order_handling$!destructor!*/
/*$TET$*/
}

/*$TET$Order_handling$!usercode!*/
/*$TET$*/

bool Order_handling::check(/*in*/Customer_Order_handling::order*p1,/*out*/Customer_Order_handling::order_conformation*p2)
{
/*$TET$Order_handling$check*/
		cout << "\tOrder Handling checks the order. It sends an order confirmation to the Customer." << endl;
		return true;
/*$TET$*/
}

bool Order_handling::send(/*out*/Order_handling_Shipment::delivery_request*p1)
{
/*$TET$Order_handling$send*/
		cout << "\tOrder Handling sends a delivery request to Shipment." << endl;
		return true;
/*$TET$*/
}

void Order_handling::_run(int _selector,TEMPLET_DBG::Channel*_channel)
{
	bool res;
/*$TET$Order_handling$!run!*/
		cout << "Order handling:" << endl;
/*$TET$*/

}

//////////////////////class Shipment////////////////////
Shipment::Shipment(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Process(a)
{
/*$TET$Shipment$!constructor!*/
/*$TET$*/
}

Shipment::~Shipment()
{
/*$TET$Shipment$!destructor!*/
/*$TET$*/
}

/*$TET$Shipment$!usercode!*/
/*$TET$*/

bool Shipment::receive(/*in*/Order_handling_Shipment::delivery_request*p1)
{
/*$TET$Shipment$receive*/
		cout << "\tShipment receives the request" << endl;
		return true;
/*$TET$*/
}

bool Shipment::deliver(/*out*/Shipment_Customer::product_delivery*p1)
{
/*$TET$Shipment$deliver*/
		cout << "\t  and sends the product delivery to the Customer." << endl;
		return true;
/*$TET$*/
}

void Shipment::_run(int _selector,TEMPLET_DBG::Channel*_channel)
{
	bool res;
/*$TET$Shipment$!run!*/
		cout << "Shipment:" << endl;
/*$TET$*/

}

//////////////////////class odrhandling////////////////////
odrhandling::odrhandling(int NT): TEMPLET_DBG::Assemble(NT)
{
/*$TET$odrhandling$!constructor!*/
/*$TET$*/
}

odrhandling::~odrhandling()
{
/*$TET$odrhandling$!destructor!*/
/*$TET$*/
}

/*$TET$odrhandling$!cpp-epilogue!*/
int main()
{
	odrhandling runtime(1);

	Customer* customer = runtime.new_Customer();
	Order_handling* order_handling = runtime.new_Order_handling();
	Shipment* shipment = runtime.new_Shipment();

	order_handling->p_customer(customer->p_order_handling());
	shipment->p_order_handling(order_handling->p_shipment());
	customer->p_shipment(shipment->p_customer());

	cout << "--Customer Order procedure--" << endl;
	srand(time(NULL));// to show different system behaviors (because of different times of message processing)
	runtime.run();

	return 0;
}
/*$TET$*/

<commit_msg>Update odrhandling.cpp<commit_after>/*$TET$odrhandling$!cpp-copyright!*/
/*--------------------------------------------------------------------------*/
/*  Copyright 2015 Sergey Vostokin                                          */
/*                                                                          */
/*  Licensed under the Apache License, Version 2.0 (the "License");         */
/*  you may not use this file except in compliance with the License.        */
/*  You may obtain a copy of the License at                                 */
/*                                                                          */
/*  http://www.apache.org/licenses/LICENSE-2.0                              */
/*                                                                          */
/*  Unless required by applicable law or agreed to in writing, software     */
/*  distributed under the License is distributed on an "AS IS" BASIS,       */
/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*/
/*  See the License for the specific language governing permissions and     */
/*  limitations under the License.                                          */
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*  Business process model : Customer Order procedure                       */
/*                                                                          */
/*  A Customer prepares an Order.                                           */
/*  He / she sends the order to Order Handling.                             */
/*  Order Handling checks the order.                                        */
/*  It sends an order confirmation to the Customer.                         */
/*  The Customer receives the order confirmation.                           */
/*  The Customer waits for the product.                                     */
/*  Order Handling sends a delivery request to Shipment. Shipment receives  */
/*  the request and sends the product delivery to the Customer.             */
/*  The Customer receives the product delivery and checks the delivery.     */
/*                                                                          */
/*  Source: S-BPM in the Wild.Practical Value Creation                      */
/*          http://www.springer.com/de/book/9783319175416 (page 280)        */
/*--------------------------------------------------------------------------*/
/*$TET$*/

/*$TET$odrhandling$!templet!*/
/*
~Customer_Order_handling=
+	PREPARES? order -> CHECKS;
	CHECKS! order_conformation -> RECEIVES; RECEIVES?.

~Order_handling_Shipment=
+	SENDS? delivery_request -> RECIEVES; RECIEVES!.

~Shipment_Customer=
+	SEND? product_delivery -> RECIEVES_AND_CHECKS; RECIEVES_AND_CHECKS!.

*Customer=
	order_handling:Customer_Order_handling ! order_conformation->receive;
	shipment:Shipment_Customer ? product_delivery->recieves_and_checks;

+	prepare()->send; send(order_handling!order);
	receive(order_handling?order_conformation);
	recieves_and_checks(shipment?product_delivery).

*Order_handling=
	customer:Customer_Order_handling ? order->check;
	shipment:Order_handling_Shipment !;

	check(customer?order, customer!order_conformation)->send;
	send(shipment!delivery_request).

*Shipment=
	order_handling:Order_handling_Shipment ?
	delivery_request -> receive;
	customer:Shipment_Customer !;

	receive(order_handling?delivery_request) -> deliver;
	deliver(customer!product_delivery).
*/
/*$TET$*/

#include "odrhandling.h"

/*$TET$odrhandling$!cpp-prologue!*/
#include <iostream>
using namespace std;
#include <math.h>
#include <time.h>
/*$TET$*/
//////////////////////class Customer_Order_handling////////////////////
Customer_Order_handling::Customer_Order_handling(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Channel(a)
{
/*$TET$Customer_Order_handling$!constructor!*/
/*$TET$*/
}

Customer_Order_handling::~Customer_Order_handling()
{
/*$TET$Customer_Order_handling$!destructor!*/
/*$TET$*/
}

//////////////////////class Order_handling_Shipment////////////////////
Order_handling_Shipment::Order_handling_Shipment(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Channel(a)
{
/*$TET$Order_handling_Shipment$!constructor!*/
/*$TET$*/
}

Order_handling_Shipment::~Order_handling_Shipment()
{
/*$TET$Order_handling_Shipment$!destructor!*/
/*$TET$*/
}

//////////////////////class Shipment_Customer////////////////////
Shipment_Customer::Shipment_Customer(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Channel(a)
{
/*$TET$Shipment_Customer$!constructor!*/
/*$TET$*/
}

Shipment_Customer::~Shipment_Customer()
{
/*$TET$Shipment_Customer$!destructor!*/
/*$TET$*/
}

//////////////////////class Customer////////////////////
Customer::Customer(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Process(a)
{
/*$TET$Customer$!constructor!*/
/*$TET$*/
}

Customer::~Customer()
{
/*$TET$Customer$!destructor!*/
/*$TET$*/
}

/*$TET$Customer$!usercode!*/
/*$TET$*/

bool Customer::prepare()
{
/*$TET$Customer$prepare*/
		cout << "\tA Customer prepares an Order." << endl;
		return true;
/*$TET$*/
}

bool Customer::send(/*out*/Customer_Order_handling::order*p1)
{
/*$TET$Customer$send*/
		cout << "\tHe/she sends the order to Order Handling." << endl;
		return true;
/*$TET$*/
}

bool Customer::receive(/*in*/Customer_Order_handling::order_conformation*p1)
{
/*$TET$Customer$receive*/
		cout << "\tThe Customer receives the order confirmation." << endl;
		return true;
/*$TET$*/
}

bool Customer::recieves_and_checks(/*in*/Shipment_Customer::product_delivery*p1)
{
/*$TET$Customer$recieves_and_checks*/
		cout << "\tThe Customer receives the product delivery and checks the delivery." << endl;
		return true;
/*$TET$*/
}

void Customer::_run(int _selector,TEMPLET_DBG::Channel*_channel)
{
	bool res;
/*$TET$Customer$!run!*/
		cout << "Customer:" << endl;
/*$TET$*/

}

//////////////////////class Order_handling////////////////////
Order_handling::Order_handling(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Process(a)
{
/*$TET$Order_handling$!constructor!*/
/*$TET$*/
}

Order_handling::~Order_handling()
{
/*$TET$Order_handling$!destructor!*/
/*$TET$*/
}

/*$TET$Order_handling$!usercode!*/
/*$TET$*/

bool Order_handling::check(/*in*/Customer_Order_handling::order*p1,/*out*/Customer_Order_handling::order_conformation*p2)
{
/*$TET$Order_handling$check*/
		cout << "\tOrder Handling checks the order. It sends an order confirmation to the Customer." << endl;
		return true;
/*$TET$*/
}

bool Order_handling::send(/*out*/Order_handling_Shipment::delivery_request*p1)
{
/*$TET$Order_handling$send*/
		cout << "\tOrder Handling sends a delivery request to Shipment." << endl;
		return true;
/*$TET$*/
}

void Order_handling::_run(int _selector,TEMPLET_DBG::Channel*_channel)
{
	bool res;
/*$TET$Order_handling$!run!*/
		cout << "Order handling:" << endl;
/*$TET$*/

}

//////////////////////class Shipment////////////////////
Shipment::Shipment(TEMPLET_DBG::Assemble*a):TEMPLET_DBG::Process(a)
{
/*$TET$Shipment$!constructor!*/
/*$TET$*/
}

Shipment::~Shipment()
{
/*$TET$Shipment$!destructor!*/
/*$TET$*/
}

/*$TET$Shipment$!usercode!*/
/*$TET$*/

bool Shipment::receive(/*in*/Order_handling_Shipment::delivery_request*p1)
{
/*$TET$Shipment$receive*/
		cout << "\tShipment receives the request" << endl;
		return true;
/*$TET$*/
}

bool Shipment::deliver(/*out*/Shipment_Customer::product_delivery*p1)
{
/*$TET$Shipment$deliver*/
		cout << "\t  and sends the product delivery to the Customer." << endl;
		return true;
/*$TET$*/
}

void Shipment::_run(int _selector,TEMPLET_DBG::Channel*_channel)
{
	bool res;
/*$TET$Shipment$!run!*/
		cout << "Shipment:" << endl;
/*$TET$*/

}

//////////////////////class odrhandling////////////////////
odrhandling::odrhandling(int NT): TEMPLET_DBG::Assemble(NT)
{
/*$TET$odrhandling$!constructor!*/
/*$TET$*/
}

odrhandling::~odrhandling()
{
/*$TET$odrhandling$!destructor!*/
/*$TET$*/
}

/*$TET$odrhandling$!cpp-epilogue!*/
int main()
{
	odrhandling runtime(1);

	Customer* customer = runtime.new_Customer();
	Order_handling* order_handling = runtime.new_Order_handling();
	Shipment* shipment = runtime.new_Shipment();

	order_handling->p_customer(customer->p_order_handling());
	shipment->p_order_handling(order_handling->p_shipment());
	customer->p_shipment(shipment->p_customer());

	cout << "--Customer Order procedure--" << endl;
	srand(time(NULL));// to show different system behaviors (because of different times of message processing)
	runtime.run();

	return 0;
}
/*$TET$*/

<|endoftext|>


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

static void CaricaBmp(const char *Nome, unsigned char *header, unsigned int &dim_head_bmp, unsigned char * &image, unsigned int & sx, unsigned int & sy)
{
	FILE *fHan = fopen(Nome, "rb"); //Apertura del file in lettura
	if(fHan == NULL) {
		printf("errore!\n");
		exit(1);
	}
    fseek(fHan,14,0); //Salta Header BMP
    fread(&dim_head_bmp,sizeof(int), 1, fHan); //Lettura dimensione header
    fread(&sx,sizeof(int), 1, fHan); // lettura 18-esimo byte che contiene la larghezza [4byte]
    fread(&sy,sizeof(int), 1, fHan); // lettura 22-esimo byte che contiene l' altezza   [4byte]
    dim_head_bmp += 14; //Somma alla dimensione dell'header dell' immagine quella del formato
    rewind(fHan); // Resetta il puntatore al file
	fread(header, dim_head_bmp, 1, fHan); // Caricamento da file dell'header
	image = new unsigned char [sx*sy*3]; //Creazione spazio nello heap per l' Immagine Sorgente
	fread(image, (sx * sy)*3, 1, fHan); //Caricamento dei dati dell'Immagine Sorgente da file
	fclose(fHan); //Chiusura del file
}

static void SalvaBmp(const char *Nome, unsigned char * header, const unsigned int dim_head_bmp, unsigned char *DaDove, int x, int y)
{
	FILE *fHan = fopen(Nome, "wb"); //Apertura del file in scrittura
	if(fHan == NULL) {
		printf("errore!\n");
		exit(1);
	}

    memcpy(header+18, &x, sizeof(unsigned int)); //modifica larghezza
    memcpy(header+22, &y, sizeof(unsigned int)); //modifica altezza
    fwrite(header, dim_head_bmp, 1, fHan); //Scrittura del nuovo header
	fwrite(DaDove, (x * y)*3, 1, fHan); // Trasferimento dell' Immagine Destinazione su file
	fclose(fHan); // Chiusura del file
}

float Bilineare(unsigned char * source, unsigned int sx, unsigned int sy, float x, float y, int n_canali) {

	float v1, v2, v3, v4;
	int X = (int) x;
	int Y = (int) y;

	x -= X;
	y -= Y;

	if(X < 0) X = 0;
	if(X >= ((sx) - 1)) X = (sx) - 1;
	if(Y < 0) Y = 0;
	if(Y >= sy - 1) Y = sy - 1;

    //Ogni coordinata viene moltiplicate per il numero di canali presenti
    v1 = source[X*n_canali + (sx * Y*n_canali) ];
	v2 = source[(X+1)*n_canali + (sx * Y*n_canali)];
	v3 = source[(X)*n_canali + (sx * ((Y+1)*n_canali))];
	v4 = source[(X+1)*n_canali + (sx * ((Y+1)*n_canali))];

	return( ( v1 * (1 - x) * (1 - y)) +
			( v2 * x * (1 - y)) +
			( v3 * (1 - x) * y) +
			( v4 * x * y) );

}

void Ridimensiona(unsigned char * source, unsigned int sx, unsigned int sy, unsigned char * dest, unsigned int dx, unsigned int dy){

   float scalex = ((float)sx) / ((float)dx); //Fattore di scala per la larghezza
   float scaley = ((float)sy) / ((float)dy); //Fattore di scale per l'altezza
   float u, v; //Coordinate da leggere in riferimento all'immagine sorgente

   printf("Fattore di Scala per X: %f\nFattore di Scala per Y: %f\n",scalex,scaley);

/*  Lettura Immagine
            B  G  R
            0  1  2
        0 | FF AF AA
        1 | FF FF FF
        2 | AA FF AA
        ..| .. .. ..
    dx*dy | FF FF FF

*/
   for(int c=0; c<3; c++){ // Canali
        for(int y = 0;y < dy;y++){ //Altezza
            for(int x = 0;x < dx;x++) { // Larghezza
                u = x * scalex; //Fattore di scala per coordinata X
                v = y * scaley; //Fattore di scala per coordinata Y
                float int_canale = Bilineare((source+c),sx,sy,u,v,3); //Ricampionamento con
                                                                    //interpolazione bilineare
                if ( int_canale  > 255 ) int_canale  = 255; //Clamping se maggiore di 255
                if ( int_canale  < 0 ) int_canale  = 0; //Clamping se minore di 0
                dest[c + x*3 +y*dx*3 ] = int_canale; //Scrittura del valore di intensità del canale
                                                      //sull'immagine di destinazione
                }
            }
        }
}

// kernel

#define KD	3
#define OFS	((KD - 1) / 2)

int Kernel[KD * KD] = {
	 0,	0, 0,
	-1,	1, 0,
	 0,	0, 0
};

/*
int Kernel[KD * KD] = {
	 0, 0, 0, 0, 0,
     0, 0,-1, 0, 0,
     0,-1, 5,-1, 0,
     0, 0,-1, 0, 0,
     0, 0, 0, 0, 0
};*/

/*
int Kernel[KD * KD] = {
	0,	0,	1,	0,	0,
	0,	1,	2,	1,	0,
	1,	2,	3,	2,	1,
	0,	1,	2,	1,	0,
	0,	0,	1,	0,	0
};
*/

int Scala = 1;

int Pixel(unsigned char *source,unsigned int sx, unsigned int sy, int x, int y){
	int u, v;
	int a;
	int p = 0;

	for(v = -OFS;v <= OFS;v++) {
		if((y + v) < 0 || (y + v) >= sy) continue;
		for(u = -OFS;u <= OFS;u++) {
			if((x + u)*3 < 0 || (x + u)*3 >= sx*3) continue;

			a = source[(x + u)*3 + ((y + v) * sx*3)];
			p += (a * Kernel[u + OFS + ((v + OFS) * KD)]);
		}
	}

	p /= Scala;

	if(p < 0) p = 0;
	if(p > 255) p = 255;

	return(p);
}

void Convoluzione(unsigned char * source, unsigned int sx, unsigned int sy, unsigned char * dest ) {

	int x, y, c;

    for(c=0;c<3;c++){
        for(y = 0;y < sy;y++) {
            for(x = 0;x < sx;x++) {
                dest[c + x*3 + y*sx*3] = Pixel(source+c, sx, sy, x, y);
            }
        }
    }

}

int main(int argc, char *argv[])
{
	unsigned char header[54]; // Header
	unsigned int dim_head_bmp=0; //Dimensione Header
	unsigned int sx=0; //Larghezza Immagine Sorgente
	unsigned int sy=0; //Altezza Immagine Sorgente
    unsigned int dx = 300; /*atoi(argv[3]);*/ //Larghezza Immagine Destinazione
    unsigned int dy = 394; /*atoi(argv[4]);*/ //Altezza Immagine Destinazione
    unsigned char *ImmagineS = NULL; //Puntatore a Immagine Sorgente
    unsigned char *ImmagineD = new unsigned char[dx*dy*3]; //Creazione spazio per Immagine di Destinazione

	CaricaBmp("acdc_red_ltoh.bmp", header, dim_head_bmp, ImmagineS, sx, sy); //Caricamento Immagine sorgente

    printf("Dimensione immagine: L %d x H %d\n", sx, sy);

    unsigned char *ImmagineF = new unsigned char [sx*sy*3];

	Convoluzione(ImmagineS, sx, sy, ImmagineF);

	Ridimensiona(ImmagineF, sx, sy, ImmagineD, dx, dy); //Ridimensionamento Immagine

	SalvaBmp("output.bmp", header, dim_head_bmp, ImmagineD, dx, dy); //Serializzazione Immagine

	//Deallocazione memoria
	delete[] ImmagineS;
	delete[] ImmagineD;
	delete[] ImmagineF;
	return 0;

}

<commit_msg>Aggiunta gestione parametri, selezione filtro, gestione padding<commit_after>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

static void CaricaBmp(const char *Nome, unsigned char *header, unsigned int &dim_head_bmp, unsigned char * &image, unsigned int & sx, unsigned int & sy)
{
	FILE *fHan = fopen(Nome, "rb"); //Apertura del file in lettura
	if(fHan == NULL) {
		printf("errore!\n");
		exit(1);
	}
    fseek(fHan,14,0); //Salta Header BMP
    fread(&dim_head_bmp,sizeof(int), 1, fHan); //Lettura dimensione header
    fread(&sx,sizeof(int), 1, fHan); // lettura 18-esimo byte che contiene la larghezza [4byte]
    fread(&sy,sizeof(int), 1, fHan); // lettura 22-esimo byte che contiene l' altezza   [4byte]
    dim_head_bmp += 14; //Somma alla dimensione dell'header dell' immagine quella del formato
    rewind(fHan); // Resetta il puntatore al file
	fread(header, dim_head_bmp, 1, fHan); // Caricamento da file dell'header
	int dim = sx*sy*3;
	if((sx*3)%4 != 0){
     dim += ((4 - (sx*3)%4) * sy);
	}
	image = new unsigned char [dim]; //Creazione spazio nello heap per l' Immagine Sorgente
	fread(image, dim, 1, fHan); //Caricamento dei dati dell'Immagine Sorgente da file
	fclose(fHan); //Chiusura del file
}

static void SalvaBmp(const char *Nome, unsigned char * header, const unsigned int dim_head_bmp, unsigned char *DaDove, int x, int y)
{
	FILE *fHan = fopen(Nome, "wb"); //Apertura del file in scrittura
	if(fHan == NULL) {
		printf("errore!\n");
		exit(1);
	}

    memcpy(header+18, &x, sizeof(unsigned int)); //modifica larghezza
    memcpy(header+22, &y, sizeof(unsigned int)); //modifica altezza
    fwrite(header, dim_head_bmp, 1, fHan); //Scrittura del nuovo header
    int dim = x*y*3;
	if((x*3)%4 != 0){
     dim += ((4 - (x*3)%4) * y);
	}
	fwrite(DaDove, dim, 1, fHan); // Trasferimento dell' Immagine Destinazione su file
	fclose(fHan); // Chiusura del file
}

void RimuoviPadding(unsigned char * source, int width, int height, int padding, unsigned char * dest){
    int offset = 0;
    for(int y=0; y<height; y++ ){
        for(int x=0; x<width*3; x++ ){
            dest[x + y*width*3] = source[x+offset + y*width*3];
        }
        offset += padding;
    }
}

void AggiungiPadding(unsigned char * source, int width, int height, int padding, unsigned char * dest){
    int offset = 0;
    for(int y=0; y<height; y++ ){
        for(int x=0; x<width*3; x++ ){
            dest[x+offset+ y*width*3] = source[x + y*width*3];
        }
        if(y>0){
            for(int p=0; p<padding; p++){
                dest[p + offset + y*width*3] = 0;
            }
        }
        offset += padding;
    }
}

float Bilineare(unsigned char * source, unsigned int sx, unsigned int sy, float x, float y, int n_canali) {

	float v1, v2, v3, v4;
	int X = (int) x;
	int Y = (int) y;

	x -= X;
	y -= Y;

	if(X < 0) X = 0;
	if(X >= ((sx) - 1)) X = (sx) - 1;
	if(Y < 0) Y = 0;
	if(Y >= sy - 1) Y = sy - 1;

    //Ogni coordinata viene moltiplicate per il numero di canali presenti
    v1 = source[X*n_canali + (sx * Y*n_canali) ];
	v2 = source[(X+1)*n_canali + (sx * Y*n_canali)];
	v3 = source[(X)*n_canali + (sx * ((Y+1)*n_canali))];
	v4 = source[(X+1)*n_canali + (sx * ((Y+1)*n_canali))];

	return( ( v1 * (1 - x) * (1 - y)) +
			( v2 * x * (1 - y)) +
			( v3 * (1 - x) * y) +
			( v4 * x * y) );

}

void Ridimensiona(unsigned char * source, unsigned int sx, unsigned int sy, unsigned char * dest, unsigned int dx, unsigned int dy){

   float scalex = ((float)sx) / ((float)dx); //Fattore di scala per la larghezza
   float scaley = ((float)sy) / ((float)dy); //Fattore di scale per l'altezza
   float u, v; //Coordinate da leggere in riferimento all'immagine sorgente

   printf("Fattore di Scala per X: %f\nFattore di Scala per Y: %f\n",scalex,scaley);

/*  Lettura Immagine
            B  G  R
            0  1  2
        0 | FF AF AA
        1 | FF FF FF
        2 | AA FF AA
        ..| .. .. ..
    dx*dy | FF FF FF

*/
   for(int c=0; c<3; c++){ // Canali
       printf("C: %d\n",c);
        for(int y = 0;y < dy;y++){ //Altezza
            for(int x = 0;x < dx;x++) { // Larghezza
                u = x * scalex; //Fattore di scala per coordinata X
                v = y * scaley; //Fattore di scala per coordinata Y
                float int_canale = Bilineare((source+c),sx,sy,u,v,3); //Ricampionamento con
                                                                     //interpolazione bilineare
                if ( int_canale  > 255 ) int_canale  = 255; //Clamping se maggiore di 255
                if ( int_canale  < 0 ) int_canale  = 0; //Clamping se minore di 0
                dest[c + x*3 +y*dx*3 ] = int_canale; //Scrittura del valore di intensità del canale
                                                     //sull'immagine di destinazione
                }
            }
        }
}

// kernel

#define OFS ((KD - 1) / 2)

int *Kernel;
int KD;
char* Filtri[4] = {"sharpen", "blur", "bordi", "bassorilievo"};

int Sharpen[5 * 5] = {
	 0, 0, 0, 0, 0,
     0, 0,-1, 0, 0,
     0,-1, 5,-1, 0,
     0, 0,-1, 0, 0,
     0, 0, 0, 0, 0
};

int Blur[5 * 5] = {
	 0, 0, 0, 0, 0,
     0, 1, 1, 1, 0,
     0, 1, 1, 1, 0,
     0, 1, 1, 1, 0,
     0, 0, 0, 0, 0
};

int Bordi[3 * 3] = {
    0, 1, 0,
    1,-4, 1,
    0, 1, 0
};

int BassoRilievo[3 * 3] = {
    -2,-1, 0,
    -1, 1, 1,
     0, 1, 2
};

/*
int Kernel[KD * KD] = {
	0,	0,	1,	0,	0,
	0,	1,	2,	1,	0,
	1,	2,	3,	2,	1,
	0,	1,	2,	1,	0,
	0,	0,	1,	0,	0
};
*/

int Scala = 1;

int Pixel(unsigned char *source,unsigned int sx, unsigned int sy, int x, int y){

	int u, v;
	int a;
	int p = 0;

	for(v = -OFS;v <= OFS;v++) {
		if((y + v) < 0 || (y + v) >= sy) continue;
		for(u = -OFS;u <= OFS;u++) {
			if((x + u)*3 < 0 || (x + u)*3 >= sx*3) continue;

			a = source[(x + u)*3 + ((y + v) * sx*3)];
			p += (a * Kernel[u + OFS + ((v + OFS) * KD)]);
		}
	}

	p /= Scala;

	if(p < 0) p = 0;
	if(p > 255) p = 255;

	return(p);
}

void Convoluzione(unsigned char * source, unsigned int sx, unsigned int sy, unsigned char * dest ) {

	int x, y, c;

    for(c=0;c<3;c++){
        for(y = 0;y < sy;y++) {
            for(x = 0;x < sx;x++) {
                dest[c + x*3 + y*sx*3] = Pixel(source+c, sx, sy, x, y);
            }
        }
    }

}

static void SelezioneFiltro(char * selezione){

    if(strcmp(selezione,Filtri[0]) == 0){
        KD = 5;
        Kernel = Sharpen;
    }else if(strcmp(selezione,Filtri[1]) == 0){
        KD = 5;
        Kernel = Blur;
    }else if(strcmp(selezione,Filtri[2]) == 0){
        KD = 3;
        Kernel = Bordi;
    }else if(strcmp(selezione,Filtri[3]) == 0){
        KD = 3;
        Kernel = BassoRilievo;
    }else{
        printf("Filtro non disponibile");
        exit(1);
    }

}

void ControlloDimensioni(const char *in_dx, unsigned int &out_dx, const char *in_dy, unsigned int &out_dy){

    if(atoi(in_dx) > 0){
        out_dx = atoi(in_dx);
    }else{
        printf("Larghezza non valida\n");
        exit(1);
    }
    if(atoi(in_dy) > 0){
        out_dy = atoi(in_dy);
    }else{
        printf("Altezza non valida\n");
        exit(1);
    }

}

int main(int argc, char *argv[])
{
	unsigned char header[54]; // Header
	unsigned int dim_head_bmp=0; //Dimensione Header
    unsigned int paddingS = 0;
    unsigned int paddingD = 0;
	unsigned int sx=0; //Larghezza Immagine Sorgente
	unsigned int sy=0; //Altezza Immagine Sorgente
    unsigned int dx=0; //Larghezza Immagine Destinazione
    unsigned int dy=0; //Altezza Immagine Destinazione

    ControlloDimensioni(argv[3], dx, argv[4], dy);

    unsigned char *ImmagineS = NULL; //Puntatore a Immagine Sorgente
    unsigned char *ImmagineD = new unsigned char[dx*dy*3]; //Creazione spazio per Immagine di Destinazione

	CaricaBmp(argv[1], header, dim_head_bmp, ImmagineS, sx, sy); //Caricamento Immagine sorgente

    printf("Dimensione immagine: L %d x H %d\n", sx, sy);

    unsigned char *ImmagineF = new unsigned char [sx*sy*3];

    SelezioneFiltro(argv[2]);

    unsigned char *ImmagineSNP;
    if((sx*3)%4 != 0){
      paddingS = 4 - (sx*3)%4;
      ImmagineSNP = new unsigned char [sx*sy*3];
      RimuoviPadding(ImmagineS, sx, sy, paddingS, ImmagineSNP);
      printf("Padding Rimosso\n");
      printf("PaddingS: %d\n",paddingS);
      Convoluzione(ImmagineSNP, sx, sy, ImmagineF);
    }else{
      Convoluzione(ImmagineS, sx, sy, ImmagineF);
    }

    unsigned char *ImmagineDP;
	if((dx*3)%4 != 0){
        paddingD = 4 - ((dx*3)%4);
        printf("PaddingD: %d\n", paddingD);
        ImmagineDP = new unsigned char [(dx*dy*3) + (paddingD*dy)];
	}

    if( (sx != dx) || (sy != dy) ){
        Ridimensiona(ImmagineF, sx, sy, ImmagineD, dx, dy); //Ridimensionamento Immagine
        printf("Ridimensionato\n");
        if(paddingD != 0){
            AggiungiPadding(ImmagineD, dx, dy, paddingD, ImmagineDP);
            printf("Aggiunto Padding \n");
            SalvaBmp( argv[5], header, dim_head_bmp, ImmagineDP, dx, dy); //Serializzazione Immagine
         }else{
            SalvaBmp( argv[5], header, dim_head_bmp, ImmagineD, dx, dy); //Serializzazione Immagine
         }
    }else if( (sx == dx) && (sy == dy) ){
         if(paddingD != 0){
            AggiungiPadding(ImmagineF, dx, dy, paddingD, ImmagineDP);
            printf("Aggiunto Padding\n");
            SalvaBmp( argv[5], header, dim_head_bmp, ImmagineDP, dx, dy); //Serializzazione Immagine
         }else{
            SalvaBmp( argv[5], header, dim_head_bmp, ImmagineF, dx, dy); //Serializzazione Immagine
         }
    }

	//Deallocazione memoria
	delete[] ImmagineS;
	delete[] ImmagineD;
	delete[] ImmagineF;
	if (ImmagineSNP){
    delete[] ImmagineSNP;
	}
	if (ImmagineDP){
    delete[] ImmagineDP;
	}
	return 0;

}

<|endoftext|>