<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      toolbar.cpp
// Purpose:   Implementation of wxExToolBar class
// Author:    Anton van Wezenbeek
// Copyright: (c) 2013 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/extension/toolbar.h>
#include <wx/extension/art.h>
#include <wx/extension/frame.h>
#include <wx/extension/frd.h>
#include <wx/extension/stc.h>
#include <wx/extension/util.h>

#if wxUSE_GUI

// Cannot use wxNewId here, as these are used in a switch statement.
enum
{
  ID_MATCH_WHOLE_WORD = 100,
  ID_MATCH_CASE,
  ID_REGULAR_EXPRESSION,
  ID_HEX_MODE,
  ID_SYNC_MODE
};

// Support class.
// Offers a find text ctrl that allows you to find text
// on a current STC on an wxExFrame.
class wxExTextCtrl : public wxExFindTextCtrl
{
public:
  /// Constructor. Fills the text ctrl with value
  /// from FindReplace from config.
  wxExTextCtrl(
    wxWindow* parent,
    wxExFrame* frame,
    wxWindowID id = wxID_ANY,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize);

  /// Finds current value in control.
  void Find(bool find_next = true, bool restore_position = false);
protected:
  void OnCommand(wxCommandEvent& event);
  void OnEnter(wxCommandEvent& event);
  void OnFocus(wxFocusEvent& event);
private:
  wxExFrame* m_Frame;

  DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(wxExToolBar, wxAuiToolBar)
  EVT_CHECKBOX(ID_HEX_MODE, wxExToolBar::OnCommand)
  EVT_CHECKBOX(ID_SYNC_MODE, wxExToolBar::OnCommand)
END_EVENT_TABLE()

wxExToolBar::wxExToolBar(wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxAuiToolBar(frame, id, pos, size, style | wxAUI_TB_HORZ_TEXT)
  , m_Frame(frame)
  , m_HexMode(NULL)
  , m_SyncMode(NULL)
{
}

void wxExToolBar::AddControls()
{
  AddTool(wxID_OPEN);
  AddTool(wxID_SAVE);
  AddTool(wxID_PRINT);
  AddTool(wxID_FIND);

  AddControl(
    m_HexMode = new wxCheckBox(
      this,
      ID_HEX_MODE,
      "Hex"));

  AddControl(
    m_SyncMode = new wxCheckBox(
      this,
      ID_SYNC_MODE,
      "Sync"));

#if wxUSE_TOOLTIPS
  m_HexMode->SetToolTip(_("Open in hex mode"));
  m_SyncMode->SetToolTip(_("Synchronize modified files"));
#endif

  m_HexMode->SetValue(wxConfigBase::Get()->ReadBool("HexMode", false));
  m_SyncMode->SetValue(wxConfigBase::Get()->ReadBool("AllowSync", true));

  Realize();
}

wxAuiToolBarItem* wxExToolBar::AddTool(
  int toolId,
  const wxString& label,
  const wxBitmap& bitmap,
  const wxString& shortHelp,
  wxItemKind kind)
{
  const wxExStockArt art(toolId);

  if (art.GetBitmap(wxART_TOOLBAR).IsOk())
  {
    return wxAuiToolBar::AddTool(
      toolId,
      wxEmptyString,
      art.GetBitmap(wxART_TOOLBAR),
      wxGetStockLabel(toolId, wxSTOCK_NOFLAGS),
      kind);
  }
  else
  {
    return wxAuiToolBar::AddTool(
      toolId,
      label,
      bitmap,
      shortHelp,
      kind);
  }
}

void wxExToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case ID_HEX_MODE:
    wxConfigBase::Get()->Write("HexMode", m_HexMode->GetValue());
    break;

  case ID_SYNC_MODE:
    wxConfigBase::Get()->Write("AllowSync", m_SyncMode->GetValue());
    break;

  default:
    wxFAIL;
    break;
  }
}

BEGIN_EVENT_TABLE(wxExFindToolBar, wxExToolBar)
  EVT_CHECKBOX(ID_MATCH_WHOLE_WORD, wxExFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_MATCH_CASE, wxExFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_REGULAR_EXPRESSION, wxExFindToolBar::OnCommand)
  EVT_MENU(wxID_DOWN, wxExFindToolBar::OnCommand)
  EVT_MENU(wxID_UP, wxExFindToolBar::OnCommand)
  EVT_UPDATE_UI(wxID_DOWN, wxExFindToolBar::OnUpdateUI)
  EVT_UPDATE_UI(wxID_UP, wxExFindToolBar::OnUpdateUI)
END_EVENT_TABLE()

wxExFindToolBar::wxExFindToolBar(
  wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExToolBar(frame, id, pos, size, style)
{
  Initialize();

  // And place the controls on the toolbar.
  AddControl(m_FindCtrl);

  AddTool(
    wxID_DOWN,
    wxEmptyString,
    wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR),
    _("Find next"));
  AddTool(
    wxID_UP,
    wxEmptyString,
    wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR),
    _("Find previous"));

  AddControl(m_MatchWholeWord);
  AddControl(m_MatchCase);
  AddControl(m_IsRegularExpression);

  Realize();
}

void wxExFindToolBar::Initialize()
{
  m_FindCtrl = new wxExTextCtrl(this, GetFrame());

  m_MatchCase = new wxCheckBox(this,
    ID_MATCH_CASE, wxExFindReplaceData::Get()->GetTextMatchCase());

  m_MatchWholeWord = new wxCheckBox(this,
    ID_MATCH_WHOLE_WORD, wxExFindReplaceData::Get()->GetTextMatchWholeWord());

  m_IsRegularExpression = new wxCheckBox(this,
    ID_REGULAR_EXPRESSION, wxExFindReplaceData::Get()->GetTextRegEx());

#if wxUSE_TOOLTIPS
  m_MatchCase->SetToolTip(_("Search case sensitive"));
  m_MatchWholeWord->SetToolTip(_("Search matching words"));
  m_IsRegularExpression->SetToolTip(_("Search using regular expressions"));
#endif

  m_MatchCase->SetValue(wxExFindReplaceData::Get()->MatchCase());
  m_MatchWholeWord->SetValue(wxExFindReplaceData::Get()->MatchWord());
  m_IsRegularExpression->SetValue(wxExFindReplaceData::Get()->UseRegularExpression());
}

void wxExFindToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case wxID_DOWN:
  case wxID_UP:
    m_FindCtrl->Find(event.GetId() == wxID_DOWN);
    break;
  case ID_MATCH_WHOLE_WORD:
    wxExFindReplaceData::Get()->SetMatchWord(
      m_MatchWholeWord->GetValue());
    break;
  case ID_MATCH_CASE:
    wxExFindReplaceData::Get()->SetMatchCase(
      m_MatchCase->GetValue());
    break;
  case ID_REGULAR_EXPRESSION:
    wxExFindReplaceData::Get()->SetUseRegularExpression(
      m_IsRegularExpression->GetValue());
    break;
  default:
    wxFAIL;
    break;
  }
}

void wxExFindToolBar::OnUpdateUI(wxUpdateUIEvent& event)
{
  event.Enable(!m_FindCtrl->GetValue().empty());
}

// Implementation of support class.

BEGIN_EVENT_TABLE(wxExTextCtrl, wxExFindTextCtrl)
  EVT_SET_FOCUS(wxExTextCtrl::OnFocus)
  EVT_TEXT(wxID_ANY, wxExTextCtrl::OnCommand)
  EVT_TEXT_ENTER(wxID_ANY, wxExTextCtrl::OnEnter)
END_EVENT_TABLE()

wxExTextCtrl::wxExTextCtrl(
  wxWindow* parent,
  wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size)
  : wxExFindTextCtrl(parent, id, pos, size)
  , m_Frame(frame)
{
  const int accels = 1;
  wxAcceleratorEntry entries[accels];
  entries[0].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_DELETE);
  wxAcceleratorTable accel(accels, entries);
  SetAcceleratorTable(accel);
}

void wxExTextCtrl::Find(bool find_next, bool restore_position)
{
  // We cannot use events here, as OnFindDialog in stc uses frd data,
  // whereas we need the GetValue here.
  wxExSTC* stc = m_Frame->GetSTC();

  if (stc != NULL)
  {
    m_Frame->SetFindFocus(stc);

    if (restore_position)
    {
      stc->PositionRestore();
    }

    stc->FindNext(
      GetValue(),
      wxExFindReplaceData::Get()->STCFlags(),
      find_next);
  }
}

void wxExTextCtrl::OnCommand(wxCommandEvent& event)
{
  event.Skip();
  Find(true, true);
}

void wxExTextCtrl::OnEnter(wxCommandEvent& event)
{
  if (!GetValue().empty())
  {
    Find();
  }
}

void wxExTextCtrl::OnFocus(wxFocusEvent& event)
{
  wxExSTC* stc = m_Frame->GetSTC();

  if (stc != NULL)
  {
    stc->PositionSave();
  }

  event.Skip();
}
#endif // wxUSE_GUI
<commit_msg>use TB_PLAIN_BACKGROUND<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      toolbar.cpp
// Purpose:   Implementation of wxExToolBar class
// Author:    Anton van Wezenbeek
// Copyright: (c) 2013 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/extension/toolbar.h>
#include <wx/extension/art.h>
#include <wx/extension/frame.h>
#include <wx/extension/frd.h>
#include <wx/extension/stc.h>
#include <wx/extension/util.h>

#if wxUSE_GUI

// Cannot use wxNewId here, as these are used in a switch statement.
enum
{
  ID_MATCH_WHOLE_WORD = 100,
  ID_MATCH_CASE,
  ID_REGULAR_EXPRESSION,
  ID_HEX_MODE,
  ID_SYNC_MODE
};

// Support class.
// Offers a find text ctrl that allows you to find text
// on a current STC on an wxExFrame.
class wxExTextCtrl : public wxExFindTextCtrl
{
public:
  /// Constructor. Fills the text ctrl with value
  /// from FindReplace from config.
  wxExTextCtrl(
    wxWindow* parent,
    wxExFrame* frame,
    wxWindowID id = wxID_ANY,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize);

