<commit_before>// Copyright (c) 2009 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/gtk/location_bar_view_gtk.h"

#include <string>

#include "app/resource_bundle.h"
#include "base/basictypes.h"
#include "base/gfx/gtk_util.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/alternate_nav_url_fetcher.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/page_transition_types.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/window_open_disposition.h"

namespace {

// We are positioned with a little bit of extra space that we don't use now.
const int kTopMargin = 1;
const int kBottomMargin = 1;
// We don't want to edit control's text to be right against the edge.
const int kEditLeftRightPadding = 4;
// We draw a border on the top and bottom (but not on left or right).
const int kBorderThickness = 1;

// Padding around the security icon.
const int kSecurityIconPaddingLeft = 4;
const int kSecurityIconPaddingRight = 2;

// TODO(deanm): Eventually this should be painted with the background png
// image, but for now we get pretty close by just drawing a solid border.
const GdkColor kBorderColor = GDK_COLOR_RGB(0xbe, 0xc8, 0xd4);

}  // namespace

// static
const GdkColor LocationBarViewGtk::kBackgroundColorByLevel[3] = {
  GDK_COLOR_RGB(255, 245, 195),  // SecurityLevel SECURE: Yellow.
  GDK_COLOR_RGB(255, 255, 255),  // SecurityLevel NORMAL: White.
  GDK_COLOR_RGB(255, 255, 255),  // SecurityLevel INSECURE: White.
};

LocationBarViewGtk::LocationBarViewGtk(CommandUpdater* command_updater,
    ToolbarModel* toolbar_model, AutocompletePopupPositioner* popup_positioner)
    : security_icon_(NULL),
      profile_(NULL),
      command_updater_(command_updater),
      toolbar_model_(toolbar_model),
      popup_positioner_(popup_positioner),
      disposition_(CURRENT_TAB),
      transition_(PageTransition::TYPED) {
}

LocationBarViewGtk::~LocationBarViewGtk() {
  // All of our widgets should have be children of / owned by the alignment.
  alignment_.Destroy();
}

void LocationBarViewGtk::Init() {
  location_entry_.reset(new AutocompleteEditViewGtk(this,
                                                    toolbar_model_,
                                                    profile_,
                                                    command_updater_,
                                                    popup_positioner_));
  location_entry_->Init();

  alignment_.Own(gtk_alignment_new(0.0, 0.0, 1.0, 1.0));
  UpdateAlignmentPadding();
  // We will paint for the alignment, to paint the background and border.
  gtk_widget_set_app_paintable(alignment_.get(), TRUE);
  // Have GTK double buffer around the expose signal.
  gtk_widget_set_double_buffered(alignment_.get(), TRUE);
  g_signal_connect(alignment_.get(), "expose-event",
                   G_CALLBACK(&HandleExposeThunk), this);

  gtk_container_add(GTK_CONTAINER(alignment_.get()),
                    location_entry_->widget());
}

void LocationBarViewGtk::SetProfile(Profile* profile) {
  profile_ = profile;
}

void LocationBarViewGtk::Update(const TabContents* contents) {
  SetSecurityIcon(toolbar_model_->GetIcon());
  location_entry_->Update(contents);
  // The security level (background color) could have changed, etc.
  gtk_widget_queue_draw(alignment_.get());
}

void LocationBarViewGtk::OnAutocompleteAccept(const GURL& url,
      WindowOpenDisposition disposition,
      PageTransition::Type transition,
      const GURL& alternate_nav_url) {
  if (!url.is_valid())
    return;

  location_input_ = UTF8ToWide(url.spec());
  disposition_ = disposition;
  transition_ = transition;

  if (!command_updater_)
    return;

  if (!alternate_nav_url.is_valid()) {
    command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
    return;
  }

  scoped_ptr<AlternateNavURLFetcher> fetcher(
      new AlternateNavURLFetcher(alternate_nav_url));
  // The AlternateNavURLFetcher will listen for the pending navigation
  // notification that will be issued as a result of the "open URL." It
  // will automatically install itself into that navigation controller.
  command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
  if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) {
    // I'm not sure this should be reachable, but I'm not also sure enough
    // that it shouldn't to stick in a NOTREACHED().  In any case, this is
    // harmless; we can simply let the fetcher get deleted here and it will
    // clean itself up properly.
  } else {
    fetcher.release();  // The navigation controller will delete the fetcher.
  }
}

void LocationBarViewGtk::OnChanged() {
  // TODO(deanm): Here is where we would do layout when we have things like
  // the keyword display, ssl icons, etc.
}

void LocationBarViewGtk::OnInputInProgress(bool in_progress) {
  // Here's a comment copied from the Windows code, which propagates this
  // call up to the toolbar.
  // "Called by the location bar view when the user starts typing in the edit.
  // This forces our security style to be UNKNOWN for the duration of the
  // editing."
  // http://code.google.com/p/chromium/issues/detail?id=10965
}

SkBitmap LocationBarViewGtk::GetFavIcon() const {
  NOTIMPLEMENTED();
  return SkBitmap();
}

std::wstring LocationBarViewGtk::GetTitle() const {
  NOTIMPLEMENTED();
  return std::wstring();
}

void LocationBarViewGtk::ShowFirstRunBubble(bool use_OEM_bubble) {
  NOTIMPLEMENTED();
}

std::wstring LocationBarViewGtk::GetInputString() const {
  return location_input_;
}

WindowOpenDisposition LocationBarViewGtk::GetWindowOpenDisposition() const {
  return disposition_;
}

PageTransition::Type LocationBarViewGtk::GetPageTransition() const {
  return transition_;
}

void LocationBarViewGtk::AcceptInput() {
  AcceptInputWithDisposition(CURRENT_TAB);
}

void LocationBarViewGtk::AcceptInputWithDisposition(
    WindowOpenDisposition disposition) {
  location_entry_->model()->AcceptInput(disposition, false);
}

void LocationBarViewGtk::FocusLocation() {
  location_entry_->SetFocus();
  location_entry_->SelectAll(true);
}

void LocationBarViewGtk::FocusSearch() {
  location_entry_->SetUserText(L"?");
  location_entry_->SetFocus();
}

void LocationBarViewGtk::UpdatePageActions() {
  // http://code.google.com/p/chromium/issues/detail?id=11973
}

void LocationBarViewGtk::SaveStateToContents(TabContents* contents) {
  // http://crbug.com/9225
}

void LocationBarViewGtk::Revert() {
  location_entry_->RevertAll();
}

gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget,
                                          GdkEventExpose* event) {
  GdkDrawable* drawable = GDK_DRAWABLE(event->window);
  GdkGC* gc = gdk_gc_new(drawable);

  GdkRectangle* alloc_rect = &alignment_.get()->allocation;

  // The area outside of our margin, which includes the border.
  GdkRectangle inner_rect = {
      alloc_rect->x,
      alloc_rect->y + kTopMargin,
      alloc_rect->width,
      alloc_rect->height - kTopMargin - kBottomMargin};

  // Some of our calculations are a bit sloppy.  Since we draw on our parent
  // window, set a clip to make sure that we don't draw outside.
  gdk_gc_set_clip_rectangle(gc, &inner_rect);

  // Draw our 1px border.  TODO(deanm): Maybe this would be cleaner as an
  // overdrawn stroked rect with a clip to the allocation?
  gdk_gc_set_rgb_fg_color(gc, &kBorderColor);
  gdk_draw_rectangle(drawable, gc, TRUE,
                     inner_rect.x,
                     inner_rect.y,
                     inner_rect.width,
                     kBorderThickness);
  gdk_draw_rectangle(drawable, gc, TRUE,
                     inner_rect.x,
                     inner_rect.y + inner_rect.height - kBorderThickness,
                     inner_rect.width,
                     kBorderThickness);

  // Draw the background within the border.
  gdk_gc_set_rgb_fg_color(gc,
      &kBackgroundColorByLevel[toolbar_model_->GetSchemeSecurityLevel()]);
  gdk_draw_rectangle(drawable, gc, TRUE,
                     inner_rect.x,
                     inner_rect.y + kBorderThickness,
                     inner_rect.width,
                     inner_rect.height - (kBorderThickness * 2));

  // If we have an SSL icon, draw it vertically centered on the right side.
  if (security_icon_) {
    int icon_width = gdk_pixbuf_get_width(security_icon_);
    int icon_height = gdk_pixbuf_get_height(security_icon_);
    int icon_x = inner_rect.x + inner_rect.width -
        kBorderThickness - icon_width - kSecurityIconPaddingRight;
    int icon_y = inner_rect.y +
        ((inner_rect.height - icon_height) / 2);
    gdk_draw_pixbuf(drawable, gc, security_icon_,
                    0, 0, icon_x, icon_y, -1, -1,
                    GDK_RGB_DITHER_NONE, 0, 0);
  }

  g_object_unref(gc);

  return FALSE;  // Continue propagating the expose.
}

void LocationBarViewGtk::UpdateAlignmentPadding() {
  // When we have an icon, increase our right padding to make space for it.
  int right_padding = security_icon_ ? gdk_pixbuf_get_width(security_icon_) +
      kSecurityIconPaddingLeft + kSecurityIconPaddingRight :
      kEditLeftRightPadding;

  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_.get()),
                            kTopMargin + kBorderThickness,
                            kBottomMargin + kBorderThickness,
                            kEditLeftRightPadding, right_padding);
}

void LocationBarViewGtk::SetSecurityIcon(ToolbarModel::Icon icon) {
  static ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  static GdkPixbuf* kLockIcon = rb.GetPixbufNamed(IDR_LOCK);
  static GdkPixbuf* kWarningIcon = rb.GetPixbufNamed(IDR_WARNING);

  switch (icon) {
    case ToolbarModel::LOCK_ICON:
      security_icon_ = kLockIcon;
      break;
    case ToolbarModel::WARNING_ICON:
      security_icon_ = kWarningIcon;
      break;
    case ToolbarModel::NO_ICON:
      security_icon_ = NULL;
      break;
    default:
      NOTREACHED();
      security_icon_ = NULL;
      break;
  }

  // Make sure there is room for the icon.
  UpdateAlignmentPadding();
}
<commit_msg>Linux Omnibox, handle OnInputInProgress to clear the security style.<commit_after>// Copyright (c) 2009 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/gtk/location_bar_view_gtk.h"

#include <string>

#include "app/resource_bundle.h"
#include "base/basictypes.h"
#include "base/gfx/gtk_util.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/alternate_nav_url_fetcher.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/page_transition_types.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/window_open_disposition.h"

namespace {

// We are positioned with a little bit of extra space that we don't use now.
const int kTopMargin = 1;
const int kBottomMargin = 1;
// We don't want to edit control's text to be right against the edge.
const int kEditLeftRightPadding = 4;
// We draw a border on the top and bottom (but not on left or right).
const int kBorderThickness = 1;

// Padding around the security icon.
const int kSecurityIconPaddingLeft = 4;
const int kSecurityIconPaddingRight = 2;

// TODO(deanm): Eventually this should be painted with the background png
// image, but for now we get pretty close by just drawing a solid border.
const GdkColor kBorderColor = GDK_COLOR_RGB(0xbe, 0xc8, 0xd4);

}  // namespace

// static
const GdkColor LocationBarViewGtk::kBackgroundColorByLevel[3] = {
  GDK_COLOR_RGB(255, 245, 195),  // SecurityLevel SECURE: Yellow.
  GDK_COLOR_RGB(255, 255, 255),  // SecurityLevel NORMAL: White.
  GDK_COLOR_RGB(255, 255, 255),  // SecurityLevel INSECURE: White.
};