  /// Finds current value in control.
  void Find(bool find_next = true, bool restore_position = false);
protected:
  void OnCommand(wxCommandEvent& event);
  void OnEnter(wxCommandEvent& event);
  void OnFocus(wxFocusEvent& event);
private:
  wxExFrame* m_Frame;

  DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(wxExToolBar, wxAuiToolBar)
  EVT_CHECKBOX(ID_HEX_MODE, wxExToolBar::OnCommand)
  EVT_CHECKBOX(ID_SYNC_MODE, wxExToolBar::OnCommand)
END_EVENT_TABLE()

wxExToolBar::wxExToolBar(wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxAuiToolBar(frame, id, pos, size,
    style | wxAUI_TB_PLAIN_BACKGROUND | wxAUI_TB_HORZ_TEXT)
  , m_Frame(frame)
  , m_HexMode(NULL)
  , m_SyncMode(NULL)
{
}

void wxExToolBar::AddControls()
{
  AddTool(wxID_OPEN);
  AddTool(wxID_SAVE);
  AddTool(wxID_PRINT);
  AddTool(wxID_FIND);

  AddControl(
    m_HexMode = new wxCheckBox(
      this,
      ID_HEX_MODE,
      "Hex"));

  AddControl(
    m_SyncMode = new wxCheckBox(
      this,
      ID_SYNC_MODE,
      "Sync"));

#if wxUSE_TOOLTIPS
  m_HexMode->SetToolTip(_("Open in hex mode"));
  m_SyncMode->SetToolTip(_("Synchronize modified files"));
#endif

  m_HexMode->SetValue(wxConfigBase::Get()->ReadBool("HexMode", false));
  m_SyncMode->SetValue(wxConfigBase::Get()->ReadBool("AllowSync", true));

  Realize();
}

wxAuiToolBarItem* wxExToolBar::AddTool(
  int toolId,
  const wxString& label,
  const wxBitmap& bitmap,
  const wxString& shortHelp,
  wxItemKind kind)
{
  const wxExStockArt art(toolId);

  if (art.GetBitmap(wxART_TOOLBAR).IsOk())
  {
    return wxAuiToolBar::AddTool(
      toolId,
      wxEmptyString,
      art.GetBitmap(wxART_TOOLBAR),
      wxGetStockLabel(toolId, wxSTOCK_NOFLAGS),
      kind);
  }
  else
  {
    return wxAuiToolBar::AddTool(
      toolId,
      label,
      bitmap,
      shortHelp,
      kind);
  }
}

void wxExToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case ID_HEX_MODE:
    wxConfigBase::Get()->Write("HexMode", m_HexMode->GetValue());
    break;

  case ID_SYNC_MODE:
    wxConfigBase::Get()->Write("AllowSync", m_SyncMode->GetValue());
    break;

  default:
    wxFAIL;
    break;
  }
}

BEGIN_EVENT_TABLE(wxExFindToolBar, wxExToolBar)
  EVT_CHECKBOX(ID_MATCH_WHOLE_WORD, wxExFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_MATCH_CASE, wxExFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_REGULAR_EXPRESSION, wxExFindToolBar::OnCommand)
  EVT_MENU(wxID_DOWN, wxExFindToolBar::OnCommand)
  EVT_MENU(wxID_UP, wxExFindToolBar::OnCommand)
  EVT_UPDATE_UI(wxID_DOWN, wxExFindToolBar::OnUpdateUI)
  EVT_UPDATE_UI(wxID_UP, wxExFindToolBar::OnUpdateUI)
END_EVENT_TABLE()

wxExFindToolBar::wxExFindToolBar(
  wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExToolBar(frame, id, pos, size, style)
{
  Initialize();

  // And place the controls on the toolbar.
  AddControl(m_FindCtrl);

  AddTool(
    wxID_DOWN,
    wxEmptyString,
    wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR),
    _("Find next"));
  AddTool(
    wxID_UP,
    wxEmptyString,
    wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR),
    _("Find previous"));

  AddControl(m_MatchWholeWord);
  AddControl(m_MatchCase);
  AddControl(m_IsRegularExpression);

  Realize();
}

void wxExFindToolBar::Initialize()
{
  m_FindCtrl = new wxExTextCtrl(this, GetFrame());

  m_MatchCase = new wxCheckBox(this,
    ID_MATCH_CASE, wxExFindReplaceData::Get()->GetTextMatchCase());

  m_MatchWholeWord = new wxCheckBox(this,
    ID_MATCH_WHOLE_WORD, wxExFindReplaceData::Get()->GetTextMatchWholeWord());

  m_IsRegularExpression = new wxCheckBox(this,
    ID_REGULAR_EXPRESSION, wxExFindReplaceData::Get()->GetTextRegEx());

#if wxUSE_TOOLTIPS
  m_MatchCase->SetToolTip(_("Search case sensitive"));
  m_MatchWholeWord->SetToolTip(_("Search matching words"));
  m_IsRegularExpression->SetToolTip(_("Search using regular expressions"));
#endif

  m_MatchCase->SetValue(wxExFindReplaceData::Get()->MatchCase());
  m_MatchWholeWord->SetValue(wxExFindReplaceData::Get()->MatchWord());
  m_IsRegularExpression->SetValue(wxExFindReplaceData::Get()->UseRegularExpression());
}

void wxExFindToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case wxID_DOWN:
  case wxID_UP:
    m_FindCtrl->Find(event.GetId() == wxID_DOWN);
    break;
  case ID_MATCH_WHOLE_WORD:
    wxExFindReplaceData::Get()->SetMatchWord(
      m_MatchWholeWord->GetValue());
    break;
  case ID_MATCH_CASE:
    wxExFindReplaceData::Get()->SetMatchCase(
      m_MatchCase->GetValue());
    break;
  case ID_REGULAR_EXPRESSION:
    wxExFindReplaceData::Get()->SetUseRegularExpression(
      m_IsRegularExpression->GetValue());
    break;
  default:
    wxFAIL;
    break;
  }
}

void wxExFindToolBar::OnUpdateUI(wxUpdateUIEvent& event)
{
  event.Enable(!m_FindCtrl->GetValue().empty());
}

// Implementation of support class.

BEGIN_EVENT_TABLE(wxExTextCtrl, wxExFindTextCtrl)
  EVT_SET_FOCUS(wxExTextCtrl::OnFocus)
  EVT_TEXT(wxID_ANY, wxExTextCtrl::OnCommand)
  EVT_TEXT_ENTER(wxID_ANY, wxExTextCtrl::OnEnter)
END_EVENT_TABLE()

wxExTextCtrl::wxExTextCtrl(
  wxWindow* parent,
  wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size)
  : wxExFindTextCtrl(parent, id, pos, size)
  , m_Frame(frame)
{
  const int accels = 1;
  wxAcceleratorEntry entries[accels];
  entries[0].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_DELETE);
  wxAcceleratorTable accel(accels, entries);
  SetAcceleratorTable(accel);
}

void wxExTextCtrl::Find(bool find_next, bool restore_position)
{
  // We cannot use events here, as OnFindDialog in stc uses frd data,
  // whereas we need the GetValue here.
  wxExSTC* stc = m_Frame->GetSTC();

  if (stc != NULL)
  {
    m_Frame->SetFindFocus(stc);

    if (restore_position)
    {
      stc->PositionRestore();
    }

    stc->FindNext(
      GetValue(),
      wxExFindReplaceData::Get()->STCFlags(),
      find_next);
  }
}

void wxExTextCtrl::OnCommand(wxCommandEvent& event)
{
  event.Skip();
  Find(true, true);
}

void wxExTextCtrl::OnEnter(wxCommandEvent& event)
{
  if (!GetValue().empty())
  {
    Find();
  }
}

void wxExTextCtrl::OnFocus(wxFocusEvent& event)
{
  wxExSTC* stc = m_Frame->GetSTC();

  if (stc != NULL)
  {
    stc->PositionSave();
  }

  event.Skip();
}
#endif // wxUSE_GUI
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#ifndef UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_STORAGE_MARSHALLER_HPP_INCLUDED
#define UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_STORAGE_MARSHALLER_HPP_INCLUDED

#include <uavcan/build_config.hpp>
#include <uavcan/debug.hpp>
#include <uavcan/protocol/dynamic_node_id_server/storage_backend.hpp>
#include <uavcan/protocol/dynamic_node_id_server/types.hpp>
#include <cstdlib>

#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
# include <cerrno>
#endif

namespace uavcan
{
namespace dynamic_node_id_server
{
/**
 * This class extends the storage backend interface with serialization/deserialization functionality.
 */
class StorageMarshaller
{
    IStorageBackend& storage_;

    static uint8_t convertLowerCaseHexCharToNibble(char ch)
    {
        const uint8_t ret = (ch > '9') ? static_cast<uint8_t>(ch - 'a' + 10) : static_cast<uint8_t>(ch - '0');
        UAVCAN_ASSERT(ret < 16);
        return ret;
    }

public:
    StorageMarshaller(IStorageBackend& storage)
        : storage_(storage)
    { }

    /**
     * Turns a unique ID into a hex string that can be used as a key or as a value.
     */
    static IStorageBackend::String convertUniqueIDToHex(const UniqueID& key)
    {
        IStorageBackend::String serialized;
        for (uint8_t i = 0; i < UniqueID::MaxSize; i++)
        {
            serialized.appendFormatted("%02x", key.at(i));
        }
        UAVCAN_ASSERT(serialized.size() == UniqueID::MaxSize * 2);
        return serialized;
    }

    /**
     * These methods set the value and then immediately read it back.
     *  1. Serialize the value.
     *  2. Update the value on the backend.
     *  3. Call get() with the same value argument.
     * The caller then is supposed to check whether the argument has the desired value.
     */
    int setAndGetBack(const IStorageBackend::String& key, uint32_t& inout_value)
    {
        IStorageBackend::String serialized;
        serialized.appendFormatted("%llu", static_cast<unsigned long long>(inout_value));

        UAVCAN_TRACE("StorageMarshaller", "Set %s = %s", key.c_str(), serialized.c_str());
        storage_.set(key, serialized);

        return get(key, inout_value);
    }