LocationBarViewGtk::LocationBarViewGtk(CommandUpdater* command_updater,
    ToolbarModel* toolbar_model, AutocompletePopupPositioner* popup_positioner)
    : security_icon_(NULL),
      profile_(NULL),
      command_updater_(command_updater),
      toolbar_model_(toolbar_model),
      popup_positioner_(popup_positioner),
      disposition_(CURRENT_TAB),
      transition_(PageTransition::TYPED) {
}

LocationBarViewGtk::~LocationBarViewGtk() {
  // All of our widgets should have be children of / owned by the alignment.
  alignment_.Destroy();
}

void LocationBarViewGtk::Init() {
  location_entry_.reset(new AutocompleteEditViewGtk(this,
                                                    toolbar_model_,
                                                    profile_,
                                                    command_updater_,
                                                    popup_positioner_));
  location_entry_->Init();

  alignment_.Own(gtk_alignment_new(0.0, 0.0, 1.0, 1.0));
  UpdateAlignmentPadding();
  // We will paint for the alignment, to paint the background and border.
  gtk_widget_set_app_paintable(alignment_.get(), TRUE);
  // Have GTK double buffer around the expose signal.
  gtk_widget_set_double_buffered(alignment_.get(), TRUE);
  g_signal_connect(alignment_.get(), "expose-event",
                   G_CALLBACK(&HandleExposeThunk), this);

  gtk_container_add(GTK_CONTAINER(alignment_.get()),
                    location_entry_->widget());
}

void LocationBarViewGtk::SetProfile(Profile* profile) {
  profile_ = profile;
}

void LocationBarViewGtk::Update(const TabContents* contents) {
  SetSecurityIcon(toolbar_model_->GetIcon());
  location_entry_->Update(contents);
  // The security level (background color) could have changed, etc.
  gtk_widget_queue_draw(alignment_.get());
}

void LocationBarViewGtk::OnAutocompleteAccept(const GURL& url,
      WindowOpenDisposition disposition,
      PageTransition::Type transition,
      const GURL& alternate_nav_url) {
  if (!url.is_valid())
    return;

  location_input_ = UTF8ToWide(url.spec());
  disposition_ = disposition;
  transition_ = transition;

  if (!command_updater_)
    return;

  if (!alternate_nav_url.is_valid()) {
    command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
    return;
  }

  scoped_ptr<AlternateNavURLFetcher> fetcher(
      new AlternateNavURLFetcher(alternate_nav_url));
  // The AlternateNavURLFetcher will listen for the pending navigation
  // notification that will be issued as a result of the "open URL." It
  // will automatically install itself into that navigation controller.
  command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
  if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) {
    // I'm not sure this should be reachable, but I'm not also sure enough
    // that it shouldn't to stick in a NOTREACHED().  In any case, this is
    // harmless; we can simply let the fetcher get deleted here and it will
    // clean itself up properly.
  } else {
    fetcher.release();  // The navigation controller will delete the fetcher.
  }
}

void LocationBarViewGtk::OnChanged() {
  // TODO(deanm): Here is where we would do layout when we have things like
  // the keyword display, ssl icons, etc.
}

void LocationBarViewGtk::OnInputInProgress(bool in_progress) {
  // This is identical to the Windows code, except that we don't proxy the call
  // back through the Toolbar, and just access the model here.
  // The edit should make sure we're only notified when something changes.
  DCHECK(toolbar_model_->input_in_progress() != in_progress);

  toolbar_model_->set_input_in_progress(in_progress);
  Update(NULL);
}

SkBitmap LocationBarViewGtk::GetFavIcon() const {
  NOTIMPLEMENTED();
  return SkBitmap();
}

std::wstring LocationBarViewGtk::GetTitle() const {
  NOTIMPLEMENTED();
  return std::wstring();
}

void LocationBarViewGtk::ShowFirstRunBubble(bool use_OEM_bubble) {
  NOTIMPLEMENTED();
}

std::wstring LocationBarViewGtk::GetInputString() const {
  return location_input_;
}

WindowOpenDisposition LocationBarViewGtk::GetWindowOpenDisposition() const {
  return disposition_;
}

PageTransition::Type LocationBarViewGtk::GetPageTransition() const {
  return transition_;
}

void LocationBarViewGtk::AcceptInput() {
  AcceptInputWithDisposition(CURRENT_TAB);
}

void LocationBarViewGtk::AcceptInputWithDisposition(
    WindowOpenDisposition disposition) {
  location_entry_->model()->AcceptInput(disposition, false);
}

void LocationBarViewGtk::FocusLocation() {
  location_entry_->SetFocus();
  location_entry_->SelectAll(true);
}

void LocationBarViewGtk::FocusSearch() {
  location_entry_->SetUserText(L"?");
  location_entry_->SetFocus();
}

void LocationBarViewGtk::UpdatePageActions() {
  // http://code.google.com/p/chromium/issues/detail?id=11973
}

void LocationBarViewGtk::SaveStateToContents(TabContents* contents) {
  // http://crbug.com/9225
}

void LocationBarViewGtk::Revert() {
  location_entry_->RevertAll();
}

gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget,
                                          GdkEventExpose* event) {
  GdkDrawable* drawable = GDK_DRAWABLE(event->window);
  GdkGC* gc = gdk_gc_new(drawable);

  GdkRectangle* alloc_rect = &alignment_.get()->allocation;

  // The area outside of our margin, which includes the border.
  GdkRectangle inner_rect = {
      alloc_rect->x,
      alloc_rect->y + kTopMargin,
      alloc_rect->width,
      alloc_rect->height - kTopMargin - kBottomMargin};

  // Some of our calculations are a bit sloppy.  Since we draw on our parent
  // window, set a clip to make sure that we don't draw outside.
  gdk_gc_set_clip_rectangle(gc, &inner_rect);

  // Draw our 1px border.  TODO(deanm): Maybe this would be cleaner as an
  // overdrawn stroked rect with a clip to the allocation?
  gdk_gc_set_rgb_fg_color(gc, &kBorderColor);
  gdk_draw_rectangle(drawable, gc, TRUE,
                     inner_rect.x,
                     inner_rect.y,
                     inner_rect.width,
                     kBorderThickness);
  gdk_draw_rectangle(drawable, gc, TRUE,
                     inner_rect.x,
                     inner_rect.y + inner_rect.height - kBorderThickness,
                     inner_rect.width,
                     kBorderThickness);

  // Draw the background within the border.
  gdk_gc_set_rgb_fg_color(gc,
      &kBackgroundColorByLevel[toolbar_model_->GetSchemeSecurityLevel()]);
  gdk_draw_rectangle(drawable, gc, TRUE,
                     inner_rect.x,
                     inner_rect.y + kBorderThickness,
                     inner_rect.width,
                     inner_rect.height - (kBorderThickness * 2));

  // If we have an SSL icon, draw it vertically centered on the right side.
  if (security_icon_) {
    int icon_width = gdk_pixbuf_get_width(security_icon_);
    int icon_height = gdk_pixbuf_get_height(security_icon_);
    int icon_x = inner_rect.x + inner_rect.width -
        kBorderThickness - icon_width - kSecurityIconPaddingRight;
    int icon_y = inner_rect.y +
        ((inner_rect.height - icon_height) / 2);
    gdk_draw_pixbuf(drawable, gc, security_icon_,
                    0, 0, icon_x, icon_y, -1, -1,
                    GDK_RGB_DITHER_NONE, 0, 0);
  }

  g_object_unref(gc);

  return FALSE;  // Continue propagating the expose.
}

void LocationBarViewGtk::UpdateAlignmentPadding() {
  // When we have an icon, increase our right padding to make space for it.
  int right_padding = security_icon_ ? gdk_pixbuf_get_width(security_icon_) +
      kSecurityIconPaddingLeft + kSecurityIconPaddingRight :
      kEditLeftRightPadding;

  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_.get()),
                            kTopMargin + kBorderThickness,
                            kBottomMargin + kBorderThickness,
                            kEditLeftRightPadding, right_padding);
}

void LocationBarViewGtk::SetSecurityIcon(ToolbarModel::Icon icon) {
  static ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  static GdkPixbuf* kLockIcon = rb.GetPixbufNamed(IDR_LOCK);
  static GdkPixbuf* kWarningIcon = rb.GetPixbufNamed(IDR_WARNING);

  switch (icon) {
    case ToolbarModel::LOCK_ICON:
      security_icon_ = kLockIcon;
      break;
    case ToolbarModel::WARNING_ICON:
      security_icon_ = kWarningIcon;
      break;
    case ToolbarModel::NO_ICON:
      security_icon_ = NULL;
      break;
    default:
      NOTREACHED();
      security_icon_ = NULL;
      break;
  }

  // Make sure there is room for the icon.
  UpdateAlignmentPadding();
}
<|endoftext|>


<commit_before>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2021 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#ifndef __YLIKUUTIO_ONTOLOGY_VARIABLE_STRUCT_HPP_INCLUDED
#define __YLIKUUTIO_ONTOLOGY_VARIABLE_STRUCT_HPP_INCLUDED

#include "entity_struct.hpp"
#include "activate_callback.hpp"
#include "read_callback.hpp"

// Include standard headers
#include <memory> // std::make_shared, std::shared_ptr

namespace yli::data
{
    class AnyValue;
}

namespace yli::ontology
{
    class Entity;

    struct VariableStruct: public yli::ontology::EntityStruct
    {
        VariableStruct()
        {
            // constructor.
            this->is_variable = true;
        }

        VariableStruct(std::shared_ptr<yli::data::AnyValue> initial_value)
            : initial_value { initial_value }
        {
            // constructor.
            this->is_variable = true;
        }

        VariableStruct(const yli::ontology::VariableStruct& variable_struct)
            : EntityStruct(variable_struct),
            parent { variable_struct.parent },
            initial_value { variable_struct.initial_value },
            activate_callback { variable_struct.activate_callback },
            read_callback { variable_struct.read_callback },
            should_call_activate_callback_now { variable_struct.should_call_activate_callback_now }
        {
            // copy constructor.
            this->global_name = variable_struct.global_name;
            this->local_name = variable_struct.local_name;
            this->is_variable = true;
        }

        yli::ontology::Entity* parent                      { nullptr };
        std::shared_ptr<yli::data::AnyValue> initial_value { nullptr };
        ActivateCallback activate_callback                 { nullptr };
        ReadCallback read_callback                         { nullptr };
        bool should_call_activate_callback_now             { true };
    };
}

#endif
<commit_msg>`VariableStruct`: make 1 parameter constructor `explicit`.<commit_after>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2021 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#ifndef __YLIKUUTIO_ONTOLOGY_VARIABLE_STRUCT_HPP_INCLUDED
#define __YLIKUUTIO_ONTOLOGY_VARIABLE_STRUCT_HPP_INCLUDED

#include "entity_struct.hpp"
#include "activate_callback.hpp"
#include "read_callback.hpp"

// Include standard headers
#include <memory> // std::make_shared, std::shared_ptr

namespace yli::data
{
    class AnyValue;
}

namespace yli::ontology
{
    class Entity;

    struct VariableStruct: public yli::ontology::EntityStruct
    {
        VariableStruct()
        {
            // constructor.
            this->is_variable = true;
        }

        explicit VariableStruct(std::shared_ptr<yli::data::AnyValue> initial_value)
            : initial_value { initial_value }
        {
            // constructor.
            this->is_variable = true;
        }