    int setAndGetBack(const IStorageBackend::String& key, UniqueID& inout_value)
    {
        const IStorageBackend::String serialized = convertUniqueIDToHex(inout_value);

        UAVCAN_TRACE("StorageMarshaller", "Set %s = %s", key.c_str(), serialized.c_str());
        storage_.set(key, serialized);

        return get(key, inout_value);
    }

    /**
     * Getters simply read and deserialize the value.
     *  1. Read the value back from the backend; return false if read fails.
     *  2. Deserealize the newly read value; return false if deserialization fails.
     *  3. Update the argument with deserialized value.
     *  4. Return true.
     */
    int get(const IStorageBackend::String& key, uint32_t& out_value) const
    {
        /*
         * Reading the storage
         */
        const IStorageBackend::String val = storage_.get(key);
        if (val.empty())
        {
            return -ErrFailure;
        }

        /*
         * Per MISRA C++ recommendations, checking the inputs instead of relying solely on errno.
         * The value must contain only numeric characters.
         */
        for (IStorageBackend::String::const_iterator it = val.begin(); it != val.end(); ++it)
        {
            if (static_cast<char>(*it) < '0' || static_cast<char>(*it) > '9')
            {
                return -ErrFailure;
            }
        }

        if (val.size() > 10) // len(str(0xFFFFFFFF))
        {
            return -ErrFailure;
        }

        /*
         * Conversion is carried out here
         */
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
        errno = 0;
#endif

#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
        const unsigned long long x = std::strtoull(val.c_str(), UAVCAN_NULLPTR, 10);
#else
        // There was no strtoull() before C++11, so we need to resort to strtoul()
        StaticAssert<(sizeof(unsigned long) >= sizeof(uint32_t))>::check();
        const unsigned long x = std::strtoul(val.c_str(), UAVCAN_NULLPTR, 10);
#endif

#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
        if (errno != 0)
        {
            return -ErrFailure;
        }
#endif

        out_value = static_cast<uint32_t>(x);
        return 0;
    }

    int get(const IStorageBackend::String& key, UniqueID& out_value) const
    {
        static const uint8_t NumBytes = UniqueID::MaxSize;

        /*
         * Reading the storage
         */
        IStorageBackend::String val = storage_.get(key);
        if (val.size() != NumBytes * 2)
        {
            return -ErrFailure;
        }

        /*
         * The value must contain only hexadecimal numbers.
         */
        val.convertToLowerCaseASCII();
        for (IStorageBackend::String::const_iterator it = val.begin(); it != val.end(); ++it)
        {
            if ((static_cast<char>(*it) < '0' || static_cast<char>(*it) > '9') &&
                (static_cast<char>(*it) < 'a' || static_cast<char>(*it) > 'f'))
            {
                return -ErrFailure;
            }
        }

        /*
         * Conversion is carried out here
         */
        IStorageBackend::String::const_iterator it = val.begin();

        for (uint8_t byte_index = 0; byte_index < NumBytes; byte_index++)
        {
            out_value[byte_index] =
                static_cast<uint8_t>(convertLowerCaseHexCharToNibble(static_cast<char>(*it++)) << 4);
            out_value[byte_index] =
                static_cast<uint8_t>(convertLowerCaseHexCharToNibble(static_cast<char>(*it++)) | out_value[byte_index]);
        }

        return 0;
    }
};

}
}

#endif // Include guard
<commit_msg>protocol: replace unsupported %llu format string<commit_after>/*
 * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#ifndef UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_STORAGE_MARSHALLER_HPP_INCLUDED
#define UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_STORAGE_MARSHALLER_HPP_INCLUDED

#include <uavcan/build_config.hpp>
#include <uavcan/debug.hpp>
#include <uavcan/protocol/dynamic_node_id_server/storage_backend.hpp>
#include <uavcan/protocol/dynamic_node_id_server/types.hpp>
#include <cstdlib>

#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
# include <cerrno>
#endif

namespace uavcan
{
namespace dynamic_node_id_server
{
/**
 * This class extends the storage backend interface with serialization/deserialization functionality.
 */
class StorageMarshaller
{
    IStorageBackend& storage_;

    static uint8_t convertLowerCaseHexCharToNibble(char ch)
    {
        const uint8_t ret = (ch > '9') ? static_cast<uint8_t>(ch - 'a' + 10) : static_cast<uint8_t>(ch - '0');
        UAVCAN_ASSERT(ret < 16);
        return ret;
    }

public:
    StorageMarshaller(IStorageBackend& storage)
        : storage_(storage)
    { }

    /**
     * Turns a unique ID into a hex string that can be used as a key or as a value.
     */
    static IStorageBackend::String convertUniqueIDToHex(const UniqueID& key)
    {
        IStorageBackend::String serialized;
        for (uint8_t i = 0; i < UniqueID::MaxSize; i++)
        {
            serialized.appendFormatted("%02x", key.at(i));
        }
        UAVCAN_ASSERT(serialized.size() == UniqueID::MaxSize * 2);
        return serialized;
    }

    /**
     * These methods set the value and then immediately read it back.
     *  1. Serialize the value.
     *  2. Update the value on the backend.
     *  3. Call get() with the same value argument.
     * The caller then is supposed to check whether the argument has the desired value.
     */
    int setAndGetBack(const IStorageBackend::String& key, uint32_t& inout_value)
    {
        IStorageBackend::String serialized;
        serialized.appendFormatted("%lu", inout_value);

        UAVCAN_TRACE("StorageMarshaller", "Set %s = %s", key.c_str(), serialized.c_str());
        storage_.set(key, serialized);

        return get(key, inout_value);
    }

    int setAndGetBack(const IStorageBackend::String& key, UniqueID& inout_value)
    {
        const IStorageBackend::String serialized = convertUniqueIDToHex(inout_value);

        UAVCAN_TRACE("StorageMarshaller", "Set %s = %s", key.c_str(), serialized.c_str());
        storage_.set(key, serialized);

        return get(key, inout_value);
    }

    /**
     * Getters simply read and deserialize the value.
     *  1. Read the value back from the backend; return false if read fails.
     *  2. Deserealize the newly read value; return false if deserialization fails.
     *  3. Update the argument with deserialized value.
     *  4. Return true.
     */
    int get(const IStorageBackend::String& key, uint32_t& out_value) const
    {
        /*
         * Reading the storage
         */
        const IStorageBackend::String val = storage_.get(key);
        if (val.empty())
        {
            return -ErrFailure;
        }

        /*
         * Per MISRA C++ recommendations, checking the inputs instead of relying solely on errno.
         * The value must contain only numeric characters.
         */
        for (IStorageBackend::String::const_iterator it = val.begin(); it != val.end(); ++it)
        {
            if (static_cast<char>(*it) < '0' || static_cast<char>(*it) > '9')
            {
                return -ErrFailure;
            }
        }

        if (val.size() > 10) // len(str(0xFFFFFFFF))
        {
            return -ErrFailure;
        }

        /*
         * Conversion is carried out here
         */
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
        errno = 0;
#endif

#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
        const unsigned long long x = std::strtoull(val.c_str(), UAVCAN_NULLPTR, 10);
#else
        // There was no strtoull() before C++11, so we need to resort to strtoul()
        StaticAssert<(sizeof(unsigned long) >= sizeof(uint32_t))>::check();
        const unsigned long x = std::strtoul(val.c_str(), UAVCAN_NULLPTR, 10);
#endif

#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
        if (errno != 0)
        {
            return -ErrFailure;
        }
#endif

        out_value = static_cast<uint32_t>(x);
        return 0;
    }

    int get(const IStorageBackend::String& key, UniqueID& out_value) const
    {
        static const uint8_t NumBytes = UniqueID::MaxSize;

        /*
         * Reading the storage
         */
        IStorageBackend::String val = storage_.get(key);
        if (val.size() != NumBytes * 2)
        {
            return -ErrFailure;
        }

        /*
         * The value must contain only hexadecimal numbers.
         */
        val.convertToLowerCaseASCII();
        for (IStorageBackend::String::const_iterator it = val.begin(); it != val.end(); ++it)
        {
            if ((static_cast<char>(*it) < '0' || static_cast<char>(*it) > '9') &&
                (static_cast<char>(*it) < 'a' || static_cast<char>(*it) > 'f'))
            {
                return -ErrFailure;
            }
        }

        /*
         * Conversion is carried out here
         */
        IStorageBackend::String::const_iterator it = val.begin();

        for (uint8_t byte_index = 0; byte_index < NumBytes; byte_index++)
        {
            out_value[byte_index] =
                static_cast<uint8_t>(convertLowerCaseHexCharToNibble(static_cast<char>(*it++)) << 4);
            out_value[byte_index] =
                static_cast<uint8_t>(convertLowerCaseHexCharToNibble(static_cast<char>(*it++)) | out_value[byte_index]);
        }

        return 0;
    }
};

}
}

#endif // Include guard
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(1)

class Solution {
public:
    /**
     * @param A : An integer array
     * @return : An integer
     */
    int singleNumberII(vector<int> &A) {
        int one = 0, two = 0;

        for (auto& i : A) {
            int new_one, new_two;
            new_one = (~i & one) | (i & ~one & ~two);
            new_two = (~i & two) | (i & one);
            one = new_one, two = new_two;
        }

        return one;
    }
};
<commit_msg>Update single-number-ii.cpp<commit_after>// Time:  O(n)
// Space: O(1)

class Solution {
public:
    /**
     * @param A : An integer array
     * @return : An integer
     */
    int singleNumberII(vector<int> &A) {
        int one = 0, two = 0;

        for (const auto& i : A) {
            int new_one, new_two;
            new_one = (~i & one) | (i & ~one & ~two);
            new_two = (~i & two) | (i & one);
            one = new_one, two = new_two;
        }

        return one;
    }
};
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/
#include "modules/planning/toolkits/optimizers/proceed_with_caution_speed/proceed_with_caution_speed_generator.h"

#include "gtest/gtest.h"

#include "modules/common/proto/pnc_point.pb.h"
#include "modules/perception/proto/perception_obstacle.pb.h"
#include "modules/planning/proto/planning_config.pb.h"

#include "cybertron/common/log.h"
#include "modules/common/util/file.h"
#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {

class ProceedWithCautionSpeedGeneratorTest : public ::testing::Test {
 public:
  virtual void SetUp() {}