        VariableStruct(const yli::ontology::VariableStruct& variable_struct)
            : EntityStruct(variable_struct),
            parent { variable_struct.parent },
            initial_value { variable_struct.initial_value },
            activate_callback { variable_struct.activate_callback },
            read_callback { variable_struct.read_callback },
            should_call_activate_callback_now { variable_struct.should_call_activate_callback_now }
        {
            // copy constructor.
            this->global_name = variable_struct.global_name;
            this->local_name = variable_struct.local_name;
            this->is_variable = true;
        }

        yli::ontology::Entity* parent                      { nullptr };
        std::shared_ptr<yli::data::AnyValue> initial_value { nullptr };
        ActivateCallback activate_callback                 { nullptr };
        ReadCallback read_callback                         { nullptr };
        bool should_call_activate_callback_now             { true };
    };
}

#endif
<|endoftext|>


<commit_before>#include "colibri_ca.h"
#include "colibri_local_nav.h"
#include "colibri_action.h"
#include "PID_controller.h"
#include "global_planner.h"
#include "task_mgr.h"

#include <boost/bind.hpp>

#include "geometry_msgs/PoseStamped.h"

void PlannerCallback(planner *plannerObj, float* start_pos, float* goal_pos, bool *finish_flag);

int main(int argc, char* argv[])
{

	ros::init(argc, argv, "Nav_Mult_RvizGoal_Node");

	scan_ca scan4caObj;
	local_nav local4navObj;
	nav_action actionObj;
	planner plannerObj;
	task_mgr taskObj;

	ROS_INFO("Start to Go to Mult Rviz Goal ... ");

	ros::Rate loop_rate(10);		// ctrl  freq 10 hz
	unsigned int delay_cnt = 0;

	float tmp_delta_dis = 0.0;
	float tmp_robot2goal_yaw = 0.0;
	float tmp_laser2goal_yaw = 0.0;
	bool goal_inlaser_flag = true;
	float dir_goal_in_laser = 0.0;
	float self_rotation_angle = 0.0;

	unsigned int turn_adj_flag = 1;

	float tmp_action_cmd_t[2] = {0.0, 0.0};
	float* ptr_action_cmd_t = tmp_action_cmd_t;
	float newyaw = 145.0;
	unsigned int micro_adj_flag = 0;

	unsigned int adj_flag = 0;

	bool obtain_flag = false;
	unsigned int search_start = 0;

	ros::NodeHandle nh_fp;
	ros::Timer planner_timer;
	bool finish_plan = false;

	bool tmp_timer_finish =false;
	bool *timer_finish = &tmp_timer_finish;

	static unsigned int index4gravaton = 0;

	float delta_robot2gravaton = 0.0;
	bool at_gravaton_flag = false;
	bool exist_gravaton_flag = false;
	bool replan_flag = false;

	float rt_r2g_dis = 100.0;

	while(taskObj.obtain_goal_flag == false)
	{
		ros::spinOnce();
		loop_rate.sleep();

	}

	local4navObj.goal_state[0] = taskObj.cur_goal[0];
	local4navObj.goal_state[1] = taskObj.cur_goal[1];
	local4navObj.goal_state[2] = taskObj.cur_goal[2];

	cout<<" local4navObj.goal_state.x = "<<local4navObj.goal_state[0]<<endl;
	cout<<" local4navObj.goal_state.y = "<<local4navObj.goal_state[1]<<endl;

	while (!ros::service::waitForService(plannerObj.srv4make_plan, ros::Duration(0.2)))
	{
		ROS_INFO("Waiting for service move_base/make_plan to become available");
	}

	ROS_INFO("Service move_base/make_plan prepared OK...");

	finish_plan = plannerObj.ExecMonoPlanAndGravaton(plannerObj,&local4navObj.cur_robot_state[0],&local4navObj.goal_state[0], search_start,index4gravaton);

	planner_timer = nh_fp.createTimer(ros::Duration(PLAN_INTERVAL), boost::bind(&PlannerCallback, &plannerObj, &local4navObj.amcl_cur_state[0],&taskObj.cur_goal[0], timer_finish));

	while (ros::ok())
	{

		if(delay_cnt < DELAY_CNT_MAX)
		{
			delay_cnt++;
			ros::spinOnce();
			loop_rate.sleep();
		}

		if(delay_cnt >= DELAY_CNT_MAX)
		{
			ROS_INFO("------ start ------");
			if(*timer_finish == true)
			{
				*timer_finish = false;
				index4gravaton = 0;
				replan_flag = true;

			}else
			{

				if((at_gravaton_flag == true && local4navObj.approaching_flag == false)||(replan_flag == true))
				{
					plannerObj.CalcPath2RobotDeltaDis(plannerObj.path_array, local4navObj.amcl_cur_state);
					index4gravaton = plannerObj.CalcGravatonFromPath(plannerObj.path_array, plannerObj.path2robot_array, index4gravaton, plannerObj.gravaton,exist_gravaton_flag);

					at_gravaton_flag = false;
					replan_flag = false;

				}

				at_gravaton_flag = actionObj.ReachGravatonOK(&local4navObj.amcl_cur_state[0],&plannerObj.gravaton.x, delta_robot2gravaton);

				if(local4navObj.approaching_flag == true)
				{
					plannerObj.gravaton.x = taskObj.cur_goal[0];
					plannerObj.gravaton.y = taskObj.cur_goal[1];
					plannerObj.gravaton.yaw = taskObj.cur_goal[2];

				}
			}

			local4navObj.CalcOffsetOfGoalAndRobot(local4navObj.amcl_cur_state, &plannerObj.gravaton.x, &tmp_delta_dis, &tmp_robot2goal_yaw, &tmp_laser2goal_yaw);

			goal_inlaser_flag = local4navObj.CalcGoalDirOfLaserViewNew(&tmp_laser2goal_yaw, &local4navObj.amcl_cur_state[2], &dir_goal_in_laser, &self_rotation_angle);

			scan4caObj.CalcPhiParam(local4navObj.cur_robot_vel[0], dir_goal_in_laser);

			scan4caObj.CalcKrfTheta(scan4caObj.kp_phi_vec, scan4caObj.phi_start_vec, scan4caObj.phi_end_vec);
			scan4caObj.CalcCorrectedKrf();
			scan4caObj.CalcPassFcnAndFwdBnd(scan4caObj.wander, &scan4caObj.max_passfcn_val, scan4caObj.passfcn_vec);
			scan4caObj.CalcPassFcnAndBwdBnd(scan4caObj.wander, &scan4caObj.max_passfcn_val, scan4caObj.passfcn_vec);

			scan4caObj.angle_adj = scan4caObj.CalcAdjDir(scan4caObj.passfcn_vec,scan4caObj.max_passfcn_val, &scan4caObj.maxfcn_fwdbnd,&scan4caObj.maxfcn_bwdbnd);

			scan4caObj.CalcCollisionInAPF();

			if(goal_inlaser_flag == true)
			{
				local4navObj.apf_ctrl_output[0] = (V_MAX - V_MIN) * (scan4caObj.max_passfcn_val / D_M) + V_MIN;
				local4navObj.apf_ctrl_output[1] = scan4caObj.angle_adj / 200.0;
			}
			else
			{
				local4navObj.apf_ctrl_output[0] = 0.0;
				local4navObj.apf_ctrl_output[1] = 0.0;
			}

			local4navObj.SatuateCmdVel(local4navObj.apf_ctrl_output,local4navObj.apf_ctrl_output+1);

			local4navObj.CalcEuclidDistance(local4navObj.amcl_cur_state, taskObj.cur_goal, rt_r2g_dis);

			local4navObj.approaching_flag = local4navObj.ReachApprochingAreaOK(&rt_r2g_dis);

			if(tmp_delta_dis >= GOAL_NGHBORHD)
			{
				ptr_action_cmd_t = actionObj.AdjustMovingDirAction(&local4navObj.amcl_cur_state[2], &dir_goal_in_laser, &tmp_robot2goal_yaw, &turn_adj_flag);
			}
			else
			{

			}

			if(turn_adj_flag == 1)
			{
				if(local4navObj.approaching_flag == false)
				{
					*ptr_action_cmd_t = local4navObj.apf_ctrl_output[0];
					*(ptr_action_cmd_t + 1) = local4navObj.apf_ctrl_output[1];
				}
				else
				{
					ptr_action_cmd_t = actionObj.ApproachingGoalAction(&local4navObj.amcl_cur_state[0],&local4navObj.goal_state[0],&dir_goal_in_laser,&micro_adj_flag);
				}

			}

			cout<<"carto_current_robot_state[0]"<<local4navObj.cur_robot_state[0]<<endl;
			cout<<"carto_current_robot_state[1]"<<local4navObj.cur_robot_state[1]<<endl;
			cout<<"carto_current_robot_state[2]"<<local4navObj.cur_robot_state[2]<<endl;

			cout<<"amcl_current_robot_state[0]"<<local4navObj.amcl_cur_state[0]<<endl;
			cout<<"amcl_current_robot_state[1]"<<local4navObj.amcl_cur_state[1]<<endl;
			cout<<"amcl_current_robot_state[2]"<<local4navObj.amcl_cur_state[2]<<endl;

			cout<<"adj_angle: "<< scan4caObj.angle_adj <<endl;

			cout<<"tmp_delta_dis: "<<tmp_delta_dis<<endl;
			cout<<"tmp_robot2goal_yaw: "<<tmp_robot2goal_yaw<<endl;
			cout<<"tmp_laser2goal_yaw: "<<tmp_laser2goal_yaw<<endl;

			cout<<"dir_goal_in_laser: "<<dir_goal_in_laser<<endl;

			//local4navObj.position_OK_flag = local4navObj.ReachGoalPositionOK(&tmp_delta_dis);

			local4navObj.SatuateCmdVel(ptr_action_cmd_t,ptr_action_cmd_t + 1);

			local4navObj.apf_cmd_vel.linear.x = *ptr_action_cmd_t;
			local4navObj.apf_cmd_vel.angular.z = *(ptr_action_cmd_t + 1);

			if(local4navObj.position_OK_flag == true)
			{
				local4navObj.apf_cmd_vel.linear.x = 0.0;
				local4navObj.apf_cmd_vel.angular.z = 0.0;
			}

			cout<<"approaching_flag: " << local4navObj.approaching_flag <<endl;
			cout<<"position_OK_flag: " << local4navObj.position_OK_flag <<endl;

			local4navObj.pub_apf_twist.publish(local4navObj.apf_cmd_vel);

			cout<<"pub_linear_x: " << local4navObj.apf_cmd_vel.linear.x <<endl;
			cout<<"pub_angular_z: " << local4navObj.apf_cmd_vel.angular.z <<endl;

			scan4caObj.fwd_maxpass_num = 0;
			scan4caObj.bwd_maxpass_num = 0;

			cout<<"taskObj.cur_goal[0]: "<<taskObj.cur_goal[0]<<endl;
			cout<<"taskObj.cur_goal[1]: "<<taskObj.cur_goal[1]<<endl;
			cout<<"taskObj.cur_goal[2]: "<<taskObj.cur_goal[2]<<endl;

			ros::spinOnce();
			loop_rate.sleep();
			ROS_INFO("------- end --------");
		}
	}

	local4navObj.apf_cmd_vel.linear.x = 0.0;
	local4navObj.apf_cmd_vel.angular.z = 0.0;

	local4navObj.pub_apf_twist.publish(local4navObj.apf_cmd_vel);

	return 0;
}