  virtual void TearDown() {}

 protected:
  DpStSpeedConfig dp_config_;

  SLBoundary adc_sl_boundary_;
  PathData path_data_;
  common::TrajectoryPoint init_point_;
  PathDecision path_decision_;
};

TEST_F(ProceedWithCautionSpeedGeneratorTest, FixedSpeed) {
  ProceedWithCautionSpeedGenerator test_obj;

  // Set up testing for ProceedWithCautionSpeedGenerator::Init
  ProceedWithCautionSpeedConfig proceed_with_caution_speed_config;

  proceed_with_caution_speed_config.
      set_type(ProceedWithCautionSpeedConfig::FIXED_SPEED);
  proceed_with_caution_speed_config.set_max_speed(5.0);
  ScenarioConfig::ScenarioTaskConfig scenario_task_config;
  scenario_task_config.mutable_proceed_with_caution_speed_config()->
      CopyFrom(proceed_with_caution_speed_config);
  bool init_output = test_obj.Init(scenario_task_config);
  EXPECT_TRUE(init_output);

  // Set up testing for ProceedWithCautionSpeedGenerator::Process
  std::vector<common::PathPoint> path_points;
  common::PathPoint pointA;
  pointA.set_x(0.0);
  pointA.set_y(0.0);
  pointA.set_z(0.0);
  pointA.set_s(0.0);
  common::PathPoint pointB;
  pointB.set_x(10.0);
  pointB.set_y(0.0);
  pointB.set_z(0.0);
  pointB.set_s(10.0);
  path_points.emplace_back(pointA);
  path_points.emplace_back(pointB);
  DiscretizedPath path(path_points);
  double path_len = path.Length();
  EXPECT_EQ(path_len, 10.0);

  ReferenceLine reference_line_;
  path_data_.SetReferenceLine(&reference_line_);
  path_data_.SetDiscretizedPath(path);
  int num_of_points = path_data_.discretized_path().NumOfPoints();
  EXPECT_EQ(num_of_points, 2);

  SpeedData speed_data1;
  SpeedData speed_data2;
  common::Status process_status = test_obj.Process(adc_sl_boundary_,
      path_data_, init_point_, reference_line_, speed_data1,
      &path_decision_, &speed_data2);
  EXPECT_EQ(process_status, common::Status::OK());

  std::vector<common::SpeedPoint> speed_points = speed_data2.speed_vector();
  int num_speed_points = speed_points.size();
  EXPECT_GT(num_speed_points, 0);

  // Check if the output speed are the same for all points
  for (int i = 0; i < num_speed_points; i++) {
    double actual_speed = speed_points[i].v();
    EXPECT_EQ(actual_speed, 2.23);
  }
}

}  // namespace planning
}  // namespace apollo
<commit_msg>Planning: some minor bug fixes.<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/
#include "modules/planning/toolkits/optimizers/proceed_with_caution_speed/proceed_with_caution_speed_generator.h"

#include "gtest/gtest.h"

#include "modules/common/proto/pnc_point.pb.h"
#include "modules/perception/proto/perception_obstacle.pb.h"
#include "modules/planning/proto/planning_config.pb.h"

#include "cybertron/common/log.h"
#include "modules/common/util/file.h"
#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {

class ProceedWithCautionSpeedGeneratorTest : public ::testing::Test {
 public:
  virtual void SetUp() {}

  virtual void TearDown() {}

 protected:
  DpStSpeedConfig dp_config_;

  SLBoundary adc_sl_boundary_;
  PathData path_data_;
  common::TrajectoryPoint init_point_;
  PathDecision path_decision_;
};