void PlannerCallback(planner *plannerObj, float* start_pos, float* goal_pos, bool *finish_flag)
{
	plannerObj->ObtainPathArray(plannerObj->serviceClient, plannerObj->path_srv, start_pos, goal_pos, finish_flag);
}

<commit_msg>re arrange the statements and comments<commit_after>#include "colibri_ca.h"
#include "colibri_local_nav.h"
#include "colibri_action.h"
#include "PID_controller.h"
#include "global_planner.h"
#include "task_mgr.h"

#include <boost/bind.hpp>

#include "geometry_msgs/PoseStamped.h"

void PlannerCallback(planner *plannerObj, float* start_pos, float* goal_pos, bool *finish_flag);

int main(int argc, char* argv[])
{

	ROS_INFO("Start to Go to Mult Goals in Rviz ... ");

	// ROS nav node initial
	ros::init(argc, argv, "Nav_Mult_RvizGoal_Node");
	ros::Rate loop_rate(10);		// Set control  freq at 10 hz
	unsigned int delay_cnt = 0;		// Init delay conter for scanObj

	// Auto nav obj initial
	scan_ca scan4caObj;
	local_nav local4navObj;
	nav_action actionObj;
	planner plannerObj;
	task_mgr taskObj;

	// Local key points relation param initial
	float tmp_delta_dis = 0.0;
	float tmp_robot2goal_yaw = 0.0;
	float tmp_laser2goal_yaw = 0.0;
	float dir_goal_in_laser = 0.0;
	float self_rotation_angle = 0.0;
	bool goal_inlaser_flag = true;

	unsigned int turn_adj_flag = 1;

	float tmp_action_cmd_t[2] = {0.0, 0.0};
	float* ptr_action_cmd_t = tmp_action_cmd_t;
	unsigned int micro_adj_flag = 0;

	unsigned int adj_flag = 0;

	bool obtain_flag = false;
	unsigned int search_start = 0;

	ros::NodeHandle nh_fp;
	ros::Timer planner_timer;
	bool finish_plan = false;

	bool tmp_timer_finish =false;
	bool *timer_finish = &tmp_timer_finish;

	static unsigned int index4gravaton = 0;

	float delta_robot2gravaton = 0.0;
	bool at_gravaton_flag = false;
	bool exist_gravaton_flag = false;
	bool replan_flag = false;

	float rt_r2g_dis = 100.0;

	// Waiting for set goal in Rviz
	while(taskObj.obtain_goal_flag == false)
	{
		ros::spinOnce();
		loop_rate.sleep();
	}
	local4navObj.goal_state[0] = taskObj.cur_goal[0];	// Extract the Rviz goal for nav
	local4navObj.goal_state[1] = taskObj.cur_goal[1];
	local4navObj.goal_state[2] = taskObj.cur_goal[2];

	while (!ros::service::waitForService(plannerObj.srv4make_plan, ros::Duration(0.2)))		// Waiting for path paln srv
	{
		ROS_INFO("Waiting for srv move_base/make_plan to become available");
	}
	ROS_INFO("Srv move_base/make_plan prepared OK...");

	// Inital path plan calling  and gravaton calc
	finish_plan = plannerObj.ExecMonoPlanAndGravaton(plannerObj,&local4navObj.cur_robot_state[0],&local4navObj.goal_state[0], search_start,index4gravaton);

	// Set path plan timer
	planner_timer = nh_fp.createTimer(ros::Duration(PLAN_INTERVAL), boost::bind(&PlannerCallback, &plannerObj, &local4navObj.amcl_cur_state[0],&taskObj.cur_goal[0], timer_finish));

	while (ros::ok())
	{

		if(delay_cnt < DELAY_CNT_MAX)
		{
			delay_cnt++;
			ros::spinOnce();
			loop_rate.sleep();
		}

		if(delay_cnt >= DELAY_CNT_MAX)
		{
			ROS_INFO("------ start ------");
			if(*timer_finish == true)
			{
				*timer_finish = false;
				index4gravaton = 0;
				replan_flag = true;
			}
			else
			{

				if((at_gravaton_flag == true && local4navObj.approaching_flag == false)||(replan_flag == true))
				{
					plannerObj.CalcPath2RobotDeltaDis(plannerObj.path_array, local4navObj.amcl_cur_state);
					index4gravaton = plannerObj.CalcGravatonFromPath(plannerObj.path_array, plannerObj.path2robot_array, index4gravaton, plannerObj.gravaton,exist_gravaton_flag);

					at_gravaton_flag = false;
					replan_flag = false;

				}

				at_gravaton_flag = actionObj.ReachGravatonOK(&local4navObj.amcl_cur_state[0],&plannerObj.gravaton.x, delta_robot2gravaton);

				if(local4navObj.approaching_flag == true)
				{
					plannerObj.gravaton.x = taskObj.cur_goal[0];
					plannerObj.gravaton.y = taskObj.cur_goal[1];
					plannerObj.gravaton.yaw = taskObj.cur_goal[2];
				}
			}

			local4navObj.CalcOffsetOfGoalAndRobot(local4navObj.amcl_cur_state, &plannerObj.gravaton.x, &tmp_delta_dis, &tmp_robot2goal_yaw, &tmp_laser2goal_yaw);

			goal_inlaser_flag = local4navObj.CalcGoalDirOfLaserViewNew(&tmp_laser2goal_yaw, &local4navObj.amcl_cur_state[2], &dir_goal_in_laser, &self_rotation_angle);

			scan4caObj.CalcPhiParam(local4navObj.cur_robot_vel[0], dir_goal_in_laser);

			scan4caObj.CalcKrfTheta(scan4caObj.kp_phi_vec, scan4caObj.phi_start_vec, scan4caObj.phi_end_vec);
			scan4caObj.CalcCorrectedKrf();
			scan4caObj.CalcPassFcnAndFwdBnd(scan4caObj.wander, &scan4caObj.max_passfcn_val, scan4caObj.passfcn_vec);
			scan4caObj.CalcPassFcnAndBwdBnd(scan4caObj.wander, &scan4caObj.max_passfcn_val, scan4caObj.passfcn_vec);

			scan4caObj.angle_adj = scan4caObj.CalcAdjDir(scan4caObj.passfcn_vec,scan4caObj.max_passfcn_val, &scan4caObj.maxfcn_fwdbnd,&scan4caObj.maxfcn_bwdbnd);

			scan4caObj.CalcCollisionInAPF();

			if(goal_inlaser_flag == true)
			{
				local4navObj.apf_ctrl_output[0] = (V_MAX - V_MIN) * (scan4caObj.max_passfcn_val / D_M) + V_MIN;
				local4navObj.apf_ctrl_output[1] = scan4caObj.angle_adj / 200.0;
			}
			else
			{
				local4navObj.apf_ctrl_output[0] = 0.0;
				local4navObj.apf_ctrl_output[1] = 0.0;
			}

			local4navObj.SatuateCmdVel(local4navObj.apf_ctrl_output,local4navObj.apf_ctrl_output+1);

			local4navObj.CalcEuclidDistance(local4navObj.amcl_cur_state, taskObj.cur_goal, rt_r2g_dis);

			local4navObj.approaching_flag = local4navObj.ReachApprochingAreaOK(&rt_r2g_dis);

			if(tmp_delta_dis >= GOAL_NGHBORHD)
			{
				ptr_action_cmd_t = actionObj.AdjustMovingDirAction(&local4navObj.amcl_cur_state[2], &dir_goal_in_laser, &tmp_robot2goal_yaw, &turn_adj_flag);
			}
			else
			{

			}

			if(turn_adj_flag == 1)
			{
				if(local4navObj.approaching_flag == false)
				{
					*ptr_action_cmd_t = local4navObj.apf_ctrl_output[0];
					*(ptr_action_cmd_t + 1) = local4navObj.apf_ctrl_output[1];
				}
				else
				{
					ptr_action_cmd_t = actionObj.ApproachingGoalAction(&local4navObj.amcl_cur_state[0],&local4navObj.goal_state[0],&dir_goal_in_laser,&micro_adj_flag);
				}

			}

			//local4navObj.position_OK_flag = local4navObj.ReachGoalPositionOK(&tmp_delta_dis);

			local4navObj.SatuateCmdVel(ptr_action_cmd_t,ptr_action_cmd_t + 1);

			local4navObj.apf_cmd_vel.linear.x = *ptr_action_cmd_t;
			local4navObj.apf_cmd_vel.angular.z = *(ptr_action_cmd_t + 1);

			if(local4navObj.position_OK_flag == true)
			{
				local4navObj.apf_cmd_vel.linear.x = 0.0;
				local4navObj.apf_cmd_vel.angular.z = 0.0;
			}

			local4navObj.pub_apf_twist.publish(local4navObj.apf_cmd_vel);

			scan4caObj.fwd_maxpass_num = 0;
			scan4caObj.bwd_maxpass_num = 0;

			cout<<"taskObj.cur_goal[0]: "<<taskObj.cur_goal[0]<<endl;
			cout<<"taskObj.cur_goal[1]: "<<taskObj.cur_goal[1]<<endl;
			cout<<"taskObj.cur_goal[2]: "<<taskObj.cur_goal[2]<<endl;

			ros::spinOnce();
			loop_rate.sleep();
			ROS_INFO("------- end --------");
		}
	}

	local4navObj.apf_cmd_vel.linear.x = 0.0;
	local4navObj.apf_cmd_vel.angular.z = 0.0;

	local4navObj.pub_apf_twist.publish(local4navObj.apf_cmd_vel);

	return 0;
}

void PlannerCallback(planner *plannerObj, float* start_pos, float* goal_pos, bool *finish_flag)
{
	plannerObj->ObtainPathArray(plannerObj->serviceClient, plannerObj->path_srv, start_pos, goal_pos, finish_flag);
}

<|endoftext|>


<commit_before>//
//  refract/Element.cc
//  librefract
//
//  Created by Jiri Kratochvil on 18/05/15.
//  Copyright (c) 2015 Apiary Inc. All rights reserved.
//
#include "Element.h"
#include <cassert>

#include <set>
#include <map>
#include <string>

#include "ComparableVisitor.h"
#include "TypeQueryVisitor.h"

#include <string.h>

namespace refract
{

    namespace {

        const constexpr std::array<const char*, 13> reservedKeywords = {

            "null",
            "boolean",
            "number",
            "string",

            "member",

            "array",
            "enum",
            "object",

            "ref",
            "select",
            "option",
            "extend",

            "generic"
        };

        const constexpr std::array<const char*, 3> noMetaKeywords = {
            "id",
            "prefix",
            "namespace"
        };

        const constexpr std::array<const char*, 0> emptyArray = {
        };

        template <typename Container>
        struct inKeys {
            const Container& keywords;
            inKeys(const Container& keywords) : keywords(keywords) {}

            bool operator()(const std::string& searched) {
                return std::any_of(keywords.begin(), keywords.end(),
                                   [&searched](const char* key) {
                                       return !strcmp(key, searched.c_str());
                                   });
            }
        };

        template <typename Container>
        inKeys<Container> InKeysChecker(const Container& keywords) {
            return inKeys<Container>(keywords);
        }

    }

    bool isReserved(const std::string& element) {
        return InKeysChecker(reservedKeywords)(element);
    }