TEST_F(ProceedWithCautionSpeedGeneratorTest, FixedSpeed) {
  ProceedWithCautionSpeedGenerator test_obj;

  // Set up testing for ProceedWithCautionSpeedGenerator::Init
  ProceedWithCautionSpeedConfig proceed_with_caution_speed_config;

  proceed_with_caution_speed_config.
      set_type(ProceedWithCautionSpeedConfig::FIXED_SPEED);
  proceed_with_caution_speed_config.set_max_speed(5.0);
  ScenarioConfig::ScenarioTaskConfig scenario_task_config;
  scenario_task_config.mutable_proceed_with_caution_speed_config()->
      CopyFrom(proceed_with_caution_speed_config);
  bool init_output = test_obj.Init(scenario_task_config);
  EXPECT_TRUE(init_output);

  // Set up testing for ProceedWithCautionSpeedGenerator::Process
  std::vector<common::PathPoint> path_points;
  common::PathPoint pointA;
  pointA.set_x(0.0);
  pointA.set_y(0.0);
  pointA.set_z(0.0);
  pointA.set_s(0.0);
  common::PathPoint pointB;
  pointB.set_x(10.0);
  pointB.set_y(0.0);
  pointB.set_z(0.0);
  pointB.set_s(10.0);
  path_points.emplace_back(pointA);
  path_points.emplace_back(pointB);
  DiscretizedPath path(path_points);
  double path_len = path.Length();
  EXPECT_EQ(path_len, 10.0);

  ReferenceLine reference_line_;
  path_data_.SetReferenceLine(&reference_line_);
  path_data_.SetDiscretizedPath(path);
  int num_of_points = path_data_.discretized_path().NumOfPoints();
  EXPECT_EQ(num_of_points, 2);

  SpeedData speed_data1;
  SpeedData speed_data2;
  common::Status process_status = test_obj.Process(adc_sl_boundary_,
      path_data_, init_point_, reference_line_, speed_data1,
      &path_decision_, &speed_data2);
  EXPECT_EQ(process_status, common::Status::OK());

  std::vector<common::SpeedPoint> speed_points = speed_data2.speed_vector();
  int num_speed_points = speed_points.size();
  EXPECT_GT(num_speed_points, 0);
  AERROR << "Number of speed points: " << num_speed_points;

  // Check if the output speed are the same for all points
  for (int i = 0; i < num_speed_points; i++) {
    double actual_speed = speed_points[i].v();
    EXPECT_DOUBLE_EQ(actual_speed, 2.23);
  }
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>// validator: no-include-guards
/*
disabled_warnings.hpp
*/
/*
Copyright © 2015 Far Group
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifdef _MSC_VER
// some warnings are not exist in older VC versions, no sense to care about them
#pragma warning(disable: 4616) // https://msdn.microsoft.com/en-us/library/t7ab6xtd.aspx #pragma warning : warning number 'number' not a valid compiler warning
#pragma warning(disable: 4619) // https://msdn.microsoft.com/en-us/library/tacee08d.aspx #pragma warning : there is no warning number 'number'

#ifdef DISABLE_WARNINGS_IN_STD_HEADERS
// these warnings are triggered in the standard headers ONLY
#pragma warning(disable: 4091) // https://msdn.microsoft.com/en-us/library/eehkcz60.aspx 'typedef ': ignored on left of 'type' when no variable is declared
#pragma warning(disable: 4265) // https://msdn.microsoft.com/en-us/library/wzxffy8c.aspx 'class' : class has virtual functions, but destructor is not virtual
#pragma warning(disable: 4668) // https://msdn.microsoft.com/en-us/library/4dt9kyhy.aspx 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
#pragma warning(disable: 4768) // no page                                                __declspec attributes before linkage specification are ignored
#pragma warning(disable: 4774) // no page                                                'function' : format string expected in argument 'number' is not a string literal
#pragma warning(disable: 4917) // https://msdn.microsoft.com/en-us/library/3w98z1xh.aspx 'declarator' : a GUID can only be associated with a class, interface or namespace
#pragma warning(disable: 4987) // no page                                                nonstandard extension used: 'throw (...)'
#pragma warning(disable: 4996) // https://msdn.microsoft.com/en-us/library/ttcz0bys.aspx The compiler encountered a deprecated declaration
#else
// these in the rest of the code as well
#pragma warning(disable: 4061) // https://msdn.microsoft.com/en-us/library/96f5t7fy.aspx enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label
#pragma warning(disable: 4100) // https://msdn.microsoft.com/en-us/library/26kb9fy0.aspx 'identifier' : unreferenced formal parameter
#pragma warning(disable: 4201) // https://msdn.microsoft.com/en-us/library/c89bw853.aspx nonstandard extension used : nameless struct/union
#pragma warning(disable: 4242) // https://msdn.microsoft.com/en-us/library/3hca13eh.aspx 'identifier' : conversion from 'type1' to 'type2', possible loss of data
#pragma warning(disable: 4244) // https://msdn.microsoft.com/en-us/library/th7a07tz.aspx 'conversion' conversion from 'type1' to 'type2', possible loss of data
#pragma warning(disable: 4245) // https://msdn.microsoft.com/en-us/library/e9s7thk1.aspx 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
#pragma warning(disable: 4250) // https://msdn.microsoft.com/en-us/library/6b3sy7ae.aspx 'class1' : inherits 'class2::member' via dominance
#pragma warning(disable: 4324) // https://msdn.microsoft.com/en-us/library/92fdk6xx.aspx 'struct_name' : structure was padded due to __declspec(align())
#pragma warning(disable: 4355) // https://msdn.microsoft.com/en-us/library/3c594ae3.aspx 'this' : used in base member initializer list
#pragma warning(disable: 4365) // https://msdn.microsoft.com/en-us/library/ms173683.aspx 'action' : conversion from 'type_1' to 'type_2', signed/unsigned mismatch
#pragma warning(disable: 4371) // no page                                                layout of class may have changed from a previous version of the compiler due to better packing of member 'member'
#pragma warning(disable: 4373) // https://msdn.microsoft.com/en-us/library/bb384874.aspx 'function': virtual function overrides 'function', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
#pragma warning(disable: 4435) // https://msdn.microsoft.com/en-us/library/jj155806.aspx 'class1' : Object layout under /vd2 will change due to virtual base 'class2'
#pragma warning(disable: 4503) // https://msdn.microsoft.com/en-us/library/074af4b6.aspx 'identifier' : decorated name length exceeded, name was truncated
#pragma warning(disable: 4512) // https://msdn.microsoft.com/en-us/library/hsyx7kbz.aspx 'class' : assignment operator could not be generated
#pragma warning(disable: 4514) // https://msdn.microsoft.com/en-us/library/cw9x3tcf.aspx 'function' : unreferenced inline function has been removed
#pragma warning(disable: 4571) // https://msdn.microsoft.com/en-us/library/55s8esw4.aspx Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught
#pragma warning(disable: 4623) // https://msdn.microsoft.com/en-us/library/8dk81ahy.aspx 'derived class' : default constructor was implicitly defined as deleted because a base class default constructor is inaccessible or deleted
#pragma warning(disable: 4625) // https://msdn.microsoft.com/en-us/library/306zwa5e.aspx 'derived class' : copy constructor could not be generated because a base class copy constructor is inaccessible
#pragma warning(disable: 4626) // https://msdn.microsoft.com/en-us/library/6ay4xcyd.aspx 'derived class' : assignment operator could not be generated because a base class assignment operator is inaccessible
#pragma warning(disable: 4640) // https://msdn.microsoft.com/en-us/library/4f5c8560.aspx 'instance' : construction of local static object is not thread-safe
#pragma warning(disable: 4710) // https://msdn.microsoft.com/en-us/library/yd3056cz.aspx 'function' : function not inlined
#pragma warning(disable: 4711) // https://msdn.microsoft.com/en-us/library/k402bt7y.aspx function 'function' selected for inline expansion
#pragma warning(disable: 4770) // no page                                                partially validated enum 'name' used as index
#pragma warning(disable: 4738) // https://msdn.microsoft.com/en-us/library/c24hdbz6.aspx storing 32-bit float result in memory, possible loss of performance
#pragma warning(disable: 4814) // no page                                                in C++14 'constexpr' will not imply 'const'; consider explicitly specifying 'const'
#pragma warning(disable: 4820) // https://msdn.microsoft.com/en-us/library/t7khkyth.aspx 'bytes' bytes padding added after construct 'member_name'
#pragma warning(disable: 4868) // https://msdn.microsoft.com/en-us/library/mt656772.aspx file(line_number)' compiler may not enforce left-to-right evaluation order in braced initializer list
#pragma warning(disable: 5025) // no page                                                'class': move assignment operator was implicitly defined as deleted
#pragma warning(disable: 5026) // no page                                                'class': move constructor was implicitly defined as deleted because a base class move constructor is inaccessible or deleted
#pragma warning(disable: 5027) // no page                                                'class': move assignment operator was implicitly defined as deleted because a base class move assignment operator is inaccessible or deleted
#pragma warning(disable: 5030) // no page                                                attribute 'attribute' is not recognized
#pragma warning(disable: 5039) // no page                                                'function': pointer or reference to potentially throwing function passed to extern C function under -EHc. Undefined behavior may occur if this function throws an exception.
#endif

#endif
<commit_msg>Suppress (may be temporary?) some c++17 specific warnings generated by VC14.13+ (VS2017.6+)<commit_after>// validator: no-include-guards
/*
disabled_warnings.hpp
*/
/*
Copyright © 2015 Far Group
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifdef _MSC_VER
// some warnings are not exist in older VC versions, no sense to care about them
#pragma warning(disable: 4616) // https://msdn.microsoft.com/en-us/library/t7ab6xtd.aspx #pragma warning : warning number 'number' not a valid compiler warning
#pragma warning(disable: 4619) // https://msdn.microsoft.com/en-us/library/tacee08d.aspx #pragma warning : there is no warning number 'number'

#ifdef DISABLE_WARNINGS_IN_STD_HEADERS
// these warnings are triggered in the standard headers ONLY
#pragma warning(disable: 4091) // https://msdn.microsoft.com/en-us/library/eehkcz60.aspx 'typedef ': ignored on left of 'type' when no variable is declared
#pragma warning(disable: 4265) // https://msdn.microsoft.com/en-us/library/wzxffy8c.aspx 'class' : class has virtual functions, but destructor is not virtual
#pragma warning(disable: 4668) // https://msdn.microsoft.com/en-us/library/4dt9kyhy.aspx 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
#pragma warning(disable: 4768) // no page                                                __declspec attributes before linkage specification are ignored
#pragma warning(disable: 4774) // no page                                                'function' : format string expected in argument 'number' is not a string literal
#pragma warning(disable: 4917) // https://msdn.microsoft.com/en-us/library/3w98z1xh.aspx 'declarator' : a GUID can only be associated with a class, interface or namespace
#pragma warning(disable: 4987) // no page                                                nonstandard extension used: 'throw (...)'
#pragma warning(disable: 4996) // https://msdn.microsoft.com/en-us/library/ttcz0bys.aspx The compiler encountered a deprecated declaration
#else
// these in the rest of the code as well
#pragma warning(disable: 4061) // https://msdn.microsoft.com/en-us/library/96f5t7fy.aspx enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label
#pragma warning(disable: 4100) // https://msdn.microsoft.com/en-us/library/26kb9fy0.aspx 'identifier' : unreferenced formal parameter
#pragma warning(disable: 4201) // https://msdn.microsoft.com/en-us/library/c89bw853.aspx nonstandard extension used : nameless struct/union
#pragma warning(disable: 4242) // https://msdn.microsoft.com/en-us/library/3hca13eh.aspx 'identifier' : conversion from 'type1' to 'type2', possible loss of data
#pragma warning(disable: 4244) // https://msdn.microsoft.com/en-us/library/th7a07tz.aspx 'conversion' conversion from 'type1' to 'type2', possible loss of data
#pragma warning(disable: 4245) // https://msdn.microsoft.com/en-us/library/e9s7thk1.aspx 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
#pragma warning(disable: 4250) // https://msdn.microsoft.com/en-us/library/6b3sy7ae.aspx 'class1' : inherits 'class2::member' via dominance
#pragma warning(disable: 4324) // https://msdn.microsoft.com/en-us/library/92fdk6xx.aspx 'struct_name' : structure was padded due to __declspec(align())
#pragma warning(disable: 4355) // https://msdn.microsoft.com/en-us/library/3c594ae3.aspx 'this' : used in base member initializer list
#pragma warning(disable: 4365) // https://msdn.microsoft.com/en-us/library/ms173683.aspx 'action' : conversion from 'type_1' to 'type_2', signed/unsigned mismatch
#pragma warning(disable: 4371) // no page                                                layout of class may have changed from a previous version of the compiler due to better packing of member 'member'
#pragma warning(disable: 4373) // https://msdn.microsoft.com/en-us/library/bb384874.aspx 'function': virtual function overrides 'function', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
#pragma warning(disable: 4435) // https://msdn.microsoft.com/en-us/library/jj155806.aspx 'class1' : Object layout under /vd2 will change due to virtual base 'class2'
#pragma warning(disable: 4503) // https://msdn.microsoft.com/en-us/library/074af4b6.aspx 'identifier' : decorated name length exceeded, name was truncated
#pragma warning(disable: 4512) // https://msdn.microsoft.com/en-us/library/hsyx7kbz.aspx 'class' : assignment operator could not be generated
#pragma warning(disable: 4514) // https://msdn.microsoft.com/en-us/library/cw9x3tcf.aspx 'function' : unreferenced inline function has been removed
#pragma warning(disable: 4571) // https://msdn.microsoft.com/en-us/library/55s8esw4.aspx Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught
#pragma warning(disable: 4623) // https://msdn.microsoft.com/en-us/library/8dk81ahy.aspx 'derived class' : default constructor was implicitly defined as deleted because a base class default constructor is inaccessible or deleted
#pragma warning(disable: 4625) // https://msdn.microsoft.com/en-us/library/306zwa5e.aspx 'derived class' : copy constructor could not be generated because a base class copy constructor is inaccessible
#pragma warning(disable: 4626) // https://msdn.microsoft.com/en-us/library/6ay4xcyd.aspx 'derived class' : assignment operator could not be generated because a base class assignment operator is inaccessible
#pragma warning(disable: 4640) // https://msdn.microsoft.com/en-us/library/4f5c8560.aspx 'instance' : construction of local static object is not thread-safe
#pragma warning(disable: 4710) // https://msdn.microsoft.com/en-us/library/yd3056cz.aspx 'function' : function not inlined
#pragma warning(disable: 4711) // https://msdn.microsoft.com/en-us/library/k402bt7y.aspx function 'function' selected for inline expansion
#pragma warning(disable: 4770) // no page                                                partially validated enum 'name' used as index
#pragma warning(disable: 4738) // https://msdn.microsoft.com/en-us/library/c24hdbz6.aspx storing 32-bit float result in memory, possible loss of performance
#pragma warning(disable: 4814) // no page                                                in C++14 'constexpr' will not imply 'const'; consider explicitly specifying 'const'
#pragma warning(disable: 4820) // https://msdn.microsoft.com/en-us/library/t7khkyth.aspx 'bytes' bytes padding added after construct 'member_name'
#pragma warning(disable: 4868) // https://msdn.microsoft.com/en-us/library/mt656772.aspx file(line_number)' compiler may not enforce left-to-right evaluation order in braced initializer list
#pragma warning(disable: 5025) // no page                                                'class': move assignment operator was implicitly defined as deleted
#pragma warning(disable: 5026) // no page                                                'class': move constructor was implicitly defined as deleted because a base class move constructor is inaccessible or deleted
#pragma warning(disable: 5027) // no page                                                'class': move assignment operator was implicitly defined as deleted because a base class move assignment operator is inaccessible or deleted
#pragma warning(disable: 5030) // no page                                                attribute 'attribute' is not recognized
#pragma warning(disable: 5039) // no page                                                'function': pointer or reference to potentially throwing function passed to extern C function under -EHc. Undefined behavior may occur if this function throws an exception.
#endif

#if _MSC_VER >= 1913 // may be temporary (VS2017.6+)
#pragma warning(disable: 4834) // no page                                                discarding return value of function with 'nodiscard' attribute
#define _SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING
#endif

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2011 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "link.h"
#include <zorba/item_factory.h>
#include <zorba/singleton_item_sequence.h>

#include <xercesc/util/XMLDouble.hpp>
#include "../ourlib/ourlib.h"

XERCES_CPP_NAMESPACE_USE

namespace zorba { namespace linkmodule {

LinkModule::LinkModule()
{
  theXercesFunc = new XercesFuncFunction(this);
  theOurFunc = new OurFuncFunction(this);
}

LinkModule::~LinkModule()
{
  delete theXercesFunc;
  delete theOurFunc;
}

zorba::ExternalFunction*
LinkModule::getExternalFunction(const zorba::String& aLocalname)
{
  if (aLocalname == "xerces-func") {
    return theXercesFunc;
  }
  else if (aLocalname == "our-func") {
    return theOurFunc;
  }
  return NULL;
}

XercesFuncFunction::XercesFuncFunction(const LinkModule* aModule)
  : theModule(aModule)
{
}

zorba::ItemSequence_t
XercesFuncFunction::evaluate(Arguments_t const& aArgs,
  zorba::StaticContext const* aSctx, zorba::DynamicContext const* aDctx) const
{
  // Silly test case
  XMLCh doub1[2], doub2[2];
  doub1[0] = '1';
  doub2[0] = '2';
  doub1[1] = doub2[1] = '\0';
  XMLDouble* xdoub1 = new XMLDouble(doub1);
  XMLDouble* xdoub2 = new XMLDouble(doub2);
  int lComp = XMLDouble::compareValues(xdoub1, xdoub2);
  zorba::Item lStr =
    Zorba::getInstance(0)->getItemFactory()->createInteger(lComp);
  return zorba::ItemSequence_t(new zorba::SingletonItemSequence(lStr));
}

OurFuncFunction::OurFuncFunction(const LinkModule* aModule)
  : theModule(aModule)
{
}

zorba::ItemSequence_t
OurFuncFunction::evaluate(Arguments_t const& aArgs,
  zorba::StaticContext const* aSctx, zorba::DynamicContext const* aDctx) const
{
  // Silly test case
  Ourlib* lOurlib = new Ourlib(55);
  int lVal = lOurlib->ourfunc();
  zorba::Item lStr =
    Zorba::getInstance(0)->getItemFactory()->createInteger(lVal);
  return zorba::ItemSequence_t(new zorba::SingletonItemSequence(lStr));
}

} /* namespace linkmodule */
} /* namespace zorba */