    IElement::MemberElementCollection::const_iterator IElement::MemberElementCollection::find(
        const std::string& name) const
    {
        ComparableVisitor v(name);
        Visitor visitor(v);

        return std::find_if(elements.begin(), elements.end(), [&visitor, &v](const MemberElement* e) {
            e->value.first->content(visitor);
            return v.get();
        });
    }

    IElement::MemberElementCollection::iterator IElement::MemberElementCollection::find(const std::string& name)
    {
        ComparableVisitor v(name);
        Visitor visitor(v);

        return std::find_if(elements.begin(), elements.end(), [&visitor, &v](const MemberElement* e) {
            e->value.first->content(visitor);
            return v.get();
        });
    }

    IElement::MemberElementCollection::~MemberElementCollection()
    {
        for (MemberElement* e : elements)
            delete e;
    }

    StringElement* IElement::Create(const char* value)
    {
        return Create(std::string(value));
    };

    MemberElement& IElement::MemberElementCollection::operator[](const std::string& name)
    {
        auto it = find(name);
        if (it != elements.end()) {
            return *(*it);
        }

        elements.emplace_back(new MemberElement(new StringElement(name), nullptr));

        return *elements.back();
    }

    void IElement::MemberElementCollection::clone(const IElement::MemberElementCollection& other)
    {
        for (const auto& el : other.elements) {
            elements.emplace_back(static_cast<MemberElement*>(el->clone()));
        }
    }

    void IElement::MemberElementCollection::erase(const std::string& key)
    {
        auto it = find(key);

        if (it != elements.end()) {
            delete *it;
            elements.erase(it);
        }
    }

    namespace
    {

        bool TypeChecker(const ExtendElement::ValueType& values)
        {
            if (values.empty()) {
                return true;
            }

            TypeQueryVisitor visitor;
            Visit(visitor, *values.front());

            const TypeQueryVisitor::ElementType base = visitor.get();

            return std::all_of(values.begin(), values.end(), [&visitor, base](const IElement* e) {
                Visit(visitor, *e);
                return base == visitor.get();
            });
        }
    }

    void ExtendElement::set(const ExtendElement::ValueType& val)
    {
        if (!TypeChecker(val)) {
            throw LogicError("ExtendElement must be composed from Elements of same type");
        }

        if (val.empty()) {
            return;
        }

        hasContent = true;
        value = val;
    }

    void ExtendElement::push_back(IElement* e)
    {

        if (!e) {
            return;
        }

        if (!value.empty()) {
            TypeQueryVisitor baseType;
            Visit(baseType, *value.front());

            TypeQueryVisitor type;
            Visit(type, *e);

            if (baseType.get() != type.get()) {
                throw LogicError("ExtendElement must be composed from Elements of same type");
            }
        }

        hasContent = true;
        value.push_back(e);
    }

    namespace
    {

        class ElementMerger
        {

            IElement* result;
            TypeQueryVisitor::ElementType base;

            /**
             * Merge strategy for Primitive types - just replace by latest value
             */
            template <typename T, typename V = typename T::ValueType>
            struct ValueMerge {
                V& value;
                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    value = merge.value;
                }
            };

            template <typename T>
            struct ValueMerge<T, IElement*> {
                IElement*& value;
                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    if (!value && merge.value) {
                        value = merge.value->clone();
                    }
                }
            };

            /**
             * Merge stategy for objects/array
             * - if member
             *   - without existing key -> append
             *   - with existing key - replace old value
             * - if not member
             *   - if empty value -> ignore (type holder for array)
             *   - else append
             */
            template <typename T>
            struct ValueMerge<T, RefractElements> {
                typename T::ValueType& value;

                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    typedef std::map<std::string, MemberElement*> MapKeyToMember;
                    typedef std::map<std::string, RefElement*> MapNameToRef;

                    MapKeyToMember keysBase;
                    MapNameToRef refBase;

                    for (auto& element : value) {
                        if (MemberElement* member = TypeQueryVisitor::as<MemberElement>(element)) {

                            if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                                keysBase[key->value] = member;
                            }
                        } else if (RefElement* ref = TypeQueryVisitor::as<RefElement>(element)) {
                            refBase[ref->value] = ref;
                        }
                    }

                    for (auto const& element : merge.value) {
                        if (MemberElement* member = TypeQueryVisitor::as<MemberElement>(element)) {
                            if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                                MapKeyToMember::iterator iKey = keysBase.find(key->value);

                                if (iKey != keysBase.end()) { // key is already presented, replace value
                                    delete iKey->second->value.second;
                                    iKey->second->value.second = member->value.second->clone();

                                    CollectionMerge()(iKey->second->meta, member->meta, InKeysChecker(noMetaKeywords));
                                    CollectionMerge()(iKey->second->attributes, member->attributes, InKeysChecker(emptyArray));
                                }
                                else { // unknown key, append value
                                    MemberElement* clone = static_cast<MemberElement*>(member->clone());
                                    value.push_back(clone);
                                    keysBase[key->value] = clone;
                                }
                            }
                        } else if (RefElement* ref = TypeQueryVisitor::as<RefElement>(element)) {
                            if (refBase.find(ref->value) == refBase.end()) {
                                RefElement* clone = static_cast<RefElement*>(member->clone());
                                value.push_back(clone);
                                refBase[ref->value] = clone;
                            }
                        } else if (!(element)->empty()) { // merge member is not MemberElement, append value
                            value.push_back(element->clone());
                        }
                    }
                }
            };

            class CollectionMerge {

            public:
                CollectionMerge() = default;

                void operator()(IElement::MemberElementCollection& info, const IElement::MemberElementCollection& append, std::function<bool (const std::string&)> noMerge) {
                    IElement::MemberElementCollection toAppend;

                    for (const auto& member : append) {

                        assert(member);

                        if (!member) {
                            continue;
                        }

                        if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                            if (noMerge(key->value)) {
                                continue;
                            }

                            IElement::MemberElementCollection::iterator item = info.find(key->value);
                            if (item != info.end()) {
                                // this key alrady exist, replace value
                                delete (*item)->value.second;
                                (*item)->value.second = member->value.second->clone();
                                continue;
                            }
                        }

                        toAppend.push_back(static_cast<MemberElement*>(member->clone()));
                    }

                    for (const auto& member : toAppend) {
                        info.push_back(member);
                    }

                    toAppend.clear();
                }
            };

            /**
             * precondition - target && append element MUST BE of same type
             * we use static_cast<> without checking type this is responsibility of caller
             */
            template <typename T>
            static void doMerge(IElement* target, const IElement* append)
            {
                typedef T ElementType;

                CollectionMerge()(target->meta, append->meta, InKeysChecker(noMetaKeywords));
                CollectionMerge()(target->attributes, append->attributes, InKeysChecker(emptyArray));

                ValueMerge<T>(static_cast<ElementType&>(*target))(static_cast<const ElementType&>(*append));
            }

        public:
            ElementMerger() : result(NULL), base(TypeQueryVisitor::Unknown)
            {
            }

            void operator()(const IElement* e)
            {
                if (!e) {
                    return;
                }

                if (!result) {
                    result = e->clone();

                    TypeQueryVisitor type;
                    Visit(type, *result);
                    base = type.get();
                    return;
                }

                TypeQueryVisitor type;
                VisitBy(*e, type);

                if (type.get() != base) {
                    throw refract::LogicError("Can not merge different types of elements");
                }

                switch (base) {
                    case TypeQueryVisitor::String:
                        doMerge<StringElement>(result, e);
                        return;

                    case TypeQueryVisitor::Number:
                        doMerge<NumberElement>(result, e);
                        return;

                    case TypeQueryVisitor::Boolean:
                        doMerge<BooleanElement>(result, e);
                        return;

                    case TypeQueryVisitor::Array:
                        doMerge<ArrayElement>(result, e);
                        return;

                    case TypeQueryVisitor::Object:
                        doMerge<ObjectElement>(result, e);
                        return;

                    case TypeQueryVisitor::Enum:
                        doMerge<EnumElement>(result, e);
                        return;

                    case TypeQueryVisitor::Ref:
                        doMerge<RefElement>(result, e);
                        return;

                    case TypeQueryVisitor::Member:
                    case TypeQueryVisitor::Extend:
                    case TypeQueryVisitor::Null:
                        throw LogicError("Unappropriate kind of element to merging");
                    default:
                        throw LogicError("Element has no implemented merging");
                }
            }

            operator IElement*() const
            {
                return result;
            }
        };
    }

    IElement* ExtendElement::merge() const
    {
        return std::for_each(value.begin(), value.end(), ElementMerger());
    }

}; // namespace refract
<commit_msg>No init empty array<commit_after>//
//  refract/Element.cc
//  librefract
//
//  Created by Jiri Kratochvil on 18/05/15.
//  Copyright (c) 2015 Apiary Inc. All rights reserved.
//
#include "Element.h"
#include <cassert>

#include <set>
#include <map>
#include <string>

#include "ComparableVisitor.h"
#include "TypeQueryVisitor.h"

#include <string.h>

namespace refract
{

    namespace {

        const constexpr std::array<const char*, 13> reservedKeywords = {

            "null",
            "boolean",
            "number",
            "string",

            "member",

            "array",
            "enum",
            "object",

            "ref",
            "select",
            "option",
            "extend",

            "generic"
        };

        const constexpr std::array<const char*, 3> noMetaKeywords = {
            "id",
            "prefix",
            "namespace"
        };

        const constexpr std::array<const char*, 0> emptyArray;

        template <typename Container>
        struct inKeys {
            const Container& keywords;
            inKeys(const Container& keywords) : keywords(keywords) {}

            bool operator()(const std::string& searched) {
                return std::any_of(keywords.begin(), keywords.end(),
                                   [&searched](const char* key) {
                                       return !strcmp(key, searched.c_str());
                                   });
            }
        };

        template <typename Container>
        inKeys<Container> InKeysChecker(const Container& keywords) {
            return inKeys<Container>(keywords);
        }

    }

    bool isReserved(const std::string& element) {
        return InKeysChecker(reservedKeywords)(element);
    }

    IElement::MemberElementCollection::const_iterator IElement::MemberElementCollection::find(
        const std::string& name) const
    {
        ComparableVisitor v(name);
        Visitor visitor(v);

        return std::find_if(elements.begin(), elements.end(), [&visitor, &v](const MemberElement* e) {
            e->value.first->content(visitor);
            return v.get();
        });
    }

    IElement::MemberElementCollection::iterator IElement::MemberElementCollection::find(const std::string& name)
    {
        ComparableVisitor v(name);
        Visitor visitor(v);

        return std::find_if(elements.begin(), elements.end(), [&visitor, &v](const MemberElement* e) {
            e->value.first->content(visitor);
            return v.get();
        });
    }

    IElement::MemberElementCollection::~MemberElementCollection()
    {
        for (MemberElement* e : elements)
            delete e;
    }

    StringElement* IElement::Create(const char* value)
    {
        return Create(std::string(value));
    };

    MemberElement& IElement::MemberElementCollection::operator[](const std::string& name)
    {
        auto it = find(name);
        if (it != elements.end()) {
            return *(*it);
        }

        elements.emplace_back(new MemberElement(new StringElement(name), nullptr));

        return *elements.back();
    }

    void IElement::MemberElementCollection::clone(const IElement::MemberElementCollection& other)
    {
        for (const auto& el : other.elements) {
            elements.emplace_back(static_cast<MemberElement*>(el->clone()));
        }
    }

    void IElement::MemberElementCollection::erase(const std::string& key)
    {
        auto it = find(key);

        if (it != elements.end()) {
            delete *it;
            elements.erase(it);
        }
    }

    namespace
    {

        bool TypeChecker(const ExtendElement::ValueType& values)
        {
            if (values.empty()) {
                return true;
            }

            TypeQueryVisitor visitor;
            Visit(visitor, *values.front());

            const TypeQueryVisitor::ElementType base = visitor.get();

            return std::all_of(values.begin(), values.end(), [&visitor, base](const IElement* e) {
                Visit(visitor, *e);
                return base == visitor.get();
            });
        }
    }

    void ExtendElement::set(const ExtendElement::ValueType& val)
    {
        if (!TypeChecker(val)) {
            throw LogicError("ExtendElement must be composed from Elements of same type");
        }

        if (val.empty()) {
            return;
        }

        hasContent = true;
        value = val;
    }

    void ExtendElement::push_back(IElement* e)
    {

        if (!e) {
            return;
        }

        if (!value.empty()) {
            TypeQueryVisitor baseType;
            Visit(baseType, *value.front());

            TypeQueryVisitor type;
            Visit(type, *e);

            if (baseType.get() != type.get()) {
                throw LogicError("ExtendElement must be composed from Elements of same type");
            }
        }

        hasContent = true;
        value.push_back(e);
    }

    namespace
    {

        class ElementMerger
        {

            IElement* result;
            TypeQueryVisitor::ElementType base;

            /**
             * Merge strategy for Primitive types - just replace by latest value
             */
            template <typename T, typename V = typename T::ValueType>
            struct ValueMerge {
                V& value;
                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    value = merge.value;
                }
            };

            template <typename T>
            struct ValueMerge<T, IElement*> {
                IElement*& value;
                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    if (!value && merge.value) {
                        value = merge.value->clone();
                    }
                }
            };

            /**
             * Merge stategy for objects/array
             * - if member
             *   - without existing key -> append
             *   - with existing key - replace old value
             * - if not member
             *   - if empty value -> ignore (type holder for array)
             *   - else append
             */
            template <typename T>
            struct ValueMerge<T, RefractElements> {
                typename T::ValueType& value;

                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    typedef std::map<std::string, MemberElement*> MapKeyToMember;
                    typedef std::map<std::string, RefElement*> MapNameToRef;

                    MapKeyToMember keysBase;
                    MapNameToRef refBase;

                    for (auto& element : value) {
                        if (MemberElement* member = TypeQueryVisitor::as<MemberElement>(element)) {

                            if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                                keysBase[key->value] = member;
                            }
                        } else if (RefElement* ref = TypeQueryVisitor::as<RefElement>(element)) {
                            refBase[ref->value] = ref;
                        }
                    }

                    for (auto const& element : merge.value) {
                        if (MemberElement* member = TypeQueryVisitor::as<MemberElement>(element)) {
                            if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                                MapKeyToMember::iterator iKey = keysBase.find(key->value);

                                if (iKey != keysBase.end()) { // key is already presented, replace value
                                    delete iKey->second->value.second;
                                    iKey->second->value.second = member->value.second->clone();

                                    CollectionMerge()(iKey->second->meta, member->meta, InKeysChecker(noMetaKeywords));
                                    CollectionMerge()(iKey->second->attributes, member->attributes, InKeysChecker(emptyArray));
                                }
                                else { // unknown key, append value
                                    MemberElement* clone = static_cast<MemberElement*>(member->clone());
                                    value.push_back(clone);
                                    keysBase[key->value] = clone;
                                }
                            }
                        } else if (RefElement* ref = TypeQueryVisitor::as<RefElement>(element)) {
                            if (refBase.find(ref->value) == refBase.end()) {
                                RefElement* clone = static_cast<RefElement*>(member->clone());
                                value.push_back(clone);
                                refBase[ref->value] = clone;
                            }
                        } else if (!(element)->empty()) { // merge member is not MemberElement, append value
                            value.push_back(element->clone());
                        }
                    }
                }
            };

            class CollectionMerge {

            public:
                CollectionMerge() = default;

                void operator()(IElement::MemberElementCollection& info, const IElement::MemberElementCollection& append, std::function<bool (const std::string&)> noMerge) {
                    IElement::MemberElementCollection toAppend;

                    for (const auto& member : append) {

                        assert(member);

                        if (!member) {
                            continue;
                        }

                        if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                            if (noMerge(key->value)) {
                                continue;
                            }

                            IElement::MemberElementCollection::iterator item = info.find(key->value);
                            if (item != info.end()) {
                                // this key alrady exist, replace value
                                delete (*item)->value.second;
                                (*item)->value.second = member->value.second->clone();
                                continue;
                            }
                        }

                        toAppend.push_back(static_cast<MemberElement*>(member->clone()));
                    }

                    for (const auto& member : toAppend) {
                        info.push_back(member);
                    }

                    toAppend.clear();
                }
            };

            /**
             * precondition - target && append element MUST BE of same type
             * we use static_cast<> without checking type this is responsibility of caller
             */
            template <typename T>
            static void doMerge(IElement* target, const IElement* append)
            {
                typedef T ElementType;

                CollectionMerge()(target->meta, append->meta, InKeysChecker(noMetaKeywords));
                CollectionMerge()(target->attributes, append->attributes, InKeysChecker(emptyArray));

                ValueMerge<T>(static_cast<ElementType&>(*target))(static_cast<const ElementType&>(*append));
            }

        public:
            ElementMerger() : result(NULL), base(TypeQueryVisitor::Unknown)
            {
            }

            void operator()(const IElement* e)
            {
                if (!e) {
                    return;
                }

                if (!result) {
                    result = e->clone();

                    TypeQueryVisitor type;
                    Visit(type, *result);
                    base = type.get();
                    return;
                }

                TypeQueryVisitor type;
                VisitBy(*e, type);

                if (type.get() != base) {
                    throw refract::LogicError("Can not merge different types of elements");
                }

                switch (base) {
                    case TypeQueryVisitor::String:
                        doMerge<StringElement>(result, e);
                        return;

                    case TypeQueryVisitor::Number:
                        doMerge<NumberElement>(result, e);
                        return;

                    case TypeQueryVisitor::Boolean:
                        doMerge<BooleanElement>(result, e);
                        return;

                    case TypeQueryVisitor::Array:
                        doMerge<ArrayElement>(result, e);
                        return;

                    case TypeQueryVisitor::Object:
                        doMerge<ObjectElement>(result, e);
                        return;

                    case TypeQueryVisitor::Enum:
                        doMerge<EnumElement>(result, e);
                        return;

                    case TypeQueryVisitor::Ref:
                        doMerge<RefElement>(result, e);
                        return;

                    case TypeQueryVisitor::Member:
                    case TypeQueryVisitor::Extend:
                    case TypeQueryVisitor::Null:
                        throw LogicError("Unappropriate kind of element to merging");
                    default:
                        throw LogicError("Element has no implemented merging");
                }
            }

            operator IElement*() const
            {
                return result;
            }
        };
    }

    IElement* ExtendElement::merge() const
    {
        return std::for_each(value.begin(), value.end(), ElementMerger());
    }

}; // namespace refract
<|endoftext|>


<commit_before>/*! \file
 */

#include "Grid.h"

Grid::Grid() {
}

// deconstructor
Grid::~Grid() {
}

// initialization
int Grid::reinit() {
  for (int id=0; id<365; id++) {
    //the following are the original algorithm, and
    //  modified as below by Yi (2013 Feb):
    //  double ampl;
    //  ampl = exp(7.42 +0.045 *gd.lat)/3600.;
    //  gd.alldaylengths[id] = ampl * (sin ((id -79) *0.01721)) +12.0;
    double daylength = 0.0;
    //http://www.jgiesen.de/astro/solarday.htm
    //http://www.gandraxa.com/length_of_day.xml
    //make sure all arguments in sin, cos and tan are
    //  in unit of arc (not degree)
    double pi =3.14159;
    double m = 1- tan(gd.lat*pi/180.0)* tan(23.45*cos(id*pi/182.625)*pi/180.0);
    m = fmax(m, 0.);
    m = fmin(m, 2.);
    double b = acos(1-m)/pi;
    daylength = b*24;
    gd.alldaylengths[id] = daylength;
  }

  //check for the validity of grid level data
  if(gd.fri<0|| gd.fri>2000) {
    gd.fri =2000;
  }

  // 06-05-14
  // If grid fire related parameters are not
  // set here, then they are read and set from your
  // input netCDF files (grid.nc and firestatistics.nc?)
  //gd.fri = 60;
  //gd.pfseason[1] = 0.80;
  //gd.pfsize[1] = 0.80;

  if(gd.topsoil <0 || gd.botsoil <0) {
    return -2;
  }

  return 0;
}

//'ed' for the whole grid
void Grid::setEnvData(EnvData* edp) {
  grded = edp;
}

//'bd' for the whole grid
void Grid::setBgcData(BgcData* bdp) {
  grdbd = bdp;
}

//inputs
void Grid::setRegionData(RegionData* rdp) {
  rd = rdp;
}

<commit_msg>Update Grid.cpp<commit_after>/*! \file
 */

#include "Grid.h"

Grid::Grid() {
}

// deconstructor
Grid::~Grid() {
}

// initialization
int Grid::reinit() {
  for (int id=0; id<365; id++) {
    //the following are the original algorithm, and
    //  modified as below by Yi (2013 Feb):
    //  double ampl;
    //  ampl = exp(7.42 +0.045 *gd.lat)/3600.;
    //  gd.alldaylengths[id] = ampl * (sin ((id -79) *0.01721)) +12.0;
    double daylength = 0.0;
    //http://www.jgiesen.de/astro/solarday.htm
    //http://www.gandraxa.com/length_of_day.xml
    //make sure all arguments in sin, cos and tan are
    //  in unit of arc (not degree)
    double pi =3.14159;
    double m = 1- tan(gd.lat*pi/180.0)* tan(23.45*cos(id*pi/182.625)*pi/180.0);
    m = fmax(m, 0.);
    m = fmin(m, 2.);
    double b = acos(1-m)/pi;
    daylength = b*24;
    gd.alldaylengths[id] = daylength;
  }

  //check for the validity of grid level data
  if(gd.fri<0|| gd.fri>2000) {
    gd.fri =2000;
  }

  //testing or manual firestatistics setting
  // 06-05-14
  // If grid fire related parameters are
  // set here, then they ARE NOT set from your
  // input file firestatistics.nc in datagrd
  //gd.fri = 60;
  //gd.pfseason[1] = 0.80;
  //gd.pfsize[1] = 0.80;

  if(gd.topsoil <0 || gd.botsoil <0) {
    return -2;
  }

  return 0;
}

//'ed' for the whole grid
void Grid::setEnvData(EnvData* edp) {
  grded = edp;
}

//'bd' for the whole grid
void Grid::setBgcData(BgcData* bdp) {
  grdbd = bdp;
}

//inputs
void Grid::setRegionData(RegionData* rdp) {
  rd = rdp;
}

<|endoftext|>


<commit_before>
#include <s2sinputstream.h>
#include <virtualhost.h>
#include <nanosoft/asyncdns.h>
#include <iostream>

using namespace std;

/**
* Конструктор потока
*/
S2SInputStream::S2SInputStream(XMPPServer *srv, int sock): XMPPStream(srv, sock)
{
}

/**
* Деструктор потока
*/
S2SInputStream::~S2SInputStream()
{
}