#ifdef WIN32
#  define DLL_EXPORT __declspec(dllexport)
#else
#  define DLL_EXPORT __attribute__ ((visibility("default")))
#endif

extern "C" DLL_EXPORT zorba::ExternalModule* createModule() {
  return new zorba::linkmodule::LinkModule();
}
<commit_msg>Plugging a couple memory leaks in a test case.<commit_after>/*
 * Copyright 2006-2011 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "link.h"
#include <zorba/item_factory.h>
#include <zorba/singleton_item_sequence.h>

#include <xercesc/util/XMLDouble.hpp>
#include "../ourlib/ourlib.h"

XERCES_CPP_NAMESPACE_USE

namespace zorba { namespace linkmodule {

LinkModule::LinkModule()
{
  theXercesFunc = new XercesFuncFunction(this);
  theOurFunc = new OurFuncFunction(this);
}

LinkModule::~LinkModule()
{
  delete theXercesFunc;
  delete theOurFunc;
}

zorba::ExternalFunction*
LinkModule::getExternalFunction(const zorba::String& aLocalname)
{
  if (aLocalname == "xerces-func") {
    return theXercesFunc;
  }
  else if (aLocalname == "our-func") {
    return theOurFunc;
  }
  return NULL;
}

XercesFuncFunction::XercesFuncFunction(const LinkModule* aModule)
  : theModule(aModule)
{
}

zorba::ItemSequence_t
XercesFuncFunction::evaluate(Arguments_t const& aArgs,
  zorba::StaticContext const* aSctx, zorba::DynamicContext const* aDctx) const
{
  // Silly test case
  XMLCh doub1[2], doub2[2];
  doub1[0] = '1';
  doub2[0] = '2';
  doub1[1] = doub2[1] = '\0';
  std::auto_ptr<XMLDouble> xdoub1(new XMLDouble(doub1));
  std::auto_ptr<XMLDouble> xdoub2(new XMLDouble(doub2));
  int lComp = XMLDouble::compareValues(xdoub1.get(), xdoub2.get());
  zorba::Item lStr =
    Zorba::getInstance(0)->getItemFactory()->createInteger(lComp);
  return zorba::ItemSequence_t(new zorba::SingletonItemSequence(lStr));
}

OurFuncFunction::OurFuncFunction(const LinkModule* aModule)
  : theModule(aModule)
{
}

zorba::ItemSequence_t
OurFuncFunction::evaluate(Arguments_t const& aArgs,
  zorba::StaticContext const* aSctx, zorba::DynamicContext const* aDctx) const
{
  // Silly test case
  std::auto_ptr<Ourlib> lOurlib(new Ourlib(55));
  int lVal = lOurlib->ourfunc();
  zorba::Item lStr =
    Zorba::getInstance(0)->getItemFactory()->createInteger(lVal);
  return zorba::ItemSequence_t(new zorba::SingletonItemSequence(lStr));
}

} /* namespace linkmodule */
} /* namespace zorba */

#ifdef WIN32
#  define DLL_EXPORT __declspec(dllexport)
#else
#  define DLL_EXPORT __attribute__ ((visibility("default")))
#endif

extern "C" DLL_EXPORT zorba::ExternalModule* createModule() {
  return new zorba::linkmodule::LinkModule();
}
<|endoftext|>


<commit_before><commit_msg>WaE at mac tinderbox<commit_after><|endoftext|>


<commit_before>#include <catch.hpp>

#include "exp/misc.h"

#include <embr/datapump.hpp>
#include <embr/observer.h>
#include <embr/netbuf-static.h>

#include <exp/retry.h>

#include <exp/message-observer.h>
#include "test-observer.h"

#include "exp/prototype/observer-idea1.h"

#include "coap/decoder/subject.hpp"
#if __cplusplus >= 201103L
#include "platform/generic/malloc_netbuf.h"
#endif

#include "exp/events.h"
#include <exp/uripath-repeater.h>

//#include <estd/map.h>
#include <estd/stack.h>
#include <estd/sstream.h>
#include <estd/internal/ostream_basic_string.hpp>

#include "test-data.h"

using namespace moducom::coap;
using namespace moducom::coap::experimental;

typedef moducom::pipeline::MemoryChunk::readonly_t ro_chunk_t;
typedef moducom::pipeline::MemoryChunk chunk_t;

TEST_CASE("experimental 2 tests")
{
    typedef uint32_t addr_t;

#ifdef FEATURE_CPP_VARIADIC
    SECTION("AggregateMessageObserver")
    {
        moducom::pipeline::layer1::MemoryChunk<256> chunk;

        ObserverContext ctx(chunk);
        AggregateMessageObserver<ObserverContext,
                Buffer16BitDeltaObserver<ObserverContext>,
                EmptyObserver<ObserverContext>
                > amo(ctx);

        Header test_header(Header::Confirmable);
        //moducom::coap::layer1::Token token = ;
        uint8_t raw_token[] = { 0x45, 0x67 };

        test_header.token_length(sizeof(raw_token));
        test_header.message_id(0x0123);

        amo.on_header(test_header);
        //amo.on_token(raw_token); // not doing this only because Buffer16BitDeltaObserver hates it
        amo.on_option((moducom::coap::Option::Numbers) 270, 1);
    }
#endif
    SECTION("prototype observer idea1")
    {
        using namespace ::experimental::prototype::idea1;

#ifdef FEATURE_CPP_LAMBDA
        DecoderObserver test_target1([]()
        {
            // eventually activated when v1/target1 get is issued
        });
#endif

        URI uri[] =
        {
#if defined(FEATURE_CPP_MOVESEMANTIC) && defined(FEATURE_CPP_LAMBDA)
            URI("v1",
            {
                URI("target1", test_target1, true),
                URI("target2", [](IncomingContext<int>& ctx)
                {
                    // eventually activated when v2/target2 get is issued
                })
            }),
#endif
            URI("v2", 0, 2)
        };

        IncomingContext<int> ctx;

        decoder_observer(DecoderObserver(uri), ctx, buffer_16bit_delta);
    }
    SECTION("RandomPolicy test")
    {
        int value;

        for(int i = 0; i < 10; i++)
        {
            value = RandomPolicy::rand(100, 200);

            REQUIRE(value >= 100);
            REQUIRE(value <= 200);
        }
    }
    SECTION("uripath repeater")
    {
        moducom::coap::experimental::UriPathRepeater<embr::void_subject> upr;
    }
    SECTION("factory test")
    {
        constexpr int id_path_v1 = 0;
        constexpr int id_path_v1_api = 1;
        constexpr int id_path_v1_api_power = 2;
        constexpr int id_path_v1_api_test = 6;
        constexpr int id_path_dummy = 3;
        constexpr int id_path_v2 = 4;
        constexpr int id_path_v2_api = 5;

        // sort by parent id first, then by node id
        // this way we can easily optimize incoming request parsing by remembering
        // where we left off on found node id position
        // NOTE: might be better to sort by uri_path secondly instead of node_id,
        // as it potentially could speed up searching for said path.  However,
        // any of the secondary sorting the benefit is limited by our ability to know
        // how large the 'parent' region is in which we are sorting, which so far
        // is elusive
        const UriPathMap map[] =
        {
            { "v1",     id_path_v1,             MCCOAP_URIPATH_NONE },
            { "api",    id_path_v1_api,         id_path_v1 },
            { "power",  id_path_v1_api_power,   id_path_v1_api },
            { "test",   id_path_v1_api_test,    id_path_v1_api },

            { "v2",     id_path_v2,             MCCOAP_URIPATH_NONE },
            { "api",    id_path_v2_api,         id_path_v2 }
        };

        UriPathMap2 map_root[] =
        {
            { "v1", id_path_v1 }
        };

        UriPathMap2 map_v1[] =
        {
            { "api", id_path_v1_api }
        };

        UriPathMap2 map_v1_api[] =
        {
            { "power", id_path_v1_api_power }
        };

        // first = parent
        // second = list of children
        // third = count of children
        triad<int, UriPathMap2*, int> relations[]
        {
            { MCCOAP_URIPATH_NONE,  map_root, 1 },
            { id_path_v1,           map_v1, 1 },
            { id_path_v1_api,       map_v1_api, 1 }
        };

        const UriPathMap* found = match(map, 3, "api", 0);

        REQUIRE(found != NULLPTR);
        REQUIRE(found->second == 1);

        // layer2 arrays are the size of a pointer, so we don't
        // need to go to lengths to shrink the size for UriPathMatcher2
        auto _map = estd::layer2::make_array(map);

        REQUIRE(sizeof(_map) == sizeof(void*));

        //estd::layer3::array<const UriPathMap> __map(map);
        // FIX: does not invoke move constructor like it should
        UriPathMatcher2<decltype(_map)> matcher(std::move(map));

        // TODO: Should be able to make a global vs instance version of UriPathMatcher2,
        // but would mean a non-stack version of 'map'

        // NOTE: this particular class doesn't modify matcher state
        // but it's confusing which ones do and which ones don't.  more fuel
        // for the fire of making a distinct stateful variant of the matcher class
        estd::optional<int> result = matcher.find("v1", MCCOAP_URIPATH_NONE);

        REQUIRE(result.has_value());
        REQUIRE(result.value() == id_path_v1);

        result = matcher.find("v1");

        REQUIRE(result);
        REQUIRE(*result == id_path_v1);

        result = matcher.find("api");

        REQUIRE(result);
        REQUIRE(*result == id_path_v1_api);

        result = matcher.find("power");

        REQUIRE(result);
        REQUIRE(*result == id_path_v1_api_power);

        struct sax_responder
        {
            int last_parent;
            int last_pos;
            int indent;

            sax_responder() :
                last_pos(MCCOAP_URIPATH_NONE),
                last_parent(MCCOAP_URIPATH_NONE),
                indent(0)
                {}

            void on_notify(const known_uri_event& e)
            {
                std::cout << "Known path: ";
                //std::cout << std::setfill(' ') << std::setw(indent);
                std::cout << std::setw(10) << e.path_map.first;
                std::cout << ", parent=" << e.path_map.third << std::endl;

                // second = current node id
                int current_id = e.path_map.second;
                int parent_id = e.path_map.third;
                last_pos = e.path_map.second;
                last_parent = parent_id;
            }
        };

        CoREData coredata[] =
        {
            { id_path_v1_api_power, "star-power", "switch" },
            { id_path_v1_api_test, "star-power", "sensor" },
            { id_path_v2_api, "dummy-path", "noop" }
        };

        //auto _coredata = estd::layer2::make_array(coredata);

        // foundational/poc for emitter of CoRE for /.well-known/core responder
        struct core_observer
        {
            // in non-proof of concept, this won't be inline with the observer
            estd::experimental::ostringstream<256> buf;

            // all uripath nodes which actually have CoRE data associated
            // with them
            // TODO: A map would be better instead of a layer3 array
            estd::layer3::array<CoREData, uint8_t> coredata;

            // breadcrumb tracker for hierarchical navigation of nodes
            estd::layer1::stack<const UriPathMap*, 10> parents;

            core_observer(estd::layer3::array<CoREData, uint8_t> coredata) :
                coredata(coredata) {}

            // NOTE: doing this via notify but perhaps could easily do a more straight
            // ahead sequential version
            void on_notify(const known_uri_event& e)
            {
                // 'top' aka the back/last/current parent

                // if the last parent id we are looking at doesn't match incoming
                // observed one, back it out until it does match the observed one
                while(!parents.empty() && parents.top()->second != e.parent_id())
                    parents.pop();

                // when we arrive here, we're either positioned in 'parents' at the
                // matching parent OR it's empty
                parents.push(&e.path_map);

                // TODO: Need a way to aggregate CoRE datasources here
                // and maybe some should be stateful vs the current semi-global
                const auto& result = std::find_if(coredata.begin(), coredata.end(),
                                            [&](const CoREData& value)
                {
                    return value.node == e.node_id();
                });

                // only spit out CoRE results for nodes with proper metadata.  Eventually
                // maybe we can auto-deduce based on some other clues reflecting that we
                // service a particular uri-path chain
                if(result != coredata.end())
                {
                    buf << '<';

                    // in atypical queue/stack usage we push to the back but evaluate (but not
                    // pop) the front/bottom.  This way we can tack on more and more uri's to reflect
                    // our hierarchy level, then pop them off as we leave
                    // NOTE: our layer1::stack can do this but the default stack cannot
                    for(const auto& parent_node : parents)
                        buf << '/' << parent_node->first;

                    buf << '>' << *result;

                    // TODO: We'll need to intelligently spit out a comma
                    // and NOT endl unless we specifically are in a debug mode
                    buf << estd::endl;
                }
            }
        };

        sax_responder observer;
        // TODO: fixup layer3::array so that it can copy between different size_t
        // variations of itself (especially upcasting to higher precision)
        core_observer observer2(estd::layer3::make_array(coredata));
        // this will make a subject with a reference to 'observer'
        auto subject = embr::layer1::make_subject(observer, observer2);
        matcher.notify(subject);

        const auto& underlying_string = observer2.buf.rdbuf()->str();

        std::cout << underlying_string;
        //REQUIRE(underlying_string == "v1\napi\npower\n");

        // match up incoming uri-path chunk
        // (in production we'd be tracking where we left off, so 'map_root'
        // wouldn't be hardcoded)
        int id = match(map_root, 1, "v1");

        if(id >= 0)
        {
            auto hit = match(relations, sizeof(relations), id);

            REQUIRE(hit);
            REQUIRE(hit->second == map_v1);
            //auto hit = std::find(relations, &relations[2], id);

            //REQUIRE(hit->second == map_v1);
        }

        struct test_factory
        {
            int key;

            test_factory(int key) : key(key) {}

            bool can_create(int key)
            {
                return this->key == key;
            }

            int create(int key)
            {
                return 5;
            }
        };

        //auto t = estd::make_tuple(1, 2, 3, 4);
        auto t = estd::make_tuple(test_factory(2), test_factory(1));
        moducom::coap::experimental::FactoryAggregator<int, decltype (t)&> fa(t);

        fa.create(1);

        SECTION("decoder interaction")
        {
            // NOTE: layer2 not what I expected (remembered).  layer2 for netbuf is preallocated
            // memory with a variable size parameter
            //embr::mem::layer2::NetBuf<sizeof(buffer_plausible)> netbuf(buffer_plausible);
            embr::mem::layer1::NetBuf<sizeof(buffer_plausible)> netbuf;

            memcpy(netbuf.data(), buffer_plausible, sizeof(buffer_plausible));

            typedef decltype(netbuf) netbuf_type;
            typedef decltype(netbuf)& netbuf_ref_type;

            // FIX: these fail still.  thought I had repaired it
            /*
            REQUIRE(NetBufDecoder<netbuf_type>::has_data_method<netbuf_type>::value);
            REQUIRE(NetBufDecoder<netbuf_ref_type>::has_data_method<
                    typename estd::remove_reference<netbuf_ref_type&>::type>::value);
            */
            //embr::s
            //NetBufDecoder<decltype(netbuf)&> decoder(netbuf);
        }
    }
}
<commit_msg>Slightly convoluted, but very functional link attribute handler<commit_after>#include <catch.hpp>

#include "exp/misc.h"

#include <embr/datapump.hpp>
#include <embr/observer.h>
#include <embr/netbuf-static.h>

#include <exp/retry.h>

#include <exp/message-observer.h>
#include "test-observer.h"

#include "exp/prototype/observer-idea1.h"

#include "coap/decoder/subject.hpp"
#if __cplusplus >= 201103L
#include "platform/generic/malloc_netbuf.h"
#endif

#include "exp/events.h"
#include <exp/uripath-repeater.h>

//#include <estd/map.h>
#include <estd/stack.h>
#include <estd/sstream.h>
#include <estd/internal/ostream_basic_string.hpp>

#include "test-data.h"

using namespace moducom::coap;
using namespace moducom::coap::experimental;

typedef moducom::pipeline::MemoryChunk::readonly_t ro_chunk_t;
typedef moducom::pipeline::MemoryChunk chunk_t;

template <class TStream>
struct ostream_event
{
#ifdef FEATURE_CPP_STATIC_ASSERT
    // TODO: assert that we really are getting an ostream here
#endif

    TStream& ostream;

    ostream_event(TStream& ostream) : ostream(ostream) {}
};

template <class TStream>
///
/// \brief Event for evaluating a well-known CoRE request against a particular service node
///
/// In particular this event is used for producing specialized output for the distinct URI node
/// reported in the CoRE response (i.e. you can use ostream to spit out ';title="something"' or
/// similar
///
struct node_core_event : ostream_event<TStream>
{
    const int node_id;
    typedef ostream_event<TStream> base_type;

    node_core_event(int node_id, TStream& ostream) :
        base_type(ostream),
        node_id(node_id)
    {}
};

struct title_tacker
{
    // FIX: May be slight abuse because events are supposed to be read only,
    // but this ostream use isn't quite that.  Works, though
    template <class TStream>
    void on_notify(const node_core_event<TStream>& e)
    {
        e.ostream << ";title=\"test\"";
    }
};