/**
* Событие: начало потока
*/
void S2SInputStream::onStartStream(const std::string &name, const attributes_t &attributes)
{
	fprintf(stderr, "#%d new s2s stream\n", getWorkerId());
	initXML();
	startElement("stream:stream");
	setAttribute("xmlns:stream", "http://etherx.jabber.org/streams");
	setAttribute("xmlns", "jabber:server");
	setAttribute("xmlns:db", "jabber:server:dialback");
	setAttribute("id", id = "123456"); // Требования к id — непредсказуемость и уникальность
	setAttribute("xml:lang", "en");
	flush();
}

/**
* Событие: конец потока
*/
void S2SInputStream::onEndStream()
{
	cerr << "s2s input stream closed" << endl;
	endElement("stream:stream");
}

/**
* Обработчик станзы
*/
void S2SInputStream::onStanza(Stanza stanza)
{
	fprintf(stderr, "#%d s2s-input stanza: %s\n", getWorkerId(), stanza->name().c_str());
	if (stanza->name() == "verify" ) onDBVerifyStanza(stanza);
	else if (stanza->name() == "result") onDBResultStanza(stanza);
	else
	{
		fprintf(stderr, "#%d unexpected s2s-input stanza: %s\n", getWorkerId(), stanza->name().c_str());
		Stanza error = Stanza::streamError("not-authoized");
		sendStanza(error);
		delete error;
		terminate();
	}
}

/**
* Обработка <db:verify>
*/
void S2SInputStream::onDBVerifyStanza(Stanza stanza)
{
}

/**
* Резолвер s2s хоста, запись A (IPv4)
*/
static void on_s2s_a4(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
{
  printf("on_s2s_a4\n");
  for(int i = 0; i < result->dnsa4_nrr; i++)
  {
    char buf[40];
    printf("  addr: %s\n", dns_ntop(AF_INET, &result->dnsa4_addr[i], buf, sizeof(buf)));
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись SRV (_jabber._tcp)
*/
static void on_s2s_srv_jabber(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data)
{
  printf("on_s2s_srv_jabber\n");
  for(int i = 0; i < result->dnssrv_nrr; i++)
  {
    char buf[40];
    printf("  SRV priority: %d, weight: %d, port: %d, name: %s\n",
      result->dnssrv_srv[i].priority,
      result->dnssrv_srv[i].weight,
      result->dnssrv_srv[i].port,
      result->dnssrv_srv[i].name);
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись SRV (_xmpp-server._tcp)
*/
static void on_srv_xmpp_server(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data)
{
  printf("on_srv_xmpp_server\n");
  for(int i = 0; i < result->dnssrv_nrr; i++)
  {
    char buf[40];
    printf("  SRV priority: %d, weight: %d, port: %d, name: %s\n",
      result->dnssrv_srv[i].priority,
      result->dnssrv_srv[i].weight,
      result->dnssrv_srv[i].port,
      result->dnssrv_srv[i].name);
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись RBL
*/
static void on_s2s_rbl(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
{
  printf("on_s2s_rbl\n");
  if ( result ) {
  for(int i = 0; i < result->dnsa4_nrr; i++)
  {
    char buf[40];
    printf("  addr: %s\n", dns_ntop(AF_INET, &result->dnsa4_addr[i], buf, sizeof(buf)));
  }
  }
  printf("\n");
}

/**
* Обработка <db:result>
*/
void S2SInputStream::onDBResultStanza(Stanza stanza)
{
	string to = stanza->getAttribute("to");
	string from = stanza->getAttribute("from");
	cerr << "[s2s-input] db:result to: " << to << ", from: " << from << endl;

	// Шаг 1. проверка: "to" должен быть нашим виртуальным хостом
	XMPPDomain *host = server->getHostByName(to);
	VirtualHost *vhost = dynamic_cast<VirtualHost *>(host);
	if ( ! vhost )
	{
		Stanza stanza = Stanza::streamError("host-unknown");
		sendStanza(stanza);
		delete stanza;
		terminate();
		return;
	}

	// Шаг 2. проверка "from"
	//
	// RFC 3920 не запрещает делать повторные коннекты (8.3.4).
	//
	// До завершения авторизации нужно поддерживать старое соединение,
	// пока не авторизуется новое. Но можно блокировать повторные
	// коннекты с ошибкой <not-authorized />, что мы и делаем.
	//
	// NOTE: В любом случае, логично блокировать попытки представиться
	// нашим хостом - мы сами к себе никогда не коннектимся.
	// Так что, если будете открывать повторные коннекты, то забудьте
	// блокировать попытки коннекта к самим себе.
	if ( server->getHostByName(from) )
	{
		Stanza stanza = Stanza::streamError("not-authorized");
		sendStanza(stanza);
		delete stanza;
		terminate();
		return;
	}

	// Шаг 3. резолвим DNS записи сервера
	// NOTE для оптимизации отправляем все DNS (асинхронные) запросы сразу
	server->adns->a4(from.c_str(), on_s2s_a4, this);
	server->adns->srv(from.c_str(), "jabber", "tcp", on_s2s_srv_jabber, this);
	server->adns->srv(from.c_str(), "xmpp-server", "tcp", on_srv_xmpp_server, this);
	// TODO извлекать список DNSBL из конфига
	server->adns->a4((from + ".dnsbl.jabber.ru").c_str(), on_s2s_rbl, this);
}

/**
* Событие закрытие соединения
*
* Вызывается если peer закрыл соединение
*/
void S2SInputStream::onShutdown()
{
	cerr << "[s2s input]: peer shutdown connection" << endl;
	if ( state != terminating ) {
		AsyncXMLStream::onShutdown();
		XMLWriter::flush();
	}
	server->daemon->removeObject(this);
	shutdown(READ | WRITE);
	delete this;
	cerr << "[s2s input]: shutdown leave" << endl;
}

void S2SInputStream::terminate()
{
	cerr << "[s2s input]: terminating connection..." << endl;

	switch ( state )
	{
	case terminating:
		return;
	case authorized:
		break;
	}

	mutex.lock();
		if ( state != terminating ) {
			state = terminating;
			endElement("stream:stream");
			flush();
			shutdown(WRITE);
		}
	mutex.unlock();
}

/**
* Сигнал завершения работы
*
* Объект должен закрыть файловый дескриптор
* и освободить все занимаемые ресурсы
*/
void S2SInputStream::onTerminate()
{
	terminate();
}
<commit_msg>s2s: fix проверка на остуствие DNS записи<commit_after>
#include <s2sinputstream.h>
#include <virtualhost.h>
#include <nanosoft/asyncdns.h>
#include <iostream>

using namespace std;

/**
* Конструктор потока
*/
S2SInputStream::S2SInputStream(XMPPServer *srv, int sock): XMPPStream(srv, sock)
{
}

/**
* Деструктор потока
*/
S2SInputStream::~S2SInputStream()
{
}

/**
* Событие: начало потока
*/
void S2SInputStream::onStartStream(const std::string &name, const attributes_t &attributes)
{
	fprintf(stderr, "#%d new s2s stream\n", getWorkerId());
	initXML();
	startElement("stream:stream");
	setAttribute("xmlns:stream", "http://etherx.jabber.org/streams");
	setAttribute("xmlns", "jabber:server");
	setAttribute("xmlns:db", "jabber:server:dialback");
	setAttribute("id", id = "123456"); // Требования к id — непредсказуемость и уникальность
	setAttribute("xml:lang", "en");
	flush();
}

/**
* Событие: конец потока
*/
void S2SInputStream::onEndStream()
{
	cerr << "s2s input stream closed" << endl;
	endElement("stream:stream");
}

/**
* Обработчик станзы
*/
void S2SInputStream::onStanza(Stanza stanza)
{
	fprintf(stderr, "#%d s2s-input stanza: %s\n", getWorkerId(), stanza->name().c_str());
	if (stanza->name() == "verify" ) onDBVerifyStanza(stanza);
	else if (stanza->name() == "result") onDBResultStanza(stanza);
	else
	{
		fprintf(stderr, "#%d unexpected s2s-input stanza: %s\n", getWorkerId(), stanza->name().c_str());
		Stanza error = Stanza::streamError("not-authoized");
		sendStanza(error);
		delete error;
		terminate();
	}
}

/**
* Обработка <db:verify>
*/
void S2SInputStream::onDBVerifyStanza(Stanza stanza)
{
}

/**
* Резолвер s2s хоста, запись A (IPv4)
*/
static void on_s2s_a4(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
{
  printf("on_s2s_a4\n");
  if ( result )
  for(int i = 0; i < result->dnsa4_nrr; i++)
  {
    char buf[40];
    printf("  addr: %s\n", dns_ntop(AF_INET, &result->dnsa4_addr[i], buf, sizeof(buf)));
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись SRV (_jabber._tcp)
*/
static void on_s2s_srv_jabber(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data)
{
  printf("on_s2s_srv_jabber\n");
  if ( result )
  for(int i = 0; i < result->dnssrv_nrr; i++)
  {
    char buf[40];
    printf("  SRV priority: %d, weight: %d, port: %d, name: %s\n",
      result->dnssrv_srv[i].priority,
      result->dnssrv_srv[i].weight,
      result->dnssrv_srv[i].port,
      result->dnssrv_srv[i].name);
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись SRV (_xmpp-server._tcp)
*/
static void on_srv_xmpp_server(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data)
{
  printf("on_srv_xmpp_server\n");
  if ( result )
  for(int i = 0; i < result->dnssrv_nrr; i++)
  {
    char buf[40];
    printf("  SRV priority: %d, weight: %d, port: %d, name: %s\n",
      result->dnssrv_srv[i].priority,
      result->dnssrv_srv[i].weight,
      result->dnssrv_srv[i].port,
      result->dnssrv_srv[i].name);
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись RBL
*/
static void on_s2s_rbl(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
{
  printf("on_s2s_rbl\n");
  if ( result ) {
  for(int i = 0; i < result->dnsa4_nrr; i++)
  {
    char buf[40];
    printf("  addr: %s\n", dns_ntop(AF_INET, &result->dnsa4_addr[i], buf, sizeof(buf)));
  }
  }
  printf("\n");
}

/**
* Обработка <db:result>
*/
void S2SInputStream::onDBResultStanza(Stanza stanza)
{
	string to = stanza->getAttribute("to");
	string from = stanza->getAttribute("from");
	cerr << "[s2s-input] db:result to: " << to << ", from: " << from << endl;

	// Шаг 1. проверка: "to" должен быть нашим виртуальным хостом
	XMPPDomain *host = server->getHostByName(to);
	VirtualHost *vhost = dynamic_cast<VirtualHost *>(host);
	if ( ! vhost )
	{
		Stanza stanza = Stanza::streamError("host-unknown");
		sendStanza(stanza);
		delete stanza;
		terminate();
		return;
	}

	// Шаг 2. проверка "from"
	//
	// RFC 3920 не запрещает делать повторные коннекты (8.3.4).
	//
	// До завершения авторизации нужно поддерживать старое соединение,
	// пока не авторизуется новое. Но можно блокировать повторные
	// коннекты с ошибкой <not-authorized />, что мы и делаем.
	//
	// NOTE: В любом случае, логично блокировать попытки представиться
	// нашим хостом - мы сами к себе никогда не коннектимся.
	// Так что, если будете открывать повторные коннекты, то забудьте
	// блокировать попытки коннекта к самим себе.
	if ( server->getHostByName(from) )
	{
		Stanza stanza = Stanza::streamError("not-authorized");
		sendStanza(stanza);
		delete stanza;
		terminate();
		return;
	}

	// Шаг 3. резолвим DNS записи сервера
	// NOTE для оптимизации отправляем все DNS (асинхронные) запросы сразу
	server->adns->a4(from.c_str(), on_s2s_a4, this);
	server->adns->srv(from.c_str(), "jabber", "tcp", on_s2s_srv_jabber, this);
	server->adns->srv(from.c_str(), "xmpp-server", "tcp", on_srv_xmpp_server, this);
	// TODO извлекать список DNSBL из конфига
	server->adns->a4((from + ".dnsbl.jabber.ru").c_str(), on_s2s_rbl, this);
}

/**
* Событие закрытие соединения
*
* Вызывается если peer закрыл соединение
*/
void S2SInputStream::onShutdown()
{
	cerr << "[s2s input]: peer shutdown connection" << endl;
	if ( state != terminating ) {
		AsyncXMLStream::onShutdown();
		XMLWriter::flush();
	}
	server->daemon->removeObject(this);
	shutdown(READ | WRITE);
	delete this;
	cerr << "[s2s input]: shutdown leave" << endl;
}

void S2SInputStream::terminate()
{
	cerr << "[s2s input]: terminating connection..." << endl;

	switch ( state )
	{
	case terminating:
		return;
	case authorized:
		break;
	}

	mutex.lock();
		if ( state != terminating ) {
			state = terminating;
			endElement("stream:stream");
			flush();
			shutdown(WRITE);
		}
	mutex.unlock();
}

/**
* Сигнал завершения работы
*
* Объект должен закрыть файловый дескриптор
* и освободить все занимаемые ресурсы
*/
void S2SInputStream::onTerminate()
{
	terminate();
}
<|endoftext|>


<commit_before>#include "dsa_common.h"
#include "string.h"

#include <boost/filesystem.hpp>
#include "openssl/rand.h"
#include "module/default/simple_storage.h"
using namespace std;
namespace fs = boost::filesystem;

namespace dsa {

string_ string_from_file(string_ file_path) {
  SimpleStorage simple_storage;
  std::unique_ptr<StorageBucket> storage_bucket;
  string_ data;
  storage_bucket = simple_storage.get_bucket(file_path);
  auto read_callback = [&](std::string storage_key, std::vector<uint8_t> vec) {
    string_ content(vec.begin(), vec.end());
    data = content;
  };
  storage_bucket->read(file_path, read_callback);

  return data;
}

void string_to_file(string_ data, string_ file_path) {
  SimpleStorage simple_storage;
  std::unique_ptr<StorageBucket> storage_bucket;
  storage_bucket = simple_storage.get_bucket(file_path);
  auto content = new RefCountBytes(&data.c_str()[0], &data.c_str()[strlen(data.c_str())]);

  storage_bucket->write(file_path, std::forward<RefCountBytes*>(content));
}

std::vector<unsigned char> get_random_byte_array(int len) {
  if (!IS_RAND_INITIALIZED) {
    RAND_poll();
    IS_RAND_INITIALIZED = 1;
  }
  std::vector<unsigned char> buffer(len);
  RAND_bytes(buffer.data(), len);
  return buffer;
}
static unsigned char get_random_char() {
  while (1) {
    unsigned char n = (unsigned char)(get_random_byte_array(1)[0] & 0x7F);
    if ((n >= '0' && n <= '9') || (n >= 'A' && n <= 'Z') ||
        (n >= 'a' && n <= 'z')) {
      return n;
    }
  }
}
string_ generate_random_string(int len) {
  string_ randStr;

  for (int i = 0; i < len; ++i) {
    randStr += get_random_char();
  }

  return randStr;
}

string_ get_close_token_from_file(string_ path_str,
                                  bool force_to_generate_one) {
  try {
    string_ token = string_from_file(path_str);
    if (token.length() != 32)
      throw std::runtime_error("invalid token length != 32 in file");
    return token;

  } catch (std::exception &e) {
    if (!force_to_generate_one) return "";
  }

  auto new_token = generate_random_string(32);
  string_to_file(new_token, path_str);

  return new_token;
}
}<commit_msg>fix compilation error, need to include io_service first so winsock header is included in the right order<commit_after>#include "dsa_common.h"

#include "string.h"

#include <boost/asio/io_service.hpp>
#include <boost/filesystem.hpp>
#include "module/default/simple_storage.h"
#include "openssl/rand.h"

using namespace std;
namespace fs = boost::filesystem;

namespace dsa {

string_ string_from_file(string_ file_path) {
  SimpleStorage simple_storage;
  std::unique_ptr<StorageBucket> storage_bucket;
  string_ data;
  storage_bucket = simple_storage.get_bucket(file_path);
  auto read_callback = [&](std::string storage_key, std::vector<uint8_t> vec) {
    string_ content(vec.begin(), vec.end());
    data = content;
  };
  storage_bucket->read(file_path, read_callback);

  return data;
}

void string_to_file(string_ data, string_ file_path) {
  SimpleStorage simple_storage;
  std::unique_ptr<StorageBucket> storage_bucket;
  storage_bucket = simple_storage.get_bucket(file_path);
  auto content =
      new RefCountBytes(&data.c_str()[0], &data.c_str()[strlen(data.c_str())]);

  storage_bucket->write(file_path, std::forward<RefCountBytes *>(content));
}

std::vector<unsigned char> get_random_byte_array(int len) {
  if (!IS_RAND_INITIALIZED) {
    RAND_poll();
    IS_RAND_INITIALIZED = 1;
  }
  std::vector<unsigned char> buffer(len);
  RAND_bytes(buffer.data(), len);
  return buffer;
}
static unsigned char get_random_char() {
  while (1) {
    unsigned char n = (unsigned char)(get_random_byte_array(1)[0] & 0x7F);
    if ((n >= '0' && n <= '9') || (n >= 'A' && n <= 'Z') ||
        (n >= 'a' && n <= 'z')) {
      return n;
    }
  }
}
string_ generate_random_string(int len) {
  string_ randStr;

  for (int i = 0; i < len; ++i) {
    randStr += get_random_char();
  }

  return randStr;
}

string_ get_close_token_from_file(string_ path_str,
                                  bool force_to_generate_one) {
  try {
    string_ token = string_from_file(path_str);
    if (token.length() != 32)
      throw std::runtime_error("invalid token length != 32 in file");
    return token;

  } catch (std::exception &e) {
    if (!force_to_generate_one) return "";
  }

  auto new_token = generate_random_string(32);
  string_to_file(new_token, path_str);

  return new_token;
}
}<|endoftext|>


<commit_before>#include "include/writer.h"

#include <QFile>
#include <QTextStream>
#include <QDebug>

#include "include/abstractdata.h"
#include "filechecker.h"

using namespace QtCSV;

// Write data to .csv file
// @input:
// - filePath - string with absolute path to csv file
// - data - not empty data that should be written to .csv file
// - separator - string or character separating columns
// - mode - write mode of the file: rewrite file or append data to the end
// - header - strings that will be written at the beginning of the file in
// one line. separator will be used as delimiter character.
// - footer - strings that will be written at the end of the file in
// one line. separator will be used as delimiter character.
// @output:
// - bool - True if data was written to the file, otherwise False
bool Writer::write(const QString &filePath,
                   const AbstractData &data,
                   const QString &separator,
                   const WriteMode &mode,
                   const QStringList &header,
                   const QStringList &footer)
{
    if ( true == filePath.isEmpty() ||
         true == data.isEmpty() )
    {
        qDebug() << __func__ << "Error - invalid arguments";
        return false;
    }

    if ( false == CheckFile(filePath) )
    {
        qDebug() << __func__ << "Error - wrong file path/name:" << filePath;
        return false;
    }

    QFile csvFile;
    csvFile.setFileName(filePath);

    bool fileOpened = csvFile.open(GetMode(mode) | QIODevice::Text);
    if ( false == fileOpened )
    {
        qDebug() << __func__ << "Error - can't open file:" << filePath;
        return false;
    }

    QTextStream stream;
    stream.setDevice(&csvFile);

    if ( false == header.isEmpty() )
    {
        stream << header.join(separator) << endl;
    }

    int rowsNum = data.getNumberOfRows();
    for (int i = 0; i < rowsNum; ++i)
    {
        QStringList rowValues = data.getRowValues(i);
        stream << rowValues.join(separator) << endl;
    }

    if ( false == footer.isEmpty() )
    {
        stream << footer.join(separator) << endl;
    }

    csvFile.close();

    return true;
}

// Get QIODevice mode
// @input:
// - mode - write mode
// @output:
// - QIODevice::OpenMode - corresponding QIODevice::OpenMode
QIODevice::OpenMode Writer::GetMode(const WriteMode &mode)
{
    switch (mode)
    {
        case WriteMode::APPEND:
            return QIODevice::Append;
        case WriteMode::REWRITE:
        default:
            return QIODevice::WriteOnly;
    }

    return QIODevice::WriteOnly;
}
<commit_msg>Postpone all operations with file to the end of the write() function<commit_after>#include "include/writer.h"

#include <QFile>
#include <QTextStream>
#include <QDebug>

#include "include/abstractdata.h"
#include "filechecker.h"

using namespace QtCSV;

// Write data to .csv file
// @input:
// - filePath - string with absolute path to csv file
// - data - not empty data that should be written to .csv file
// - separator - string or character separating columns
// - mode - write mode of the file: rewrite file or append data to the end
// - header - strings that will be written at the beginning of the file in
// one line. separator will be used as delimiter character.
// - footer - strings that will be written at the end of the file in
// one line. separator will be used as delimiter character.
// @output:
// - bool - True if data was written to the file, otherwise False
bool Writer::write(const QString &filePath,
                   const AbstractData &data,
                   const QString &separator,
                   const WriteMode &mode,
                   const QStringList &header,
                   const QStringList &footer)
{
    if ( true == filePath.isEmpty() ||
         true == data.isEmpty() )
    {
        qDebug() << __func__ << "Error - invalid arguments";
        return false;
    }

    if ( false == CheckFile(filePath) )
    {
        qDebug() << __func__ << "Error - wrong file path/name:" << filePath;
        return false;
    }

    // Prepare data that would be written to file
    QStringList textLines;
    if ( false == header.isEmpty() )
    {
        textLines << header.join(separator);
    }

    const int rowsNum = data.getNumberOfRows();
    for (int i = 0; i < rowsNum; ++i)
    {
        textLines << data.getRowValues(i).join(separator);
    }

    if ( false == footer.isEmpty() )
    {
        textLines << footer.join(separator);
    }

    // Write prepaired data to file
    QFile csvFile(filePath);
    if ( false == csvFile.open(GetMode(mode) | QIODevice::Text) )
    {
        qDebug() << __func__ << "Error - can't open file:" << filePath;
        return false;
    }

    QTextStream stream;
    stream.setDevice(&csvFile);
    stream << textLines.join("\n");
    stream.flush();

    csvFile.close();

    return true;
}

// Get QIODevice mode
// @input:
// - mode - write mode
// @output:
// - QIODevice::OpenMode - corresponding QIODevice::OpenMode
QIODevice::OpenMode Writer::GetMode(const WriteMode &mode)
{
    switch (mode)
    {
        case WriteMode::APPEND:
            return QIODevice::Append;
        case WriteMode::REWRITE:
        default:
            return QIODevice::WriteOnly;
    }

    return QIODevice::WriteOnly;
}
<|endoftext|>