TEST_CASE("experimental 2 tests")
{
    typedef uint32_t addr_t;

#ifdef FEATURE_CPP_VARIADIC
    SECTION("AggregateMessageObserver")
    {
        moducom::pipeline::layer1::MemoryChunk<256> chunk;

        ObserverContext ctx(chunk);
        AggregateMessageObserver<ObserverContext,
                Buffer16BitDeltaObserver<ObserverContext>,
                EmptyObserver<ObserverContext>
                > amo(ctx);

        Header test_header(Header::Confirmable);
        //moducom::coap::layer1::Token token = ;
        uint8_t raw_token[] = { 0x45, 0x67 };

        test_header.token_length(sizeof(raw_token));
        test_header.message_id(0x0123);

        amo.on_header(test_header);
        //amo.on_token(raw_token); // not doing this only because Buffer16BitDeltaObserver hates it
        amo.on_option((moducom::coap::Option::Numbers) 270, 1);
    }
#endif
    SECTION("prototype observer idea1")
    {
        using namespace ::experimental::prototype::idea1;

#ifdef FEATURE_CPP_LAMBDA
        DecoderObserver test_target1([]()
        {
            // eventually activated when v1/target1 get is issued
        });
#endif

        URI uri[] =
        {
#if defined(FEATURE_CPP_MOVESEMANTIC) && defined(FEATURE_CPP_LAMBDA)
            URI("v1",
            {
                URI("target1", test_target1, true),
                URI("target2", [](IncomingContext<int>& ctx)
                {
                    // eventually activated when v2/target2 get is issued
                })
            }),
#endif
            URI("v2", 0, 2)
        };

        IncomingContext<int> ctx;

        decoder_observer(DecoderObserver(uri), ctx, buffer_16bit_delta);
    }
    SECTION("RandomPolicy test")
    {
        int value;

        for(int i = 0; i < 10; i++)
        {
            value = RandomPolicy::rand(100, 200);

            REQUIRE(value >= 100);
            REQUIRE(value <= 200);
        }
    }
    SECTION("uripath repeater")
    {
        moducom::coap::experimental::UriPathRepeater<embr::void_subject> upr;
    }
    SECTION("factory test")
    {
        constexpr int id_path_v1 = 0;
        constexpr int id_path_v1_api = 1;
        constexpr int id_path_v1_api_power = 2;
        constexpr int id_path_v1_api_test = 6;
        constexpr int id_path_dummy = 3;
        constexpr int id_path_v2 = 4;
        constexpr int id_path_v2_api = 5;

        // sort by parent id first, then by node id
        // this way we can easily optimize incoming request parsing by remembering
        // where we left off on found node id position
        // NOTE: might be better to sort by uri_path secondly instead of node_id,
        // as it potentially could speed up searching for said path.  However,
        // any of the secondary sorting the benefit is limited by our ability to know
        // how large the 'parent' region is in which we are sorting, which so far
        // is elusive
        const UriPathMap map[] =
        {
            { "v1",     id_path_v1,             MCCOAP_URIPATH_NONE },
            { "api",    id_path_v1_api,         id_path_v1 },
            { "power",  id_path_v1_api_power,   id_path_v1_api },
            { "test",   id_path_v1_api_test,    id_path_v1_api },

            { "v2",     id_path_v2,             MCCOAP_URIPATH_NONE },
            { "api",    id_path_v2_api,         id_path_v2 }
        };

        UriPathMap2 map_root[] =
        {
            { "v1", id_path_v1 }
        };

        UriPathMap2 map_v1[] =
        {
            { "api", id_path_v1_api }
        };

        UriPathMap2 map_v1_api[] =
        {
            { "power", id_path_v1_api_power }
        };

        // first = parent
        // second = list of children
        // third = count of children
        triad<int, UriPathMap2*, int> relations[]
        {
            { MCCOAP_URIPATH_NONE,  map_root, 1 },
            { id_path_v1,           map_v1, 1 },
            { id_path_v1_api,       map_v1_api, 1 }
        };

        const UriPathMap* found = match(map, 3, "api", 0);

        REQUIRE(found != NULLPTR);
        REQUIRE(found->second == 1);

        // layer2 arrays are the size of a pointer, so we don't
        // need to go to lengths to shrink the size for UriPathMatcher2
        auto _map = estd::layer2::make_array(map);

        REQUIRE(sizeof(_map) == sizeof(void*));

        //estd::layer3::array<const UriPathMap> __map(map);
        // FIX: does not invoke move constructor like it should
        UriPathMatcher2<decltype(_map)> matcher(std::move(map));

        // TODO: Should be able to make a global vs instance version of UriPathMatcher2,
        // but would mean a non-stack version of 'map'

        // NOTE: this particular class doesn't modify matcher state
        // but it's confusing which ones do and which ones don't.  more fuel
        // for the fire of making a distinct stateful variant of the matcher class
        estd::optional<int> result = matcher.find("v1", MCCOAP_URIPATH_NONE);

        REQUIRE(result.has_value());
        REQUIRE(result.value() == id_path_v1);

        result = matcher.find("v1");

        REQUIRE(result);
        REQUIRE(*result == id_path_v1);

        result = matcher.find("api");

        REQUIRE(result);
        REQUIRE(*result == id_path_v1_api);

        result = matcher.find("power");

        REQUIRE(result);
        REQUIRE(*result == id_path_v1_api_power);

        struct sax_responder
        {
            int last_parent;
            int last_pos;
            int indent;

            sax_responder() :
                last_pos(MCCOAP_URIPATH_NONE),
                last_parent(MCCOAP_URIPATH_NONE),
                indent(0)
                {}

            void on_notify(const known_uri_event& e)
            {
                std::cout << "Known path: ";
                //std::cout << std::setfill(' ') << std::setw(indent);
                std::cout << std::setw(10) << e.path_map.first;
                std::cout << ", parent=" << e.path_map.third << std::endl;

                // second = current node id
                int current_id = e.path_map.second;
                int parent_id = e.path_map.third;
                last_pos = e.path_map.second;
                last_parent = parent_id;
            }
        };

        CoREData coredata[] =
        {
            { id_path_v1_api_power, "star-power", "switch" },
            { id_path_v1_api_test, "star-power", "sensor" },
            { id_path_v2_api, "dummy-path", "noop" }
        };

        //auto _coredata = estd::layer2::make_array(coredata);

        // foundational/poc for emitter of CoRE for /.well-known/core responder
        struct core_observer
        {
            embr::void_subject link_attribute_evaluator;

            typedef estd::experimental::ostringstream<256> ostream_type;

            // in non-proof of concept, this won't be inline with the observer
            ostream_type buf;

            // all uripath nodes which actually have CoRE data associated
            // with them
            // TODO: A map would be better instead of a layer3 array
            estd::layer3::array<CoREData, uint8_t> coredata;

            // breadcrumb tracker for hierarchical navigation of nodes
            estd::layer1::stack<const UriPathMap*, 10> parents;

            core_observer(estd::layer3::array<CoREData, uint8_t> coredata) :
                coredata(coredata) {}

            // NOTE: doing this via notify but perhaps could easily do a more straight
            // ahead sequential version
            void on_notify(const known_uri_event& e)
            {
                // 'top' aka the back/last/current parent

                // if the last parent id we are looking at doesn't match incoming
                // observed one, back it out until it does match the observed one
                while(!parents.empty() && parents.top()->second != e.parent_id())
                    parents.pop();

                // when we arrive here, we're either positioned in 'parents' at the
                // matching parent OR it's empty
                parents.push(&e.path_map);

                // TODO: Need a way to aggregate CoRE datasources here
                // and maybe some should be stateful vs the current semi-global
                const auto& result = std::find_if(coredata.begin(), coredata.end(),
                                            [&](const CoREData& value)
                {
                    return value.node == e.node_id();
                });

                // only spit out CoRE results for nodes with proper metadata.  Eventually
                // maybe we can auto-deduce based on some other clues reflecting that we
                // service a particular uri-path chain
                if(result != coredata.end())
                {
                    buf << '<';

                    // in atypical queue/stack usage we push to the back but evaluate (but not
                    // pop) the front/bottom.  This way we can tack on more and more uri's to reflect
                    // our hierarchy level, then pop them off as we leave
                    // NOTE: our layer1::stack can do this but the default stack cannot
                    for(const auto& parent_node : parents)
                        buf << '/' << parent_node->first;

                    buf << '>' << *result;

                    // tack on other link attributes
                    node_core_event<ostream_type> _e(result->node, buf);
                    link_attribute_evaluator.notify(_e);

                    auto link_attribute_evaluator2 = embr::layer1::make_subject(title_tacker());
                    link_attribute_evaluator2.notify(_e);

                    // TODO: We'll need to intelligently spit out a comma
                    // and NOT endl unless we specifically are in a debug mode
                    buf << estd::endl;
                }
            }
        };

        sax_responder observer;
        // TODO: fixup layer3::array so that it can copy between different size_t
        // variations of itself (especially upcasting to higher precision)
        core_observer observer2(estd::layer3::make_array(coredata));
        // this will make a subject with a reference to 'observer'
        auto subject = embr::layer1::make_subject(observer, observer2);
        matcher.notify(subject);

        const auto& underlying_string = observer2.buf.rdbuf()->str();

        std::cout << underlying_string;
        //REQUIRE(underlying_string == "v1\napi\npower\n");

        // match up incoming uri-path chunk
        // (in production we'd be tracking where we left off, so 'map_root'
        // wouldn't be hardcoded)
        int id = match(map_root, 1, "v1");

        if(id >= 0)
        {
            auto hit = match(relations, sizeof(relations), id);

            REQUIRE(hit);
            REQUIRE(hit->second == map_v1);
            //auto hit = std::find(relations, &relations[2], id);

            //REQUIRE(hit->second == map_v1);
        }

        struct test_factory
        {
            int key;

            test_factory(int key) : key(key) {}

            bool can_create(int key)
            {
                return this->key == key;
            }

            int create(int key)
            {
                return 5;
            }
        };

        //auto t = estd::make_tuple(1, 2, 3, 4);
        auto t = estd::make_tuple(test_factory(2), test_factory(1));
        moducom::coap::experimental::FactoryAggregator<int, decltype (t)&> fa(t);

        fa.create(1);

        SECTION("decoder interaction")
        {
            // NOTE: layer2 not what I expected (remembered).  layer2 for netbuf is preallocated
            // memory with a variable size parameter
            //embr::mem::layer2::NetBuf<sizeof(buffer_plausible)> netbuf(buffer_plausible);
            embr::mem::layer1::NetBuf<sizeof(buffer_plausible)> netbuf;

            memcpy(netbuf.data(), buffer_plausible, sizeof(buffer_plausible));

            typedef decltype(netbuf) netbuf_type;
            typedef decltype(netbuf)& netbuf_ref_type;

            // FIX: these fail still.  thought I had repaired it
            /*
            REQUIRE(NetBufDecoder<netbuf_type>::has_data_method<netbuf_type>::value);
            REQUIRE(NetBufDecoder<netbuf_ref_type>::has_data_method<
                    typename estd::remove_reference<netbuf_ref_type&>::type>::value);
            */
            //embr::s
            //NetBufDecoder<decltype(netbuf)&> decoder(netbuf);
        }
    }
}
<|endoftext|>