<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/utilities/CDirEntry.cpp,v $
   $Revision: 1.1 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/05/12 19:04:36 $
   End CVS Header */

#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <direct.h>

#ifdef WIN32
# define stat _stat
# define S_IFREG _S_IFREG
# define S_IFDIR _S_IFDIR
# define access _access
# define mkdir _mkdir
# define rmdir _rmdir
#else
#endif

#include "copasi.h"

#include "CDirEntry.h"

bool CDirEntry::isFile(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

  return ((st.st_mode | S_IFREG) != 0);
}

bool CDirEntry::isDir(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

  return ((st.st_mode | S_IFDIR) != 0);
}

bool CDirEntry::exist(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

  return ((st.st_mode | S_IFREG) || (st.st_mode | S_IFDIR));
}

bool CDirEntry::isReadable(const std::string & path)
{return (access(path.c_str(), 0x4) == 0);}

bool CDirEntry::isWritable(const std::string & path)
{return (access(path.c_str(), 0x2) == 0);}

bool CDirEntry::createDir(const std::string & dir,
                          const std::string & parent)
{
  std::string Separator;
#ifdef WIN32
  Separator = "\\";
#else
  Separator = "/";
#endif

  std::string Dir;
  if (parent != "") Dir = parent + Separator;
  Dir += dir;

  // Check whether the directory already exists and is writable.
  if (isDir(Dir) && isWritable(Dir)) return true;

  // Check whether the parent directory exists and is writable.
  if (!isDir(parent) || !isWritable(parent)) return false;

  return (mkdir(Dir.c_str()) == 0);
}

bool CDirEntry::remove(const std::string & path)
{
  if (isDir(path))
    return (rmdir(path.c_str()) == 0);
  else if (isFile(path))
    return (::remove(path.c_str()) == 0);

  return false;
}

bool CDirEntry::removeFiles(const std::string & pattern,
                            const std::string & path)
{
  // :TODO:
#ifdef XXXX
#ifdef WIN32

  // Append to the "path" mask for all files in directory
  string pattern = path_base + string("*");

  bool skip_recursive_entry;

  // Open directory stream and try read info about first entry
  struct _finddata_t entry;
  long desc = _findfirst(pattern.c_str(), &entry);
  if (desc != -1)
    {
      skip_recursive_entry = (mode == eIgnoreRecursive) &&
                             ((::strcmp(entry.name, ".") == 0) ||
                              (::strcmp(entry.name, "..") == 0));
      // check all masks
      if (!skip_recursive_entry)
        {
          ITERATE(vector<string>, it, masks)
          {
            const string& mask = *it;
            if (mask.empty() ||
                 MatchesMask(entry.name, mask.c_str(), use_case))
              {
                s_AddDirEntry(contents, path_base + entry.name);
                break;
              }
          } // ITERATE
        }

      while (_findnext(desc, &entry) != -1)
        {
          if ((mode == eIgnoreRecursive) &&
               ((::strcmp(entry.name, ".") == 0) ||
                (::strcmp(entry.name, "..") == 0)))
            {
              continue;
            }
          ITERATE(vector<string>, it, masks)
          {
            const string& mask = *it;
            if (mask.empty() ||
                 MatchesMask(entry.name, mask.c_str(), use_case))
              {
                s_AddDirEntry(contents, path_base + entry.name);
                break;
              }
          } // ITERATE
        }
      _findclose(desc);
    }

#else
  DIR* dir = opendir(GetPath().c_str());
  if (dir)
    {
      while (struct dirent* entry = readdir(dir))
        {
          if ((mode == eIgnoreRecursive) &&
               ((::strcmp(entry->d_name, ".") == 0) ||
                (::strcmp(entry->d_name, "..") == 0)))
            {
              continue;
            }
          ITERATE(vector<string>, it, masks)
          {
            const string& mask = *it;
            if (mask.empty() ||
                 MatchesMask(entry->d_name, mask.c_str(), use_case))
              {
                s_AddDirEntry(contents, path_base + entry->d_name);
                break;
              }
          } // ITERATE
        } // while
      closedir(dir);
    }
#endif // WIN32
#endif // XXXX
  return false;
}
<commit_msg>Works now under WIN32.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/utilities/CDirEntry.cpp,v $
   $Revision: 1.2 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/05/13 13:15:52 $
   End CVS Header */

#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>

#ifdef WIN32
# include <direct.h>
# define stat _stat
# define S_IFREG _S_IFREG
# define S_IFDIR _S_IFDIR
# define access _access
# define mkdir _mkdir
# define rmdir _rmdir
#else
# include <dirent.h>
# include <unistd.h>
#endif // WIN32

#include "copasi.h"

#include "CDirEntry.h"

bool CDirEntry::isFile(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

#ifdef WIN32
  return ((st.st_mode & S_IFREG) == S_IFREG);
#else
  return S_ISREG(st.st_mode);
#endif
}

bool CDirEntry::isDir(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

#ifdef WIN32
  return ((st.st_mode & S_IFDIR) == S_IFDIR);
#else
  return S_ISDIR(st.st_mode);
#endif
}

bool CDirEntry::exist(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

#ifdef WIN32
  return ((st.st_mode & S_IFREG) == S_IFREG ||
          (st.st_mode & S_IFDIR) == S_IFDIR);
#else
  return (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode));
#endif
}

bool CDirEntry::isReadable(const std::string & path)
{return (access(path.c_str(), 0x4) == 0);}

bool CDirEntry::isWritable(const std::string & path)
{return (access(path.c_str(), 0x2) == 0);}

bool CDirEntry::createDir(const std::string & dir,
                          const std::string & parent)
{
  std::string Separator;
#ifdef WIN32
  Separator = "\\";
#else
  Separator = "/";
#endif

  std::string Dir;
  if (parent != "") Dir = parent + Separator;
  Dir += dir;

  // Check whether the directory already exists and is writable.
  if (isDir(Dir) && isWritable(Dir)) return true;

  // Check whether the parent directory exists and is writable.
  if (!isDir(parent) || !isWritable(parent)) return false;

  return (mkdir(Dir.c_str()) == 0);
}

bool CDirEntry::remove(const std::string & path)
{
  if (isDir(path))
    return (rmdir(path.c_str()) == 0);
  else if (isFile(path))
    return (::remove(path.c_str()) == 0);

  return false;
}

bool CDirEntry::removeFiles(const std::string & pattern,
                            const std::string & path)
{
  bool success = true;

  // :TODO:
#ifdef WIN32

  // Append to the "path" mask for all files in directory
  std::string FilePattern = path + "\\" + pattern;

  // Open directory stream and try read info about first entry
  struct _finddata_t Entry;
  C_INT32 hList = _findfirst(FilePattern.c_str(), &Entry);

  if (hList == -1) return success;

  if (Entry.attrib | _A_NORMAL)
  {if (::remove((path + "\\" + Entry.name).c_str()) != 0) success = false;}
  else
  {if (rmdir((path + "\\" + Entry.name).c_str()) != 0) success = false;}

  while (_findnext(hList, &Entry) == 0)
    if (Entry.attrib | _A_NORMAL)
    {if (::remove((path + "\\" + Entry.name).c_str()) != 0) success = false;}
    else
    {if (rmdir((path + "\\" + Entry.name).c_str()) != 0) success = false;}

  _findclose(hList);

#else

  DIR * pDir = opendir(path.c_str());
  if (!pDir) return false;

  struct dirent * pEntry;

  while (pEntry = readdir(dir))
    {
      // Match pattern.

      if (pEntry->d_type == DT_DIR)
      {if (rmdir((path + "/" + pEntry.d_name).c_str()) != 0) success = false;}
      else
      {if (::remove((path + "/" + pEntry.d_name).c_str()) != 0) success = false;}

      pEntry = readdir(dir);
    }

  closedir(dir);

#endif // WIN32

  return success;
}
<|endoftext|>


<commit_before>#include <iossteam>

#include <queue>
#include <utility>

typedef pair<int,int> node;

int re[1000000]
int main(int argc, char const *argv[])
{
	priority_queue<node> pq;

	pq.push(make_pair(1,2));
	node n;
	while(1){

		node n=pq.front();

		pq.pop();

		switch(n.second){
			case 2:
				pq.push(make_pair(n.first*2,3));
			break;
			case 3:
				pq.push(make_pair(n.first*3,5);
			break;
			case 5:
				pq.push(make_pair(n.first*5,0));
			break;
		}

	}
	return 0;
}<commit_msg>update 346588<commit_after>#include <iossteam>

#include <queue>
#include <utility>

typedef pair<int,int> node;

int re[1000000];
int main(int argc, char const *argv[])
{
	priority_queue<node> pq;

	pq.push(make_pair(1,2));
	node n;
	while(1){

		node n=pq.front();

		pq.pop();

		switch(n.second){
			case 2:
				pq.push(make_pair(n.first*2,3));
			break;
			case 3:
				pq.push(make_pair(n.first*3,5);
			break;
			case 5:
				pq.push(make_pair(n.first*5,0));
			break;
		}

	}
	return 0;
}<|endoftext|>


<commit_before>#ifndef WRAP_BARRIER_CAV_H
#define WRAP_BARRIER_CAV_H

#include "Python.h"

#ifdef __cplusplus
extern "C"
{
#endif

  namespace wrap_rfcavities
  {
    void initBarrier_Cav(PyObject* module);
  }

#ifdef __cplusplus
}
#endif  // __cplusplus

#endif // WRAP_HARMONIC_CAV_H
<commit_msg>Jeff Holmes<commit_after>#ifndef WRAP_BARRIER_CAV_H
#define WRAP_BARRIER_CAV_H

#include "Python.h"

#ifdef __cplusplus
extern "C"
{
#endif

  namespace wrap_rfcavities
  {
    void initBarrier_Cav(PyObject* module);
  }

#ifdef __cplusplus
}
#endif  // __cplusplus

#endif // WRAP_BARRIER_CAV_H
<|endoftext|>


<commit_before>/* -*- Mode: C++; eval:(c-set-style "bsd"); tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

#include "baside2.hxx"
#include "linenumberwindow.hxx"

#include <svtools/xtextedt.hxx>
#include <svtools/textview.hxx>

LineNumberWindow::LineNumberWindow( Window* pParent, ModulWindow* pModulWin ) :
    Window( pParent, WB_BORDER ),
    m_pModulWindow(pModulWin),
    m_nCurYOffset(0)
{
    SetBackground(Wallpaper(GetSettings().GetStyleSettings().GetFieldColor()));
    m_nBaseWidth = GetTextWidth(String('8'));
    m_nWidth = m_nBaseWidth * 3 + m_nBaseWidth / 2;
}

LineNumberWindow::~LineNumberWindow() { }

void LineNumberWindow::Paint( const Rectangle& )
{
    if(SyncYOffset())
        return;

    ExtTextEngine* txtEngine = m_pModulWindow->GetEditEngine();
    if(!txtEngine)
        return;

    TextView* txtView = m_pModulWindow->GetEditView();
    if(!txtView)
        return;

    GetParent()->Resize();

    int windowHeight = GetOutputSize().Height();
    int nLineHeight = GetTextHeight();

    int startY = txtView->GetStartDocPos().Y();
    int nStartLine = startY / nLineHeight + 1;
    int nEndLine = (startY + windowHeight) / nLineHeight + 1;

    if(txtEngine->GetParagraphCount() + 1 < (unsigned int)nEndLine)
        nEndLine = txtEngine->GetParagraphCount() + 1;

    // FIXME: it would be best if we could get notified of a font change
    // rather than doing that re-calculation at each Paint event
    m_nBaseWidth = GetTextWidth(String('8'));

    // reserve enough for 3 sigit minimum, with a bit to spare for confort
    m_nWidth = m_nBaseWidth * 3 + m_nBaseWidth / 2;
    int i = (nEndLine + 1) / 1000;
    while(i)
    {
        i /= 10;
        m_nWidth += m_nBaseWidth;
    }

    sal_Int64 y = (nStartLine - 1) * nLineHeight;
    for(int i = nStartLine; i <= nEndLine; ++i, y += nLineHeight)
        DrawText(Point(0, y - m_nCurYOffset), String::CreateFromInt32(i));
}

void LineNumberWindow::DataChanged(DataChangedEvent const & rDCEvt)
{
    Window::DataChanged(rDCEvt);
    if (rDCEvt.GetType() == DATACHANGED_SETTINGS
        && (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
    {
        Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
        if (aColor != rDCEvt.GetOldSettings()->GetStyleSettings().GetFieldColor())
        {
            SetBackground(Wallpaper(aColor));
            Invalidate();
        }
    }
}

void LineNumberWindow::DoScroll(long nHorzScroll, long nVertScroll)
{
    m_nCurYOffset -= nVertScroll;
    Window::Scroll(nHorzScroll, nVertScroll);
}

long& LineNumberWindow::GetCurYOffset()
{
    return m_nCurYOffset;
}

bool LineNumberWindow::SyncYOffset()
{
    TextView* pView = m_pModulWindow->GetEditView();
    if (!pView)
        return false;

    long nViewYOffset = pView->GetStartDocPos().Y();
    if (m_nCurYOffset == nViewYOffset)
        return false;

    m_nCurYOffset = nViewYOffset;
    Invalidate();
    return true;
}

int LineNumberWindow::GetWidth()
{
    return m_nWidth;
}
<commit_msg>-Werror=shadow fix<commit_after>/* -*- Mode: C++; eval:(c-set-style "bsd"); tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

#include "baside2.hxx"
#include "linenumberwindow.hxx"

#include <svtools/xtextedt.hxx>
#include <svtools/textview.hxx>

LineNumberWindow::LineNumberWindow( Window* pParent, ModulWindow* pModulWin ) :
    Window( pParent, WB_BORDER ),
    m_pModulWindow(pModulWin),
    m_nCurYOffset(0)
{
    SetBackground(Wallpaper(GetSettings().GetStyleSettings().GetFieldColor()));
    m_nBaseWidth = GetTextWidth(String('8'));
    m_nWidth = m_nBaseWidth * 3 + m_nBaseWidth / 2;
}

LineNumberWindow::~LineNumberWindow() { }

void LineNumberWindow::Paint( const Rectangle& )
{
    if(SyncYOffset())
        return;

    ExtTextEngine* txtEngine = m_pModulWindow->GetEditEngine();
    if(!txtEngine)
        return;

    TextView* txtView = m_pModulWindow->GetEditView();
    if(!txtView)
        return;

    GetParent()->Resize();

    int windowHeight = GetOutputSize().Height();
    int nLineHeight = GetTextHeight();

    int startY = txtView->GetStartDocPos().Y();
    int nStartLine = startY / nLineHeight + 1;
    int nEndLine = (startY + windowHeight) / nLineHeight + 1;

    if(txtEngine->GetParagraphCount() + 1 < (unsigned int)nEndLine)
        nEndLine = txtEngine->GetParagraphCount() + 1;

    // FIXME: it would be best if we could get notified of a font change
    // rather than doing that re-calculation at each Paint event
    m_nBaseWidth = GetTextWidth(String('8'));

    // reserve enough for 3 sigit minimum, with a bit to spare for confort
    m_nWidth = m_nBaseWidth * 3 + m_nBaseWidth / 2;
    int i = (nEndLine + 1) / 1000;
    while(i)
    {
        i /= 10;
        m_nWidth += m_nBaseWidth;
    }

    sal_Int64 y = (nStartLine - 1) * nLineHeight;
    for(int n = nStartLine; n <= nEndLine; ++n, y += nLineHeight)
        DrawText(Point(0, y - m_nCurYOffset), String::CreateFromInt32(n));
}

void LineNumberWindow::DataChanged(DataChangedEvent const & rDCEvt)
{
    Window::DataChanged(rDCEvt);
    if (rDCEvt.GetType() == DATACHANGED_SETTINGS
        && (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
    {
        Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
        if (aColor != rDCEvt.GetOldSettings()->GetStyleSettings().GetFieldColor())
        {
            SetBackground(Wallpaper(aColor));
            Invalidate();
        }
    }
}

void LineNumberWindow::DoScroll(long nHorzScroll, long nVertScroll)
{
    m_nCurYOffset -= nVertScroll;
    Window::Scroll(nHorzScroll, nVertScroll);
}

long& LineNumberWindow::GetCurYOffset()
{
    return m_nCurYOffset;
}

bool LineNumberWindow::SyncYOffset()
{
    TextView* pView = m_pModulWindow->GetEditView();
    if (!pView)
        return false;

    long nViewYOffset = pView->GetStartDocPos().Y();
    if (m_nCurYOffset == nViewYOffset)
        return false;

    m_nCurYOffset = nViewYOffset;
    Invalidate();
    return true;
}

int LineNumberWindow::GetWidth()
{
    return m_nWidth;
}
<|endoftext|>


<commit_before>#include "appcache.h"

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(appcache_tests)

BOOST_AUTO_TEST_CASE(appcache_WrittenCacheShouldBeReadable)
{
    WriteCache("section", "key", "hello", 123456789);
    BOOST_CHECK(ReadCache("section", "key").value == "hello");
}

BOOST_AUTO_TEST_CASE(appcache_ClearCacheShouldClearEntireSection)
{
    WriteCache("section", "key1", "hello", 123456789);
    WriteCache("section", "key2", "hello", 123456789);
    ClearCache("section");
    BOOST_CHECK(ReadCache("section", "key1").value.empty() == true);
    BOOST_CHECK(ReadCache("section", "key2").value.empty() == true);
    DeleteCache("section","key1");
    DeleteCache("section","key2");
}

BOOST_AUTO_TEST_CASE(appcache_KeyShouldBeEmptyAfterDeleteCache)
{
    WriteCache("section", "key", "hello", 123456789);
    DeleteCache("section", "key");
    BOOST_CHECK(ReadCache("section", "key").value.empty() == true);
    BOOST_CHECK_EQUAL(GetCountOf("section"),0);
}

BOOST_AUTO_TEST_CASE(appcache_GetCountOfShouldCountEntries)
{
   WriteCache("section", "key1", "hello", 123456789);
   WriteCache("section", "key2", "hello", 123456789);
   WriteCache("section", "key3", "hello", 123456789);
   BOOST_CHECK_EQUAL(GetCountOf("section"), 3);
}

BOOST_AUTO_TEST_CASE(appcache_GetListOfBeaconShouldIgnoreInvestors)
{

   WriteCache("beacon", "CPID1", "INVESTOR", 12345);
   BOOST_CHECK(GetListOf("beacon").empty() == true);

   WriteCache("beacon", "CPID2", "abc123", 12345);
   BOOST_CHECK(GetListOf("beacon").empty() == false);
   BOOST_CHECK(GetListOf("beacon").find("abc123") != std::string::npos);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Clear cache sections before testing.<commit_after>#include "appcache.h"

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(appcache_tests)

BOOST_AUTO_TEST_CASE(appcache_WrittenCacheShouldBeReadable)
{
    ClearCache("section");
    WriteCache("section", "key", "hello", 123456789);
    BOOST_CHECK(ReadCache("section", "key").value == "hello");
}

BOOST_AUTO_TEST_CASE(appcache_ClearCacheShouldClearEntireSection)
{
    ClearCache("section");
    WriteCache("section", "key1", "hello", 123456789);
    WriteCache("section", "key2", "hello", 123456789);
    ClearCache("section");
    BOOST_CHECK(ReadCache("section", "key1").value.empty() == true);
    BOOST_CHECK(ReadCache("section", "key2").value.empty() == true);
}

BOOST_AUTO_TEST_CASE(appcache_KeyShouldBeEmptyAfterDeleteCache)
{
    ClearCache("section");
    WriteCache("section", "key", "hello", 123456789);
    DeleteCache("section", "key");
    BOOST_CHECK(ReadCache("section", "key").value.empty() == true);
    BOOST_CHECK_EQUAL(GetCountOf("section"),0);
}

BOOST_AUTO_TEST_CASE(appcache_GetCountOfShouldCountEntries)
{
    ClearCache("section");
    WriteCache("section", "key1", "hello", 123456789);
    WriteCache("section", "key2", "hello", 123456789);
    WriteCache("section", "key3", "hello", 123456789);
    BOOST_CHECK_EQUAL(GetCountOf("section"), 3);
}

BOOST_AUTO_TEST_CASE(appcache_GetListOfBeaconShouldIgnoreInvestors)
{
    ClearCache("beacon");
    WriteCache("beacon", "CPID1", "INVESTOR", 12345);
    BOOST_CHECK(GetListOf("beacon").empty() == true);

    WriteCache("beacon", "CPID2", "abc123", 12345);
    BOOST_CHECK(GetListOf("beacon").empty() == false);
    BOOST_CHECK(GetListOf("beacon").find("abc123") != std::string::npos);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2017-2018 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "DebugMessageView.h"
#include <QAction>
#include <QMenu>
#include "Code/QRDUtils.h"
#include "ui_DebugMessageView.h"

static const int EIDRole = Qt::UserRole + 1;

class DebugMessageItemModel : public QAbstractItemModel
{
public:
  DebugMessageItemModel(ICaptureContext &ctx, QObject *parent)
      : QAbstractItemModel(parent), m_Ctx(ctx)
  {
  }

  void refresh()
  {
    emit beginResetModel();
    emit endResetModel();
  }

  QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
  {
    if(row < 0 || row >= rowCount())
      return QModelIndex();

    return createIndex(row, column);
  }

  QModelIndex parent(const QModelIndex &index) const override { return QModelIndex(); }
  int rowCount(const QModelIndex &parent = QModelIndex()) const override
  {
    return m_Ctx.DebugMessages().count();
  }
  int columnCount(const QModelIndex &parent = QModelIndex()) const override { return 6; }
  Qt::ItemFlags flags(const QModelIndex &index) const override
  {
    if(!index.isValid())
      return 0;

    return QAbstractItemModel::flags(index);
  }

  QVariant headerData(int section, Qt::Orientation orientation, int role) const override
  {
    if(orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
      switch(section)
      {
        case 0: return lit("EID");
        case 1: return lit("Source");
        case 2: return lit("Severity");
        case 3: return lit("Category");
        case 4: return lit("ID");
        case 5: return lit("Description");
        default: break;
      }
    }

    return QVariant();
  }

  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
  {
    if(index.isValid() && role == Qt::DisplayRole)
    {
      int row = index.row();
      int col = index.column();

      if(col >= 0 && col < columnCount() && row < rowCount())
      {
        const DebugMessage &msg = m_Ctx.DebugMessages()[row];

        switch(col)
        {
          case 0: return msg.eventId;
          case 1: return ToQStr(msg.source);
          case 2: return ToQStr(msg.severity);
          case 3: return ToQStr(msg.category);
          case 4: return msg.messageID;
          case 5: return msg.description;
          default: break;
        }
      }
    }

    if(index.isValid() && role == EIDRole && index.row() >= 0 &&
       index.row() < m_Ctx.DebugMessages().count())
      return m_Ctx.DebugMessages()[index.row()].eventId;

    return QVariant();
  }

private:
  ICaptureContext &m_Ctx;
};

class DebugMessageFilterModel : public QSortFilterProxyModel
{
public:
  DebugMessageFilterModel(ICaptureContext &ctx, QObject *parent)
      : QSortFilterProxyModel(parent), m_Ctx(ctx)
  {
  }

  typedef QPair<QPair<MessageSource, MessageCategory>, uint32_t> MessageType;
  static MessageType makeType(const DebugMessage &msg)
  {
    return qMakePair(qMakePair(msg.source, msg.category), msg.messageID);
  }

  QList<MessageSource> m_HiddenSources;
  QList<MessageCategory> m_HiddenCategories;
  QList<MessageSeverity> m_HiddenSeverities;
  QList<MessageType> m_HiddenTypes;

  bool showHidden = false;

  void refresh() { invalidateFilter(); }
  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
  {
    if(role == Qt::FontRole && !isVisibleRow(mapToSource(index).row()))
    {
      QFont font;
      font.setItalic(true);
      return font;
    }

    return QSortFilterProxyModel::data(index, role);
  }

protected:
  bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
  {
    if(showHidden)
      return true;

    return isVisibleRow(sourceRow);
  }

  bool isVisibleRow(int sourceRow) const
  {
    const DebugMessage &msg = m_Ctx.DebugMessages()[sourceRow];

    if(m_HiddenSources.contains(msg.source))
      return false;

    if(m_HiddenCategories.contains(msg.category))
      return false;

    if(m_HiddenSeverities.contains(msg.severity))
      return false;

    if(m_HiddenTypes.contains(makeType(msg)))
      return false;

    return true;
  }

  bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
  {
    const DebugMessage &leftMsg = m_Ctx.DebugMessages()[left.row()];
    const DebugMessage &rightMsg = m_Ctx.DebugMessages()[right.row()];

    if(leftMsg.eventId < rightMsg.eventId)
      return true;

    if(leftMsg.source < rightMsg.source)
      return true;

    if(leftMsg.severity < rightMsg.severity)
      return true;

    if(leftMsg.category < rightMsg.category)
      return true;

    if(leftMsg.messageID < rightMsg.messageID)
      return true;

    return strcmp(leftMsg.description.c_str(), rightMsg.description.c_str()) < 0;
  }

private:
  ICaptureContext &m_Ctx;
};

DebugMessageView::DebugMessageView(ICaptureContext &ctx, QWidget *parent)
    : QFrame(parent), ui(new Ui::DebugMessageView), m_Ctx(ctx)
{
  ui->setupUi(this);

  m_ItemModel = new DebugMessageItemModel(m_Ctx, this);
  m_FilterModel = new DebugMessageFilterModel(m_Ctx, this);

  m_FilterModel->setSourceModel(m_ItemModel);
  ui->messages->setModel(m_FilterModel);

  ui->messages->setContextMenuPolicy(Qt::CustomContextMenu);
  QObject::connect(ui->messages, &QWidget::customContextMenuRequested, this,
                   &DebugMessageView::messages_contextMenu);

  ui->messages->setFont(Formatter::PreferredFont());

  m_ContextMenu = new QMenu(this);

  m_ShowHidden = new QAction(tr("Show hidden rows"), this);
  m_ToggleSource = new QAction(QString(), this);
  m_ToggleSeverity = new QAction(QString(), this);
  m_ToggleCategory = new QAction(QString(), this);
  m_ToggleMessageType = new QAction(QString(), this);

  m_ShowHidden->setCheckable(true);

  m_ContextMenu->addAction(m_ShowHidden);
  m_ContextMenu->addSeparator();
  m_ContextMenu->addAction(m_ToggleSource);
  m_ContextMenu->addAction(m_ToggleSeverity);
  m_ContextMenu->addAction(m_ToggleCategory);
  m_ContextMenu->addAction(m_ToggleMessageType);

  QObject::connect(m_ShowHidden, &QAction::triggered, this, &DebugMessageView::messages_toggled);
  QObject::connect(m_ToggleSource, &QAction::triggered, this, &DebugMessageView::messages_toggled);
  QObject::connect(m_ToggleSeverity, &QAction::triggered, this, &DebugMessageView::messages_toggled);
  QObject::connect(m_ToggleCategory, &QAction::triggered, this, &DebugMessageView::messages_toggled);
  QObject::connect(m_ToggleMessageType, &QAction::triggered, this,
                   &DebugMessageView::messages_toggled);

  RefreshMessageList();

  m_Ctx.AddCaptureViewer(this);
}

DebugMessageView::~DebugMessageView()
{
  m_Ctx.BuiltinWindowClosed(this);

  m_Ctx.RemoveCaptureViewer(this);
  delete ui;
}

void DebugMessageView::OnCaptureClosed()
{
  m_FilterModel->showHidden = false;
  RefreshMessageList();
}

void DebugMessageView::OnCaptureLoaded()
{
  m_FilterModel->showHidden = false;
  RefreshMessageList();
}

void DebugMessageView::RefreshMessageList()
{
  m_ItemModel->refresh();

  ui->messages->resizeColumnsToContents();

  if(m_Ctx.UnreadMessageCount() > 0)
    setWindowTitle(tr("(%1) Errors and Warnings").arg(m_Ctx.UnreadMessageCount()));
  else
    setWindowTitle(tr("Errors and Warnings"));
}

void DebugMessageView::on_messages_doubleClicked(const QModelIndex &index)
{
  QVariant var = m_ItemModel->data(index, EIDRole);

  if(var.isValid())
  {
    uint32_t eid = var.toUInt();
    m_Ctx.SetEventID({}, eid, eid);
  }
}

void DebugMessageView::messages_toggled()
{
  QAction *action = qobject_cast<QAction *>(QObject::sender());

  if(action == m_ShowHidden)
  {
    m_FilterModel->showHidden = !m_FilterModel->showHidden;
    m_ShowHidden->setChecked(m_FilterModel->showHidden);
  }
  else if(action == m_ToggleSource)
  {
    if(m_FilterModel->m_HiddenSources.contains(m_ContextMessage.source))
      m_FilterModel->m_HiddenSources.removeOne(m_ContextMessage.source);
    else
      m_FilterModel->m_HiddenSources.push_back(m_ContextMessage.source);
  }
  else if(action == m_ToggleSeverity)
  {
    if(m_FilterModel->m_HiddenSeverities.contains(m_ContextMessage.severity))
      m_FilterModel->m_HiddenSeverities.removeOne(m_ContextMessage.severity);
    else
      m_FilterModel->m_HiddenSeverities.push_back(m_ContextMessage.severity);
  }
  else if(action == m_ToggleSeverity)
  {
    if(m_FilterModel->m_HiddenCategories.contains(m_ContextMessage.category))
      m_FilterModel->m_HiddenCategories.removeOne(m_ContextMessage.category);
    else
      m_FilterModel->m_HiddenCategories.push_back(m_ContextMessage.category);
  }
  else if(action == m_ToggleSeverity)
  {
    auto type = DebugMessageFilterModel::makeType(m_ContextMessage);
    if(m_FilterModel->m_HiddenTypes.contains(type))
      m_FilterModel->m_HiddenTypes.removeOne(type);
    else
      m_FilterModel->m_HiddenTypes.push_back(type);
  }

  m_FilterModel->refresh();
}

void DebugMessageView::messages_contextMenu(const QPoint &pos)
{
  if(!m_Ctx.IsCaptureLoaded())
    return;

  QModelIndex index = ui->messages->indexAt(pos);

  if(index.isValid())
  {
    index = m_FilterModel->mapToSource(index);

    const DebugMessage &msg = m_Ctx.DebugMessages()[index.row()];

    QString hide = tr("Hide");
    QString show = tr("Show");

    bool hidden = m_FilterModel->m_HiddenSources.contains(msg.source);
    m_ToggleSource->setText(tr("%1 Source: %2").arg(hidden ? show : hide).arg(ToQStr(msg.source)));

    hidden = m_FilterModel->m_HiddenSeverities.contains(msg.severity);
    m_ToggleSeverity->setText(
        tr("%1 Severity: %2").arg(hidden ? show : hide).arg(ToQStr(msg.severity)));

    hidden = m_FilterModel->m_HiddenCategories.contains(msg.category);
    m_ToggleCategory->setText(
        tr("%1 Category: %2").arg(hidden ? show : hide).arg(ToQStr(msg.category)));

    hidden = m_FilterModel->m_HiddenTypes.contains(DebugMessageFilterModel::makeType(msg));
    m_ToggleMessageType->setText(tr("%1 Message Type").arg(hidden ? show : hide));

    m_ContextMessage = msg;

    RDDialog::show(m_ContextMenu, ui->messages->viewport()->mapToGlobal(pos));
  }
}

void DebugMessageView::paintEvent(QPaintEvent *e)
{
  if(m_Ctx.UnreadMessageCount() > 0)
  {
    m_Ctx.MarkMessagesRead();
    RefreshMessageList();
  }

  QFrame::paintEvent(e);
}
<commit_msg>Enable sorting in debug messages<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2017-2018 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "DebugMessageView.h"
#include <QAction>
#include <QMenu>
#include "Code/QRDUtils.h"
#include "ui_DebugMessageView.h"

static const int EIDRole = Qt::UserRole + 1;
static const int SortDataRole = Qt::UserRole + 2;

class DebugMessageItemModel : public QAbstractItemModel
{
public:
  DebugMessageItemModel(ICaptureContext &ctx, QObject *parent)
      : QAbstractItemModel(parent), m_Ctx(ctx)
  {
  }

  void refresh()
  {
    emit beginResetModel();
    emit endResetModel();
  }

  QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
  {
    if(row < 0 || row >= rowCount())
      return QModelIndex();

    return createIndex(row, column);
  }

  QModelIndex parent(const QModelIndex &index) const override { return QModelIndex(); }
  int rowCount(const QModelIndex &parent = QModelIndex()) const override
  {
    return m_Ctx.DebugMessages().count();
  }
  int columnCount(const QModelIndex &parent = QModelIndex()) const override { return 6; }
  Qt::ItemFlags flags(const QModelIndex &index) const override
  {
    if(!index.isValid())
      return 0;

    return QAbstractItemModel::flags(index);
  }

  QVariant headerData(int section, Qt::Orientation orientation, int role) const override
  {
    if(orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
      switch(section)
      {
        case 0: return lit("EID");
        case 1: return lit("Source");
        case 2: return lit("Severity");
        case 3: return lit("Category");
        case 4: return lit("ID");
        case 5: return lit("Description");
        default: break;
      }
    }

    return QVariant();
  }

  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
  {
    if(index.isValid() && (role == Qt::DisplayRole || role == SortDataRole))
    {
      bool sort = (role == SortDataRole);

      int row = index.row();
      int col = index.column();

      if(col >= 0 && col < columnCount() && row < rowCount())
      {
        const DebugMessage &msg = m_Ctx.DebugMessages()[row];

        switch(col)
        {
          case 0: return msg.eventId;
          case 1: return ToQStr(msg.source);
          case 2: return sort ? QVariant((uint32_t)msg.severity) : QVariant(ToQStr(msg.severity));
          case 3: return ToQStr(msg.category);
          case 4: return msg.messageID;
          case 5: return msg.description;
          default: break;
        }
      }
    }

    if(index.isValid() && role == EIDRole && index.row() >= 0 &&
       index.row() < m_Ctx.DebugMessages().count())
      return m_Ctx.DebugMessages()[index.row()].eventId;

    return QVariant();
  }

private:
  ICaptureContext &m_Ctx;
};

class DebugMessageFilterModel : public QSortFilterProxyModel
{
public:
  DebugMessageFilterModel(ICaptureContext &ctx, QObject *parent)
      : QSortFilterProxyModel(parent), m_Ctx(ctx)
  {
  }

  typedef QPair<QPair<MessageSource, MessageCategory>, uint32_t> MessageType;
  static MessageType makeType(const DebugMessage &msg)
  {
    return qMakePair(qMakePair(msg.source, msg.category), msg.messageID);
  }

  QList<MessageSource> m_HiddenSources;
  QList<MessageCategory> m_HiddenCategories;
  QList<MessageSeverity> m_HiddenSeverities;
  QList<MessageType> m_HiddenTypes;

  bool showHidden = false;

  void refresh() { invalidateFilter(); }
  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
  {
    if(role == Qt::FontRole && !isVisibleRow(mapToSource(index).row()))
    {
      QFont font;
      font.setItalic(true);
      return font;
    }

    return QSortFilterProxyModel::data(index, role);
  }

protected:
  bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
  {
    if(showHidden)
      return true;

    return isVisibleRow(sourceRow);
  }

  bool isVisibleRow(int sourceRow) const
  {
    const DebugMessage &msg = m_Ctx.DebugMessages()[sourceRow];

    if(m_HiddenSources.contains(msg.source))
      return false;

    if(m_HiddenCategories.contains(msg.category))
      return false;

    if(m_HiddenSeverities.contains(msg.severity))
      return false;

    if(m_HiddenTypes.contains(makeType(msg)))
      return false;

    return true;
  }

  bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
  {
    return sourceModel()->data(left, SortDataRole) < sourceModel()->data(right, SortDataRole);
  }

private:
  ICaptureContext &m_Ctx;
};

DebugMessageView::DebugMessageView(ICaptureContext &ctx, QWidget *parent)
    : QFrame(parent), ui(new Ui::DebugMessageView), m_Ctx(ctx)
{
  ui->setupUi(this);

  m_ItemModel = new DebugMessageItemModel(m_Ctx, this);
  m_FilterModel = new DebugMessageFilterModel(m_Ctx, this);

  m_FilterModel->setSourceModel(m_ItemModel);
  ui->messages->setModel(m_FilterModel);

  ui->messages->setSortingEnabled(true);
  ui->messages->sortByColumn(0, Qt::AscendingOrder);

  ui->messages->setContextMenuPolicy(Qt::CustomContextMenu);
  QObject::connect(ui->messages, &QWidget::customContextMenuRequested, this,
                   &DebugMessageView::messages_contextMenu);

  ui->messages->setFont(Formatter::PreferredFont());

  m_ContextMenu = new QMenu(this);

  m_ShowHidden = new QAction(tr("Show hidden rows"), this);
  m_ToggleSource = new QAction(QString(), this);
  m_ToggleSeverity = new QAction(QString(), this);
  m_ToggleCategory = new QAction(QString(), this);
  m_ToggleMessageType = new QAction(QString(), this);

  m_ShowHidden->setCheckable(true);

  m_ContextMenu->addAction(m_ShowHidden);
  m_ContextMenu->addSeparator();
  m_ContextMenu->addAction(m_ToggleSource);
  m_ContextMenu->addAction(m_ToggleSeverity);
  m_ContextMenu->addAction(m_ToggleCategory);
  m_ContextMenu->addAction(m_ToggleMessageType);

  QObject::connect(m_ShowHidden, &QAction::triggered, this, &DebugMessageView::messages_toggled);
  QObject::connect(m_ToggleSource, &QAction::triggered, this, &DebugMessageView::messages_toggled);
  QObject::connect(m_ToggleSeverity, &QAction::triggered, this, &DebugMessageView::messages_toggled);
  QObject::connect(m_ToggleCategory, &QAction::triggered, this, &DebugMessageView::messages_toggled);
  QObject::connect(m_ToggleMessageType, &QAction::triggered, this,
                   &DebugMessageView::messages_toggled);

  RefreshMessageList();

  m_Ctx.AddCaptureViewer(this);
}

DebugMessageView::~DebugMessageView()
{
  m_Ctx.BuiltinWindowClosed(this);

  m_Ctx.RemoveCaptureViewer(this);
  delete ui;
}

void DebugMessageView::OnCaptureClosed()
{
  m_FilterModel->showHidden = false;
  RefreshMessageList();
}

void DebugMessageView::OnCaptureLoaded()
{
  m_FilterModel->showHidden = false;
  RefreshMessageList();
}

void DebugMessageView::RefreshMessageList()
{
  m_ItemModel->refresh();

  ui->messages->resizeColumnsToContents();

  if(m_Ctx.UnreadMessageCount() > 0)
    setWindowTitle(tr("(%1) Errors and Warnings").arg(m_Ctx.UnreadMessageCount()));
  else
    setWindowTitle(tr("Errors and Warnings"));
}

void DebugMessageView::on_messages_doubleClicked(const QModelIndex &index)
{
  QVariant var = m_FilterModel->data(index, EIDRole);

  if(var.isValid())
  {
    uint32_t eid = var.toUInt();
    m_Ctx.SetEventID({}, eid, eid);
  }
}

void DebugMessageView::messages_toggled()
{
  QAction *action = qobject_cast<QAction *>(QObject::sender());

  if(action == m_ShowHidden)
  {
    m_FilterModel->showHidden = !m_FilterModel->showHidden;
    m_ShowHidden->setChecked(m_FilterModel->showHidden);
  }
  else if(action == m_ToggleSource)
  {
    if(m_FilterModel->m_HiddenSources.contains(m_ContextMessage.source))
      m_FilterModel->m_HiddenSources.removeOne(m_ContextMessage.source);
    else
      m_FilterModel->m_HiddenSources.push_back(m_ContextMessage.source);
  }
  else if(action == m_ToggleSeverity)
  {
    if(m_FilterModel->m_HiddenSeverities.contains(m_ContextMessage.severity))
      m_FilterModel->m_HiddenSeverities.removeOne(m_ContextMessage.severity);
    else
      m_FilterModel->m_HiddenSeverities.push_back(m_ContextMessage.severity);
  }
  else if(action == m_ToggleSeverity)
  {
    if(m_FilterModel->m_HiddenCategories.contains(m_ContextMessage.category))
      m_FilterModel->m_HiddenCategories.removeOne(m_ContextMessage.category);
    else
      m_FilterModel->m_HiddenCategories.push_back(m_ContextMessage.category);
  }
  else if(action == m_ToggleSeverity)
  {
    auto type = DebugMessageFilterModel::makeType(m_ContextMessage);
    if(m_FilterModel->m_HiddenTypes.contains(type))
      m_FilterModel->m_HiddenTypes.removeOne(type);
    else
      m_FilterModel->m_HiddenTypes.push_back(type);
  }

  m_FilterModel->refresh();
}

void DebugMessageView::messages_contextMenu(const QPoint &pos)
{
  if(!m_Ctx.IsCaptureLoaded())
    return;

  QModelIndex index = ui->messages->indexAt(pos);

  if(index.isValid())
  {
    index = m_FilterModel->mapToSource(index);

    const DebugMessage &msg = m_Ctx.DebugMessages()[index.row()];

    QString hide = tr("Hide");
    QString show = tr("Show");

    bool hidden = m_FilterModel->m_HiddenSources.contains(msg.source);
    m_ToggleSource->setText(tr("%1 Source: %2").arg(hidden ? show : hide).arg(ToQStr(msg.source)));

    hidden = m_FilterModel->m_HiddenSeverities.contains(msg.severity);
    m_ToggleSeverity->setText(
        tr("%1 Severity: %2").arg(hidden ? show : hide).arg(ToQStr(msg.severity)));

    hidden = m_FilterModel->m_HiddenCategories.contains(msg.category);
    m_ToggleCategory->setText(
        tr("%1 Category: %2").arg(hidden ? show : hide).arg(ToQStr(msg.category)));

    hidden = m_FilterModel->m_HiddenTypes.contains(DebugMessageFilterModel::makeType(msg));
    m_ToggleMessageType->setText(tr("%1 Message Type").arg(hidden ? show : hide));

    m_ContextMessage = msg;

    RDDialog::show(m_ContextMenu, ui->messages->viewport()->mapToGlobal(pos));
  }
}

void DebugMessageView::paintEvent(QPaintEvent *e)
{
  if(m_Ctx.UnreadMessageCount() > 0)
  {
    m_Ctx.MarkMessagesRead();
    RefreshMessageList();
  }

  QFrame::paintEvent(e);
}
<|endoftext|>


<commit_before>#include <functional>
#include <iostream>
#include <vector>

#include "some_cipher.h"

std::vector<nibs> gen_keys() {
    std::vector<nibs> kss;
    for (int k5 = 0; k5 < 16; ++k5) {
    for (int k6 = 0; k6 < 16; ++k6) {
    for (int k7 = 0; k7 < 16; ++k7) {
    for (int k8 = 0; k8 < 16; ++k8) {
    for (int k9 = 0; k9 < 16; ++k9) {
    for (int k10 = 0; k10 < 16; ++k10) {
    for (int k11 = 0; k11 < 16; ++k11) {
        nibs ks{0};
        ks[5] = k5;
        ks[6] = k6;
        ks[7] = k7;
        ks[8] = k8;
        ks[9] = k9;
        ks[10] = k10;
        ks[11] = k11;
        kss.push_back(ks);
    }}}}}}}
    return kss;
}

int main() {
    // read the key
    nibs correct_ks;
    for (int i = 0; i < 12; ++i) std::cin >> correct_ks[i];

    // generate a list of all the keys
    std::vector<nibs> kss = gen_keys();
    std::cout << "Generated " << +kss.size() << " keys." << std::endl;

    // go through all the pairs

    std::function<nibs(nibs, nibs)> f = [](nibs ks, nibs cs) {
        return inv_roundf(ks, inv_roundf(ks, cs, 4), 3);
    };

    std::function<bool(nibs, nibs)> is_impossible = [](nibs ds0, nibs ds1) {
        return differences(ds0, ds1) == diffs {0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1};
    };

    while (std::cin) {
        nibs cs0, cs1;
        for (int i = 0; i < 12; ++i) std::cin >> cs0[i];
        for (int i = 0; i < 12; ++i) std::cin >> cs1[i];

        for (unsigned int i = 0; i < kss.size(); ++i) {
            auto ks = kss[i];
            auto ds0 = f(ks, cs0);
            auto ds1 = f(ks, cs1);
            if (is_impossible(ds0, ds1)) {
                if (
                    ks[5] == correct_ks[5] &&
                    ks[6] == correct_ks[6] &&
                    ks[7] == correct_ks[7] &&
                    ks[8] == correct_ks[8] &&
                    ks[9] == correct_ks[9] &&
                    ks[10] == correct_ks[10] &&
                    ks[11] == correct_ks[11]
                ) {
                    std::cout << "ERROR: Correct key was eliminated." << std::endl;
                    return 1;
                }

                std::swap(kss[i], kss[kss.size() - 1]);
                kss.pop_back();
            }
        }

        std::cout << "Number of keys remaining: " << kss.size() << std::endl;
    }

    return 0;
}
<commit_msg>some_cipher/idc.cpp: Correct error in reading input.<commit_after>#include <functional>
#include <iostream>
#include <vector>

#include "some_cipher.h"

std::vector<nibs> gen_keys() {
    std::vector<nibs> kss;
    for (int k5 = 0; k5 < 16; ++k5) {
    for (int k6 = 0; k6 < 16; ++k6) {
    for (int k7 = 0; k7 < 16; ++k7) {
    for (int k8 = 0; k8 < 16; ++k8) {
    for (int k9 = 0; k9 < 16; ++k9) {
    for (int k10 = 0; k10 < 16; ++k10) {
    for (int k11 = 0; k11 < 16; ++k11) {
        nibs ks{0};
        ks[5] = k5;
        ks[6] = k6;
        ks[7] = k7;
        ks[8] = k8;
        ks[9] = k9;
        ks[10] = k10;
        ks[11] = k11;
        kss.push_back(ks);
    }}}}}}}
    return kss;
}

int main() {
    // read the key
    int x;
    nibs correct_ks;
    for (int i = 0; i < 12; ++i) {
        std::cin >> x;
        correct_ks[i] = x;
    }

    // generate a list of all the keys
    std::vector<nibs> kss = gen_keys();
    std::cout << "Generated " << +kss.size() << " keys." << std::endl;

    // go through all the pairs

    std::function<nibs(nibs, nibs)> f = [](nibs ks, nibs cs) {
        return inv_roundf(ks, inv_roundf(ks, cs, 4), 3);
    };

    std::function<bool(nibs, nibs)> is_impossible = [](nibs ds0, nibs ds1) {
        return differences(ds0, ds1) == diffs {0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1};
    };

    while (std::cin) {
        nibs cs0, cs1;
        for (int i = 0; i < 12; ++i) {
            std::cin >> x;
            cs0[i] = x;
        }
        for (int i = 0; i < 12; ++i) {
            std::cin >> x;
            cs1[i] = x;
        }

        std::cout << "CS0: ";
        for (auto &c : cs0) std::cout << +c << " ";
        std::cout << std::endl;
        std::cout << "CS1: ";
        for (auto &c : cs1) std::cout << +c << " ";
        std::cout << std::endl;

        for (unsigned int i = 0; i < kss.size(); ++i) {
            auto ks = kss[i];
            auto ds0 = f(ks, cs0);
            auto ds1 = f(ks, cs1);
            if (is_impossible(ds0, ds1)) {
                if (
                    ks[5] == correct_ks[5] &&
                    ks[6] == correct_ks[6] &&
                    ks[7] == correct_ks[7] &&
                    ks[8] == correct_ks[8] &&
                    ks[9] == correct_ks[9] &&
                    ks[10] == correct_ks[10] &&
                    ks[11] == correct_ks[11]
                ) {
                    std::cout << "ERROR: Correct key was eliminated." << std::endl;
                    return 1;
                }

                std::swap(kss[i], kss[kss.size() - 1]);
                kss.pop_back();
            }
        }

        std::cout << "Number of keys remaining: " << kss.size() << std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>// -----------------------------------------------------------------------------
//
// GIMCS -- Generalized Intelligence Model and Computer Simulation
//
// Copyright (C) 2013-2014, Andy Huang  <andyspider@126.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// -----------------------------------------------------------------------------

#include <stdlib.h>
#include <sys/timeb.h>
#include <unistd.h>
#include "gimcs/Avatar.h"
#include "gimcs/Debug.h"

namespace gimcs
{

Avatar::Avatar() :
        name("unnamed avatar"), sps(-1), ava_loop_count(0), myagent(NULL), control_step_time(
                0)
{
}

Avatar::Avatar(std::string n) :
        name(n), sps(-1), ava_loop_count(0), myagent(NULL), control_step_time(
                0)
{
}

Avatar::~Avatar()
{
}

/**
 * \brief launch a avatar continuously.
 */
void Avatar::launch()
{
    while (true)
    {
        ava_loop_count++;    // inc count
        dbgmoreprt("Enter Launch Loop ", "------------------------------ count == %ld\n", ava_loop_count);

        unsigned long start_time = getCurrentTime();

        /* Perceive the outside world */
        Agent::State cs = percieveState();    // get current state
        dbgmoreprt("Launch():", "%s, State: %ld\n", name.c_str(), cs);

        /* Process stage */
        OSpace acts = actionCandidates(cs);    // get all action candidates of a state

        Agent::Action act = myagent->process(cs, acts);    // choose an action from candidates
        // check validation
        if (act == Agent::INVALID_ACTION)    // no valid actions available, reach a dead end, quit. !!!: be sure to check this before update stage
            break;// exit point here

        /* update stage */
        float oripayoff = originalPayoff(cs);    // get original payoff of a state
        myagent->update(oripayoff);    // agent update inner states

        /* Perform action to the outside world */
        performAction(act);    // otherwise, perform the action

        // handle time related job
        if (sps > 0)    // no control when sps <= 0
        {
            unsigned long end_time = getCurrentTime();
            unsigned long consumed_time = end_time - start_time;
            long time_remaining = control_step_time - consumed_time;
            if (time_remaining > 0)    // remaining time
            {
                dbgmoreprt("",
                        "You got %ld milliseconds remaining to do other things.\n",
                        time_remaining);
                // do some useful things here if you don't want to sleep
                usleep(time_remaining * 1000);
            }
            else
            {
                WARNNING(
                        "time is not enough to run a step, %ldms in lack, try to decrease the sps!\n",
                        -time_remaining);
            }
        }
    }
    // quit
    dbgmoreprt("Exit Launch Loop", "----------------------------------------------------------- %s Exit!\n", name.c_str());
    return;
}

/** \brief Get original payoff of each state.
 *  Return 1 for every state by default.
 * \param st state identity
 * \return original payoff of st
 *
 */
float Avatar::originalPayoff(Agent::State st)
{
    UNUSED(st);
    return 1.0;    // original payoff of states is 1.0 by default
}

unsigned long Avatar::getCurrentTime()
{
    struct timeb tb;
    ftime(&tb);
    return 1000 * tb.time + tb.millitm;
}

}    // namespace gimcs
<commit_msg>Avatar运行前检查是否链接agent<commit_after>// -----------------------------------------------------------------------------
//
// GIMCS -- Generalized Intelligence Model and Computer Simulation
//
// Copyright (C) 2013-2014, Andy Huang  <andyspider@126.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// -----------------------------------------------------------------------------

#include <stdlib.h>
#include <sys/timeb.h>
#include <unistd.h>
#include "gimcs/Avatar.h"
#include "gimcs/Debug.h"

namespace gimcs
{

Avatar::Avatar() :
        name("unnamed avatar"), sps(-1), ava_loop_count(0), myagent(NULL), control_step_time(
                0)
{
}

Avatar::Avatar(std::string n) :
        name(n), sps(-1), ava_loop_count(0), myagent(NULL), control_step_time(
                0)
{
}

Avatar::~Avatar()
{
}

/**
 * \brief launch a avatar continuously.
 */
void Avatar::launch()
{
    // check if agent is connected
    if (myagent == NULL)
        ERROR("launch(): Avatar is not connected to any agent!\n");

    while (true)
    {
        ava_loop_count++;    // inc count
        dbgmoreprt("Enter Launch Loop ", "------------------------------ count == %ld\n", ava_loop_count);

        unsigned long start_time = getCurrentTime();

        /* Perceive the outside world */
        Agent::State cs = percieveState();    // get current state
        dbgmoreprt("Launch():", "%s, State: %ld\n", name.c_str(), cs);

        /* Process stage */
        OSpace acts = actionCandidates(cs);    // get all action candidates of a state

        Agent::Action act = myagent->process(cs, acts);    // choose an action from candidates
        // check validation
        if (act == Agent::INVALID_ACTION)    // no valid actions available, reach a dead end, quit. !!!: be sure to check this before update stage
            break;// exit point here

        /* update stage */
        float oripayoff = originalPayoff(cs);    // get original payoff of a state
        myagent->update(oripayoff);    // agent update inner states

        /* Perform action to the outside world */
        performAction(act);    // otherwise, perform the action

        // handle time related job
        if (sps > 0)    // no control when sps <= 0
        {
            unsigned long end_time = getCurrentTime();
            unsigned long consumed_time = end_time - start_time;
            long time_remaining = control_step_time - consumed_time;
            if (time_remaining > 0)    // remaining time
            {
                dbgmoreprt("",
                        "You got %ld milliseconds remaining to do other things.\n",
                        time_remaining);
                // do some useful things here if you don't want to sleep
                usleep(time_remaining * 1000);
            }
            else
            {
                WARNNING(
                        "time is not enough to run a step, %ldms in lack, try to decrease the sps!\n",
                        -time_remaining);
            }
        }
    }
    // quit
    dbgmoreprt("Exit Launch Loop", "----------------------------------------------------------- %s Exit!\n", name.c_str());
    return;
}

/** \brief Get original payoff of each state.
 *  Return 1 for every state by default.
 * \param st state identity
 * \return original payoff of st
 *
 */
float Avatar::originalPayoff(Agent::State st)
{
    UNUSED(st);
    return 1.0;    // original payoff of states is 1.0 by default
}

unsigned long Avatar::getCurrentTime()
{
    struct timeb tb;
    ftime(&tb);
    return 1000 * tb.time + tb.millitm;
}

}    // namespace gimcs
<|endoftext|>


<commit_before>#include "Gfx.h"
#include "DX11.h"
#include "Gui.h"
#include <dxgi1_2.h>
#include <imgui/imgui.h>
#include <utils_window.h>
#include <utils_dwm.h>
#include <bblib/logging.h>

namespace bb {

	Gfx::~Gfx () { }

	bool Gfx::Init ()
	{
		TRACE_MSG(LL_INFO, CTX_BB | CTX_INIT, "Initializing gfx");
		m_dx11 = new DX11;
		if (m_dx11->CreateDeviceD3D(nullptr) < 0)
		{
			TRACE_MSG(LL_ERROR, CTX_BB | CTX_GFX | CTX_INIT, "Cannot create DX11 device");
			m_dx11->CleanupDeviceD3D();
			return false;
		}
		TRACE_MSG(LL_INFO, CTX_BB | CTX_GFX | CTX_INIT, "Created DX11 device");
		return true;
	}

	HWND Gfx::MkWindow (void * gui, int x, int y, int w, int h, int alpha, wchar_t const * clname, wchar_t const * wname)
	{
		WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, &Gui::GuiWndProcDispatch, 0L, 0L, ::GetModuleHandle(NULL), NULL, ::LoadCursor(NULL, IDC_ARROW), NULL, NULL, clname, NULL };
		::RegisterClassEx(&wc);

		bool const dwm_on = isDwmEnabled();
		DWORD f = 0;
		if (dwm_on)
			f |= WS_EX_LAYERED;
		HWND hwnd = ::CreateWindowExW(
			  f
			, clname
			, wname
			//, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
			, 0
			, x, y, w, h
			, NULL
			, NULL
			, wc.hInstance
			, gui);

		if (dwm_on)
			SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), alpha, ULW_ALPHA);
		removeWindowBorder(hwnd); // @TODO: removeWindowBorder triggers WM_PAINT but it's too early (will be ignored)

		TRACE_MSG(LL_INFO, CTX_BB | CTX_GFX, "Created window for gui (dwm=%u), hwnd=0x%08x", dwm_on, hwnd);
		return hwnd;
	}

	GfxWindow * Gfx::MkGfxWindow (HWND hwnd, Gui * gui, wchar_t const * clname, wchar_t const * wname)
	{
		GfxWindowPtr w(new GfxWindow);
		w->m_hwnd = hwnd;
		w->m_chain = m_dx11->CreateSwapChain(hwnd);
		w->m_view = nullptr; // created in WM_SIZE
		w->m_clName = std::move(bbstring(clname));
		w->m_wName = std::move(bbstring(wname));
		if (!w->m_gui)
		{
			w->m_gui = gui;
			w->m_gui->m_name = wname;
			w->m_gui->m_enabled = true;
			w->m_gui->m_gfxWindow = w.get();
			w->m_gui->m_dx11 = m_dx11;
			w->m_gui->Init(hwnd, m_dx11);
		}
		m_windows.push_back(std::move(w));
		return m_windows.back().get();
	}

	GfxWindow * Gfx::MkGuiWindow (int x, int y, int w, int h, int alpha, wchar_t const * clname, wchar_t const * wname, bool show)
	{
		TRACE_SCOPE(LL_INFO, CTX_BB | CTX_GFX);
		Gui * gui = new Gui;
		TRACE_MSG(LL_INFO, CTX_BB | CTX_GFX, "Created new gui @ 0x%x wname=%ws", gui, wname);
		HWND hwnd = MkWindow(static_cast<void *>(gui), x, y, w, h, alpha, clname, wname);
		GfxWindow * res = MkGfxWindow(hwnd, gui, clname, wname);

		// @TODO: find better place for this
		ImGuiStyle & style = ImGui::GetStyle();
		RECT rect;
		::GetClientRect(hwnd, &rect);
		int const cst = style.WindowRounding; // dumb correction
		createRoundedRect(hwnd, rect.right, rect.bottom, style.WindowRounding, cst);

		::ShowWindow(hwnd, show ? SW_SHOW : SW_HIDE);
		showInFromTaskBar(hwnd, false);
		return res;
	}

	bool Gfx::Done ()
	{
		TRACE_MSG(LL_INFO, CTX_BB | CTX_GFX, "Terminating gfx");
		m_dx11->CleanupDeviceD3D();
		delete m_dx11;
		m_dx11 = nullptr;
		return true;
	}

	void Gfx::NewFrame ()
	{
		for (GfxWindowPtr & w : m_windows)
		{
			w->NewFrame();
		}
	}

	void Gfx::Render ()
	{
		if (IsReady())
		{
			m_iconCache.Update();
			for (GfxWindowPtr & w : m_windows)
			{
				w->Render();
			}
		}
	}

#define USE_DYNAMIC_UPDATE 0

	bool Gfx::MkIconResourceView (IconSlab & slab)
	{
		uint8_t * bmpdata = slab.m_buffer.get();
		uint32_t const x = slab.m_x * slab.m_nx;
		uint32_t const y = slab.m_y * slab.m_ny;

		ID3D11ShaderResourceView * texview = nullptr;

		D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(
				DXGI_FORMAT_B8G8R8A8_UNORM
			,	x, y
			, 1, 1				// arraySize, mipLevels
			, D3D11_BIND_SHADER_RESOURCE		// bindFlags
#if USE_DYNAMIC_UPDATE
			, D3D11_USAGE_DYNAMIC						// dynamic usage. just for testing, default should be better (updates of icon textures should be rare)
			, D3D11_CPU_ACCESS_WRITE				// cpuaccessFlags
#else
			, D3D11_USAGE_DEFAULT						// default usage.
			, 0															// cpuaccessFlags
#endif
			, 1, 0, 0			// sampleCount, sampleQuality, miscFlags
			);

		ID3D11Texture2D * texture = nullptr;
		HRESULT hr = m_dx11->m_pd3dDevice->CreateTexture2D(&texdesc, nullptr, &texture);
		if (SUCCEEDED(hr))
		{
			D3D11_SHADER_RESOURCE_VIEW_DESC viewdesc;
			memset(&viewdesc, 0, sizeof(viewdesc));
			viewdesc.Format = texdesc.Format;
			viewdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
			viewdesc.Texture2D.MipLevels = 0;
			viewdesc.Texture2D.MostDetailedMip = texdesc.MipLevels;

			HRESULT hr_view = m_dx11->m_pd3dDevice->CreateShaderResourceView(texture, nullptr, &texview);

			if (SUCCEEDED(hr_view))
			{
				slab.m_view = texview;
				slab.m_updated = slab.m_end;

				UINT const srcRowPitch = slab.m_bits / CHAR_BIT * x;
				m_dx11->m_pd3dDeviceContext->UpdateSubresource(texture, 0, nullptr, bmpdata, srcRowPitch, 0); // update whole texture
			}
			texture->Release();
			return true;
		}
		return false;
	}

	bool Gfx::UpdateIconResourceView (IconSlab & slab)
	{
#if USE_DYNAMIC_UPDATE
		D3D11_MAPPED_SUBRESOURCE mappedResource;
		memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));

		m_dx11->m_pd3dDeviceContext->Map(v->Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
		memcpy(mappedResource.pData, bmpdata, x * y * bits / CHAR_BIT);
		m_dx11->m_pd3dDeviceContext->Unmap(vertexBuffer2.Get(), 0);
#else

		uint8_t * const bmpdata = slab.m_buffer.get();

		for (; slab.m_updated < slab.m_end; ++slab.m_updated)
		{
			uint32_t const index = slab.m_updated;

			uint32_t const bytes = slab.m_bits / CHAR_BIT;
			uint32_t const row_size = bytes * slab.m_x * slab.m_nx;
			uint32_t const sz = static_cast<float>(slab.m_x);
			uint32_t const x = index % slab.m_nx;
			uint32_t const y = index / slab.m_nx;
			uint32_t const u0x = x * slab.m_x;
			uint32_t const u0y = y * slab.m_y;
			uint32_t const u1x = u0x + sz;
			uint32_t const u1y = u0y + sz;

			D3D11_BOX destRegion;
			destRegion.left = u0x;
			destRegion.top = u0y;
			destRegion.right = u1x;
			destRegion.bottom = u1y;
			destRegion.front = 0;
			destRegion.back = 1;

			ID3D11Resource * res = nullptr;
			slab.m_view->GetResource(&res);
			void * const data = bmpdata + row_size * y + x * bytes * slab.m_x;
			m_dx11->m_pd3dDeviceContext->UpdateSubresource(res, 0, &destRegion, data, row_size, 0);
		}

// update whole texture
// 		UINT const srcRowPitch = slab.m_bits / CHAR_BIT * slab.m_x * slab.m_nx;
// 		ID3D11Resource * res = nullptr;
// 		slab.m_view->GetResource(&res);
// 		m_dx11->m_pd3dDeviceContext->UpdateSubresource(res, 0, nullptr, bmpdata, srcRowPitch, 0);
		return true;
#endif
	}

}
<commit_msg>- crash on uninit<commit_after>#include "Gfx.h"
#include "DX11.h"
#include "Gui.h"
#include <dxgi1_2.h>
#include <imgui/imgui.h>
#include <utils_window.h>
#include <utils_dwm.h>
#include <bblib/logging.h>

namespace bb {

	Gfx::~Gfx () { }

	bool Gfx::Init ()
	{
		TRACE_MSG(LL_INFO, CTX_BB | CTX_INIT, "Initializing gfx");
		m_dx11 = new DX11;
		if (m_dx11->CreateDeviceD3D(nullptr) < 0)
		{
			TRACE_MSG(LL_ERROR, CTX_BB | CTX_GFX | CTX_INIT, "Cannot create DX11 device");
			m_dx11->CleanupDeviceD3D();
			return false;
		}
		TRACE_MSG(LL_INFO, CTX_BB | CTX_GFX | CTX_INIT, "Created DX11 device");
		return true;
	}

	HWND Gfx::MkWindow (void * gui, int x, int y, int w, int h, int alpha, wchar_t const * clname, wchar_t const * wname)
	{
		WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, &Gui::GuiWndProcDispatch, 0L, 0L, ::GetModuleHandle(NULL), NULL, ::LoadCursor(NULL, IDC_ARROW), NULL, NULL, clname, NULL };
		::RegisterClassEx(&wc);

		bool const dwm_on = isDwmEnabled();
		DWORD f = 0;
		if (dwm_on)
			f |= WS_EX_LAYERED;
		HWND hwnd = ::CreateWindowExW(
			  f
			, clname
			, wname
			//, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
			, 0
			, x, y, w, h
			, NULL
			, NULL
			, wc.hInstance
			, gui);

		if (dwm_on)
			SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), alpha, ULW_ALPHA);
		removeWindowBorder(hwnd); // @TODO: removeWindowBorder triggers WM_PAINT but it's too early (will be ignored)

		TRACE_MSG(LL_INFO, CTX_BB | CTX_GFX, "Created window for gui (dwm=%u), hwnd=0x%08x", dwm_on, hwnd);
		return hwnd;
	}

	GfxWindow * Gfx::MkGfxWindow (HWND hwnd, Gui * gui, wchar_t const * clname, wchar_t const * wname)
	{
		GfxWindowPtr w(new GfxWindow);
		w->m_hwnd = hwnd;
		w->m_chain = m_dx11->CreateSwapChain(hwnd);
		w->m_view = nullptr; // created in WM_SIZE
		w->m_clName = std::move(bbstring(clname));
		w->m_wName = std::move(bbstring(wname));
		if (!w->m_gui)
		{
			w->m_gui = gui;
			w->m_gui->m_name = wname;
			w->m_gui->m_enabled = true;
			w->m_gui->m_gfxWindow = w.get();
			w->m_gui->m_dx11 = m_dx11;
			w->m_gui->Init(hwnd, m_dx11);
		}
		m_windows.push_back(std::move(w));
		return m_windows.back().get();
	}

	GfxWindow * Gfx::MkGuiWindow (int x, int y, int w, int h, int alpha, wchar_t const * clname, wchar_t const * wname, bool show)
	{
		TRACE_SCOPE(LL_INFO, CTX_BB | CTX_GFX);
		Gui * gui = new Gui;
		TRACE_MSG(LL_INFO, CTX_BB | CTX_GFX, "Created new gui @ 0x%x wname=%ws", gui, wname);
		HWND hwnd = MkWindow(static_cast<void *>(gui), x, y, w, h, alpha, clname, wname);
		GfxWindow * res = MkGfxWindow(hwnd, gui, clname, wname);

		// @TODO: find better place for this
		ImGuiStyle & style = ImGui::GetStyle();
		RECT rect;
		::GetClientRect(hwnd, &rect);
		int const cst = style.WindowRounding; // dumb correction
		createRoundedRect(hwnd, rect.right, rect.bottom, style.WindowRounding, cst);

		::ShowWindow(hwnd, show ? SW_SHOW : SW_HIDE);
		showInFromTaskBar(hwnd, false);
		return res;
	}

	bool Gfx::Done ()
	{
		TRACE_MSG(LL_INFO, CTX_BB | CTX_GFX, "Terminating gfx");
		if (m_dx11)
		{
			m_dx11->CleanupDeviceD3D();
			delete m_dx11;
			m_dx11 = nullptr;
		}
		return true;
	}

	void Gfx::NewFrame ()
	{
		for (GfxWindowPtr & w : m_windows)
		{
			w->NewFrame();
		}
	}

	void Gfx::Render ()
	{
		if (IsReady())
		{
			m_iconCache.Update();
			for (GfxWindowPtr & w : m_windows)
			{
				w->Render();
			}
		}
	}

#define USE_DYNAMIC_UPDATE 0

	bool Gfx::MkIconResourceView (IconSlab & slab)
	{
		uint8_t * bmpdata = slab.m_buffer.get();
		uint32_t const x = slab.m_x * slab.m_nx;
		uint32_t const y = slab.m_y * slab.m_ny;

		ID3D11ShaderResourceView * texview = nullptr;

		D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(
				DXGI_FORMAT_B8G8R8A8_UNORM
			,	x, y
			, 1, 1				// arraySize, mipLevels
			, D3D11_BIND_SHADER_RESOURCE		// bindFlags
#if USE_DYNAMIC_UPDATE
			, D3D11_USAGE_DYNAMIC						// dynamic usage. just for testing, default should be better (updates of icon textures should be rare)
			, D3D11_CPU_ACCESS_WRITE				// cpuaccessFlags
#else
			, D3D11_USAGE_DEFAULT						// default usage.
			, 0															// cpuaccessFlags
#endif
			, 1, 0, 0			// sampleCount, sampleQuality, miscFlags
			);

		ID3D11Texture2D * texture = nullptr;
		HRESULT hr = m_dx11->m_pd3dDevice->CreateTexture2D(&texdesc, nullptr, &texture);
		if (SUCCEEDED(hr))
		{
			D3D11_SHADER_RESOURCE_VIEW_DESC viewdesc;
			memset(&viewdesc, 0, sizeof(viewdesc));
			viewdesc.Format = texdesc.Format;
			viewdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
			viewdesc.Texture2D.MipLevels = 0;
			viewdesc.Texture2D.MostDetailedMip = texdesc.MipLevels;

			HRESULT hr_view = m_dx11->m_pd3dDevice->CreateShaderResourceView(texture, nullptr, &texview);

			if (SUCCEEDED(hr_view))
			{
				slab.m_view = texview;
				slab.m_updated = slab.m_end;

				UINT const srcRowPitch = slab.m_bits / CHAR_BIT * x;
				m_dx11->m_pd3dDeviceContext->UpdateSubresource(texture, 0, nullptr, bmpdata, srcRowPitch, 0); // update whole texture
			}
			texture->Release();
			return true;
		}
		return false;
	}

	bool Gfx::UpdateIconResourceView (IconSlab & slab)
	{
#if USE_DYNAMIC_UPDATE
		D3D11_MAPPED_SUBRESOURCE mappedResource;
		memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));

		m_dx11->m_pd3dDeviceContext->Map(v->Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
		memcpy(mappedResource.pData, bmpdata, x * y * bits / CHAR_BIT);
		m_dx11->m_pd3dDeviceContext->Unmap(vertexBuffer2.Get(), 0);
#else

		uint8_t * const bmpdata = slab.m_buffer.get();

		for (; slab.m_updated < slab.m_end; ++slab.m_updated)
		{
			uint32_t const index = slab.m_updated;

			uint32_t const bytes = slab.m_bits / CHAR_BIT;
			uint32_t const row_size = bytes * slab.m_x * slab.m_nx;
			uint32_t const sz = static_cast<float>(slab.m_x);
			uint32_t const x = index % slab.m_nx;
			uint32_t const y = index / slab.m_nx;
			uint32_t const u0x = x * slab.m_x;
			uint32_t const u0y = y * slab.m_y;
			uint32_t const u1x = u0x + sz;
			uint32_t const u1y = u0y + sz;

			D3D11_BOX destRegion;
			destRegion.left = u0x;
			destRegion.top = u0y;
			destRegion.right = u1x;
			destRegion.bottom = u1y;
			destRegion.front = 0;
			destRegion.back = 1;

			ID3D11Resource * res = nullptr;
			slab.m_view->GetResource(&res);
			void * const data = bmpdata + row_size * y + x * bytes * slab.m_x;
			m_dx11->m_pd3dDeviceContext->UpdateSubresource(res, 0, &destRegion, data, row_size, 0);
		}

// update whole texture
// 		UINT const srcRowPitch = slab.m_bits / CHAR_BIT * slab.m_x * slab.m_nx;
// 		ID3D11Resource * res = nullptr;
// 		slab.m_view->GetResource(&res);
// 		m_dx11->m_pd3dDeviceContext->UpdateSubresource(res, 0, nullptr, bmpdata, srcRowPitch, 0);
		return true;
#endif
	}

}
<|endoftext|>


<commit_before>#include <benchmark/benchmark.h>
#include <cstdlib>
#include "FEC/Convolutional.h"

/* Benchmark against fecmagic implementation. */
#include "sequence.h"
#include "convolutional-decoder.h"

using TestEncoder = Thiemar::Convolutional::PuncturedConvolutionalEncoder<
    7u,
    Thiemar::Convolutional::PuncturingMatrices::n_2_rate_1_2,
    Thiemar::BinarySequence<1, 1, 0, 1, 1, 0, 1>,
    Thiemar::BinarySequence<1, 0, 0, 1, 1, 1, 1>
>;

using TestDecoder = Thiemar::Convolutional::PuncturedHardDecisionViterbiDecoder<
    7u,
    32u,
    Thiemar::Convolutional::PuncturingMatrices::n_2_rate_1_2,
    Thiemar::BinarySequence<1, 1, 0, 1, 1, 0, 1>,
    Thiemar::BinarySequence<1, 0, 0, 1, 1, 1, 1>
>;

void FECMagicConvolutionalDecoder_Decode(benchmark::State& state) {
    fecmagic::PuncturedConvolutionalDecoder<
        fecmagic::Sequence<uint8_t, 1, 1>, 35, 7,
        uint8_t, 0b1011011, 0b1111001> fecmagic_dec;

    /* Set up test buffers. */
    uint8_t test_in[1024u] = {};
    uint8_t test_out[TestEncoder::calculate_output_length(sizeof(test_in))] = {};
    uint8_t test_decoded_fecmagic[1024u] = {};

    /* Seed RNG for repeatibility. */
    std::srand(123u);
    for (std::size_t i = 0u; i < sizeof(test_in); i++) {
        test_in[i] = std::rand() & 0xffu;
    }

    TestEncoder::encode(test_in, sizeof(test_in), test_out);

    while(state.KeepRunning()) {
        fecmagic_dec.reset(test_decoded_fecmagic);
        fecmagic_dec.decode(test_out, TestEncoder::calculate_output_length(sizeof(test_in)));
        fecmagic_dec.flush();
    }
}

BENCHMARK(FECMagicConvolutionalDecoder_Decode);

void ConvolutionalDecoder_Decode(benchmark::State& state) {
    /* Set up test buffers. */
    uint8_t test_in[1024u] = {};
    uint8_t test_out[TestEncoder::calculate_output_length(sizeof(test_in))] = {};
    uint8_t test_decoded[1024u] = {};

    /* Seed RNG for repeatibility. */
    std::srand(123u);
    for (std::size_t i = 0u; i < sizeof(test_in); i++) {
        test_in[i] = std::rand() & 0xffu;
    }

    TestEncoder::encode(test_in, sizeof(test_in), test_out);

    while(state.KeepRunning()) {
        TestDecoder::decode(test_out, sizeof(test_out), test_decoded);
    }
}

BENCHMARK(ConvolutionalDecoder_Decode);

using TestEncoderPunctured = Thiemar::Convolutional::PuncturedConvolutionalEncoder<
    7u,
    Thiemar::BinarySequence<1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0>,
    Thiemar::BinarySequence<1, 1, 0, 1, 1, 0, 1>,
    Thiemar::BinarySequence<1, 0, 0, 1, 1, 1, 1>
>;

using TestDecoderPunctured = Thiemar::Convolutional::PuncturedHardDecisionViterbiDecoder<
    7u,
    56u,
    Thiemar::BinarySequence<1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0>,
    Thiemar::BinarySequence<1, 1, 0, 1, 1, 0, 1>,
    Thiemar::BinarySequence<1, 0, 0, 1, 1, 1, 1>
>;

void FECMagicPuncturedConvolutionalDecoder_Decode(benchmark::State& state) {
    fecmagic::PuncturedConvolutionalDecoder<
        fecmagic::Sequence<uint8_t, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0>, 35, 7,
        uint8_t, 0b1011011, 0b1111001> fecmagic_dec;

    /* Set up test buffers. */
    uint8_t test_in[1024u] = {};
    uint8_t test_out[TestEncoderPunctured::calculate_output_length(sizeof(test_in))] = {};
    uint8_t test_decoded_fecmagic[1024u] = {};

    /* Seed RNG for repeatibility. */
    std::srand(123u);
    for (std::size_t i = 0u; i < sizeof(test_in); i++) {
        test_in[i] = std::rand() & 0xffu;
    }

    TestEncoderPunctured::encode(test_in, sizeof(test_in), test_out);

    while(state.KeepRunning()) {
        fecmagic_dec.reset(test_decoded_fecmagic);
        fecmagic_dec.decode(test_out, TestEncoderPunctured::calculate_output_length(sizeof(test_in)));
        fecmagic_dec.flush();
    }
}

BENCHMARK(FECMagicPuncturedConvolutionalDecoder_Decode);

void PuncturedConvolutionalDecoder_Decode(benchmark::State& state) {
    /* Set up test buffers. */
    uint8_t test_in[1024u] = {};
    uint8_t test_out[TestEncoderPunctured::calculate_output_length(sizeof(test_in))] = {};
    uint8_t test_decoded[1024u] = {};

    /* Seed RNG for repeatibility. */
    std::srand(123u);
    for (std::size_t i = 0u; i < sizeof(test_in); i++) {
        test_in[i] = std::rand() & 0xffu;
    }

    TestEncoderPunctured::encode(test_in, sizeof(test_in), test_out);

    while(state.KeepRunning()) {
        TestDecoderPunctured::decode(test_out, sizeof(test_out), test_decoded);
    }
}

BENCHMARK(PuncturedConvolutionalDecoder_Decode);
<commit_msg>Fix up buffer sizes in benchmarks<commit_after>#include <benchmark/benchmark.h>
#include <cstdlib>
#include "FEC/Convolutional.h"

/* Benchmark against fecmagic implementation. */
#include "sequence.h"
#include "convolutional-decoder.h"

using TestEncoder = Thiemar::Convolutional::PuncturedConvolutionalEncoder<
    7u,
    Thiemar::Convolutional::PuncturingMatrices::n_2_rate_1_2,
    Thiemar::BinarySequence<1, 1, 0, 1, 1, 0, 1>,
    Thiemar::BinarySequence<1, 0, 0, 1, 1, 1, 1>
>;

using TestDecoder = Thiemar::Convolutional::PuncturedHardDecisionViterbiDecoder<
    7u,
    32u,
    Thiemar::Convolutional::PuncturingMatrices::n_2_rate_1_2,
    Thiemar::BinarySequence<1, 1, 0, 1, 1, 0, 1>,
    Thiemar::BinarySequence<1, 0, 0, 1, 1, 1, 1>
>;

void FECMagicConvolutionalDecoder_Decode(benchmark::State& state) {
    fecmagic::PuncturedConvolutionalDecoder<
        fecmagic::Sequence<uint8_t, 1, 1>, 35, 7,
        uint8_t, 0b1011011, 0b1111001> fecmagic_dec;

    /* Set up test buffers. */
    uint8_t test_in[1024u] = {};
    uint8_t test_out[TestEncoder::calculate_output_length(sizeof(test_in))] = {};
    uint8_t test_decoded_fecmagic[TestDecoder::calculate_output_length(sizeof(test_out))] = {};

    /* Seed RNG for repeatibility. */
    std::srand(123u);
    for (std::size_t i = 0u; i < sizeof(test_in); i++) {
        test_in[i] = std::rand() & 0xffu;
    }

    TestEncoder::encode(test_in, sizeof(test_in), test_out);

    while(state.KeepRunning()) {
        fecmagic_dec.reset(test_decoded_fecmagic);
        fecmagic_dec.decode(test_out, TestEncoder::calculate_output_length(sizeof(test_in)));
        fecmagic_dec.flush();
    }
}

BENCHMARK(FECMagicConvolutionalDecoder_Decode);

void ConvolutionalDecoder_Decode(benchmark::State& state) {
    /* Set up test buffers. */
    uint8_t test_in[1024u] = {};
    uint8_t test_out[TestEncoder::calculate_output_length(sizeof(test_in))] = {};
    uint8_t test_decoded[TestDecoder::calculate_output_length(sizeof(test_out))] = {};

    /* Seed RNG for repeatibility. */
    std::srand(123u);
    for (std::size_t i = 0u; i < sizeof(test_in); i++) {
        test_in[i] = std::rand() & 0xffu;
    }

    TestEncoder::encode(test_in, sizeof(test_in), test_out);

    while(state.KeepRunning()) {
        TestDecoder::decode(test_out, sizeof(test_out), test_decoded);
    }
}

BENCHMARK(ConvolutionalDecoder_Decode);

using TestEncoderPunctured = Thiemar::Convolutional::PuncturedConvolutionalEncoder<
    7u,
    Thiemar::BinarySequence<1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0>,
    Thiemar::BinarySequence<1, 1, 0, 1, 1, 0, 1>,
    Thiemar::BinarySequence<1, 0, 0, 1, 1, 1, 1>
>;

using TestDecoderPunctured = Thiemar::Convolutional::PuncturedHardDecisionViterbiDecoder<
    7u,
    56u,
    Thiemar::BinarySequence<1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0>,
    Thiemar::BinarySequence<1, 1, 0, 1, 1, 0, 1>,
    Thiemar::BinarySequence<1, 0, 0, 1, 1, 1, 1>
>;

void FECMagicPuncturedConvolutionalDecoder_Decode(benchmark::State& state) {
    fecmagic::PuncturedConvolutionalDecoder<
        fecmagic::Sequence<uint8_t, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0>, 35, 7,
        uint8_t, 0b1011011, 0b1111001> fecmagic_dec;

    /* Set up test buffers. */
    uint8_t test_in[1024u] = {};
    uint8_t test_out[TestEncoderPunctured::calculate_output_length(sizeof(test_in))] = {};
    uint8_t test_decoded_fecmagic[TestDecoderPunctured::calculate_output_length(sizeof(test_out))] = {};

    /* Seed RNG for repeatibility. */
    std::srand(123u);
    for (std::size_t i = 0u; i < sizeof(test_in); i++) {
        test_in[i] = std::rand() & 0xffu;
    }

    TestEncoderPunctured::encode(test_in, sizeof(test_in), test_out);

    while(state.KeepRunning()) {
        fecmagic_dec.reset(test_decoded_fecmagic);
        fecmagic_dec.decode(test_out, TestEncoderPunctured::calculate_output_length(sizeof(test_in)));
        fecmagic_dec.flush();
    }
}

BENCHMARK(FECMagicPuncturedConvolutionalDecoder_Decode);

void PuncturedConvolutionalDecoder_Decode(benchmark::State& state) {
    /* Set up test buffers. */
    uint8_t test_in[1024u] = {};
    uint8_t test_out[TestEncoderPunctured::calculate_output_length(sizeof(test_in))] = {};
    uint8_t test_decoded[TestDecoderPunctured::calculate_output_length(sizeof(test_out))] = {};

    /* Seed RNG for repeatibility. */
    std::srand(123u);
    for (std::size_t i = 0u; i < sizeof(test_in); i++) {
        test_in[i] = std::rand() & 0xffu;
    }

    TestEncoderPunctured::encode(test_in, sizeof(test_in), test_out);

    while(state.KeepRunning()) {
        TestDecoderPunctured::decode(test_out, sizeof(test_out), test_decoded);
    }
}

BENCHMARK(PuncturedConvolutionalDecoder_Decode);
<|endoftext|>


<commit_before>// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
#include <timedata.h>

#include <test/setup_common.h>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(timedata_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(util_MedianFilter) {
    CMedianFilter<int> filter(5, 15);

    BOOST_CHECK_EQUAL(filter.median(), 15);

    filter.input(20); // [15 20]
    BOOST_CHECK_EQUAL(filter.median(), 17);

    filter.input(30); // [15 20 30]
    BOOST_CHECK_EQUAL(filter.median(), 20);

    filter.input(3); // [3 15 20 30]
    BOOST_CHECK_EQUAL(filter.median(), 17);

    filter.input(7); // [3 7 15 20 30]
    BOOST_CHECK_EQUAL(filter.median(), 15);

    filter.input(18); // [3 7 18 20 30]
    BOOST_CHECK_EQUAL(filter.median(), 18);

    filter.input(0); // [0 3 7 18 30]
    BOOST_CHECK_EQUAL(filter.median(), 7);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Add test for AddTimeData<commit_after>// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
#include <timedata.h>

#include <netaddress.h>
#include <noui.h>
#include <warnings.h>

#include <test/setup_common.h>

#include <string>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(timedata_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(util_MedianFilter) {
    CMedianFilter<int> filter(5, 15);

    BOOST_CHECK_EQUAL(filter.median(), 15);

    filter.input(20); // [15 20]
    BOOST_CHECK_EQUAL(filter.median(), 17);

    filter.input(30); // [15 20 30]
    BOOST_CHECK_EQUAL(filter.median(), 20);

    filter.input(3); // [3 15 20 30]
    BOOST_CHECK_EQUAL(filter.median(), 17);

    filter.input(7); // [3 7 15 20 30]
    BOOST_CHECK_EQUAL(filter.median(), 15);

    filter.input(18); // [3 7 18 20 30]
    BOOST_CHECK_EQUAL(filter.median(), 18);

    filter.input(0); // [0 3 7 18 30]
    BOOST_CHECK_EQUAL(filter.median(), 7);
}

static void MultiAddTimeData(int n, int64_t offset) {
    static int cnt = 0;
    for (int i = 0; i < n; ++i) {
        CNetAddr addr;
        addr.SetInternal(std::to_string(++cnt));
        AddTimeData(addr, offset);
    }
}

BOOST_AUTO_TEST_CASE(addtimedata) {
    BOOST_CHECK_EQUAL(GetTimeOffset(), 0);

    // Part 1: Add large offsets to test a warning message that our clock may be
    // wrong.
    MultiAddTimeData(3, DEFAULT_MAX_TIME_ADJUSTMENT + 1);
    // Filter size is 1 + 3 = 4: It is always initialized with a single element
    // (offset 0)

    noui_suppress();
    // filter size 5
    MultiAddTimeData(1, DEFAULT_MAX_TIME_ADJUSTMENT + 1);
    noui_reconnect();

    BOOST_CHECK(GetWarnings("gui").find("clock is wrong") != std::string::npos);

    // nTimeOffset is not changed if the median of offsets exceeds
    // DEFAULT_MAX_TIME_ADJUSTMENT
    BOOST_CHECK_EQUAL(GetTimeOffset(), 0);

    // Part 2: Test positive and negative medians by adding more offsets
    // filter size 9
    MultiAddTimeData(4, 100);
    BOOST_CHECK_EQUAL(GetTimeOffset(), 100);
    // filter size 19
    MultiAddTimeData(10, -100);
    BOOST_CHECK_EQUAL(GetTimeOffset(), -100);

    // Part 3: Test behaviour when filter has reached maximum number of offsets
    const int MAX_SAMPLES = 200;
    int nfill = (MAX_SAMPLES - 3 - 19) / 2; // 89
    MultiAddTimeData(nfill, 100);
    // filter size MAX_SAMPLES - 3
    MultiAddTimeData(nfill, -100);
    BOOST_CHECK_EQUAL(GetTimeOffset(), -100);

    MultiAddTimeData(2, 100);
    // filter size MAX_SAMPLES -1, median is the initial 0 offset
    // since we added same number of positive/negative offsets

    BOOST_CHECK_EQUAL(GetTimeOffset(), 0);

    // After the number of offsets has reached MAX_SAMPLES -1 (=199),
    // nTimeOffset will never change because it is only updated when the number
    // of elements in the filter becomes odd. It was decided not to fix this
    // because it prevents possible attacks. See the comment in AddTimeData() or
    // issue #4521 for a more detailed explanation.

    // filter median is 100 now, but nTimeOffset will not change
    MultiAddTimeData(2, 100);
    BOOST_CHECK_EQUAL(GetTimeOffset(), 0);

    // We want this test to end with nTimeOffset==0, otherwise subsequent tests
    // of the suite will fail.
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include <smooth/application/network/http/HTTPProtocol.h>
#include <algorithm>

namespace smooth::application::network::http
{

    int HTTPProtocol::get_wanted_amount(HTTPPacket& packet)
    {
        int amount_to_request;

        // Return the number of bytes wanted to fill the packet
        if (state == State::reading_headers)
        {
            // How much left until we reach max header size?
            amount_to_request = max_header_size - total_bytes_received;
            // Make sure there is room for what he have received and what we ask for.
            packet.ensure_room(total_bytes_received + amount_to_request);
        }
        else
        {
            // Never ask for more than content_chunk_size
            auto remaining_of_content = incoming_content_length - total_content_bytes_received;
            amount_to_request = std::min(content_chunk_size, remaining_of_content);

            packet.ensure_room(content_bytes_received_in_current_part + amount_to_request);
        }

        return amount_to_request;
    }

    void HTTPProtocol::data_received(HTTPPacket& packet, int length)
    {
        total_bytes_received += length;

        if (state == State::reading_headers)
        {
            const auto end_of_header = packet.find_header_ending();

            if (end_of_header != packet.data().end())
            {
                // End of header found
                state = State::reading_content;
                actual_header_size = consume_headers(packet, end_of_header);
                total_content_bytes_received = total_bytes_received - actual_header_size;

                // content_bytes_received_in_current_part may be larger than content_chunk_size
                content_bytes_received_in_current_part = total_content_bytes_received;

                try
                {
                    incoming_content_length = packet.headers()[CONTENT_LENGTH].empty() ? 0 : std::stoi(
                            packet.headers()[CONTENT_LENGTH]);

                    if (incoming_content_length < 0)
                    {
                        error = true;
                        Log::error("HTTPProtocol",
                                   Format("{1} is < 0: {1}.", Str(CONTENT_LENGTH), Int32(incoming_content_length)));
                    }
                }
                catch (...)
                {
                    incoming_content_length = 0;
                }

                if (total_content_bytes_received < incoming_content_length)
                {
                    // There is more content to read, this packet will be followed by another packet.
                    packet.set_continued();
                }

                // When still reading the headers, the packet can never be a continuation, so don't check
                // for that condition.
            }
            else if (total_bytes_received >= max_header_size)
            {
                // Headers are too large
                error = true;
                Log::error("HTTPProtocol",
                           Format("Headers larger than MaxHeaderSize of {1} bytes.", Int32(max_header_size)));
            }
        }
        else
        {
            total_content_bytes_received += length;
            content_bytes_received_in_current_part += length;

            if (total_content_bytes_received < incoming_content_length)
            {
                // There is more content to read, this packet will be followed by another packet.
                packet.set_continued();
            }

            if (total_content_bytes_received > content_chunk_size)
            {
                // Packet continues a previous packet.
                packet.set_continuation();
            }
        }

        if (is_complete(packet))
        {
            packet.set_request_data(last_method, last_url, last_request_version);
        }
    }

    uint8_t* HTTPProtocol::get_write_pos(HTTPPacket& packet)
    {
        int offset;
        if (state == State::reading_headers)
        {
            offset = total_bytes_received;
        }
        else
        {
            offset = content_bytes_received_in_current_part;
        }

        return &packet.data()[static_cast<std::vector<uint8_t>::size_type>(offset)];
    }

    bool HTTPProtocol::is_complete(HTTPPacket& /*packet*/) const
    {
        auto complete = state != State::reading_headers;

        bool content_received =
                // No content to read.
                incoming_content_length == 0
                // All content received
                || total_content_bytes_received == incoming_content_length
                // Packet filled, split into multiple chunks.
                || content_bytes_received_in_current_part >= content_chunk_size;

        return complete && content_received;
    }

    bool HTTPProtocol::is_error()
    {
        return error;
    }

    int HTTPProtocol::consume_headers(HTTPPacket& packet,
                                      std::vector<uint8_t>::const_iterator header_ending)
    {
        std::stringstream ss;

        std::for_each(packet.data().cbegin(), header_ending, [&ss](auto& c) {
            if (c != '\n')
            {
                ss << static_cast<char>(c);
            }
        });

        // Get actual end of header
        header_ending += HTTPPacket::ending.size();
        // Update actual header size
        auto actual_header_bytes_received = static_cast<int>(std::distance(packet.data().cbegin(), header_ending));

        // Erase headers from buffer
        packet.data().erase(packet.data().begin(), header_ending);

        std::string s;
        while (std::getline(ss, s, '\r'))
        {
            if (!s.empty())
            {
                auto colon = std::find(s.begin(), s.end(), ':');
                if (colon == s.end() && !s.empty())
                {
                    std::smatch m;
                    if (std::regex_match(s, m, request_line))
                    {
                        // Store method for use in continued packets.
                        last_method = m[1].str();
                        last_url = m[2].str();
                        Log::info("QQQ ===> ", last_url);
                        last_request_version = m[3].str();
                        packet.set_request_data(last_method, last_url, last_request_version);
                    }
                    else if (std::regex_match(s, m, response_line))
                    {
                        // Store response data for later use
                        try
                        {
                            auto response_code = std::stoi(m[2].str());
                            packet.set_response_data(static_cast<ResponseCode>(response_code));
                        }
                        catch (...)
                        {
                            error = true;
                            Log::error("HTTPProtocol",
                                       Format("Invalid response code: {1}", Str(m[2].str())));
                        }
                    }
                }
                else
                {
                    if (std::distance(colon, s.end()) > 2)
                    {
                        // Headers are case-insensitive: https://tools.ietf.org/html/rfc7230#section-3.2
                        packet.headers()[util::to_lower_copy({s.begin(), colon})] = {colon + 2, s.end()};
                    }
                }
            }
        }

        return actual_header_bytes_received;
    }

    void HTTPProtocol::packet_consumed()
    {
        content_bytes_received_in_current_part = 0;

        if (error || total_content_bytes_received >= incoming_content_length)
        {
            // All chunks of the current request has been received.
            total_bytes_received = 0;
            incoming_content_length = 0;
            total_content_bytes_received = 0;
            actual_header_size = 0;
            state = State::reading_headers;
        }

        error = false;
    }

    void HTTPProtocol::reset()
    {
        // Simulate an error to force protocol to be completely reset.
        error = true;
        packet_consumed();
    }

}<commit_msg>Removed leftover logging.<commit_after>#include <smooth/application/network/http/HTTPProtocol.h>
#include <algorithm>

namespace smooth::application::network::http
{

    int HTTPProtocol::get_wanted_amount(HTTPPacket& packet)
    {
        int amount_to_request;

        // Return the number of bytes wanted to fill the packet
        if (state == State::reading_headers)
        {
            // How much left until we reach max header size?
            amount_to_request = max_header_size - total_bytes_received;
            // Make sure there is room for what he have received and what we ask for.
            packet.ensure_room(total_bytes_received + amount_to_request);
        }
        else
        {
            // Never ask for more than content_chunk_size
            auto remaining_of_content = incoming_content_length - total_content_bytes_received;
            amount_to_request = std::min(content_chunk_size, remaining_of_content);

            packet.ensure_room(content_bytes_received_in_current_part + amount_to_request);
        }

        return amount_to_request;
    }

    void HTTPProtocol::data_received(HTTPPacket& packet, int length)
    {
        total_bytes_received += length;

        if (state == State::reading_headers)
        {
            const auto end_of_header = packet.find_header_ending();

            if (end_of_header != packet.data().end())
            {
                // End of header found
                state = State::reading_content;
                actual_header_size = consume_headers(packet, end_of_header);
                total_content_bytes_received = total_bytes_received - actual_header_size;

                // content_bytes_received_in_current_part may be larger than content_chunk_size
                content_bytes_received_in_current_part = total_content_bytes_received;

                try
                {
                    incoming_content_length = packet.headers()[CONTENT_LENGTH].empty() ? 0 : std::stoi(
                            packet.headers()[CONTENT_LENGTH]);

                    if (incoming_content_length < 0)
                    {
                        error = true;
                        Log::error("HTTPProtocol",
                                   Format("{1} is < 0: {1}.", Str(CONTENT_LENGTH), Int32(incoming_content_length)));
                    }
                }
                catch (...)
                {
                    incoming_content_length = 0;
                }

                if (total_content_bytes_received < incoming_content_length)
                {
                    // There is more content to read, this packet will be followed by another packet.
                    packet.set_continued();
                }

                // When still reading the headers, the packet can never be a continuation, so don't check
                // for that condition.
            }
            else if (total_bytes_received >= max_header_size)
            {
                // Headers are too large
                error = true;
                Log::error("HTTPProtocol",
                           Format("Headers larger than MaxHeaderSize of {1} bytes.", Int32(max_header_size)));
            }
        }
        else
        {
            total_content_bytes_received += length;
            content_bytes_received_in_current_part += length;

            if (total_content_bytes_received < incoming_content_length)
            {
                // There is more content to read, this packet will be followed by another packet.
                packet.set_continued();
            }

            if (total_content_bytes_received > content_chunk_size)
            {
                // Packet continues a previous packet.
                packet.set_continuation();
            }
        }

        if (is_complete(packet))
        {
            packet.set_request_data(last_method, last_url, last_request_version);
        }
    }

    uint8_t* HTTPProtocol::get_write_pos(HTTPPacket& packet)
    {
        int offset;
        if (state == State::reading_headers)
        {
            offset = total_bytes_received;
        }
        else
        {
            offset = content_bytes_received_in_current_part;
        }

        return &packet.data()[static_cast<std::vector<uint8_t>::size_type>(offset)];
    }

    bool HTTPProtocol::is_complete(HTTPPacket& /*packet*/) const
    {
        auto complete = state != State::reading_headers;

        bool content_received =
                // No content to read.
                incoming_content_length == 0
                // All content received
                || total_content_bytes_received == incoming_content_length
                // Packet filled, split into multiple chunks.
                || content_bytes_received_in_current_part >= content_chunk_size;

        return complete && content_received;
    }

    bool HTTPProtocol::is_error()
    {
        return error;
    }

    int HTTPProtocol::consume_headers(HTTPPacket& packet,
                                      std::vector<uint8_t>::const_iterator header_ending)
    {
        std::stringstream ss;

        std::for_each(packet.data().cbegin(), header_ending, [&ss](auto& c) {
            if (c != '\n')
            {
                ss << static_cast<char>(c);
            }
        });

        // Get actual end of header
        header_ending += HTTPPacket::ending.size();
        // Update actual header size
        auto actual_header_bytes_received = static_cast<int>(std::distance(packet.data().cbegin(), header_ending));

        // Erase headers from buffer
        packet.data().erase(packet.data().begin(), header_ending);

        std::string s;
        while (std::getline(ss, s, '\r'))
        {
            if (!s.empty())
            {
                auto colon = std::find(s.begin(), s.end(), ':');
                if (colon == s.end() && !s.empty())
                {
                    std::smatch m;
                    if (std::regex_match(s, m, request_line))
                    {
                        // Store method for use in continued packets.
                        last_method = m[1].str();
                        last_url = m[2].str();
                        last_request_version = m[3].str();
                        packet.set_request_data(last_method, last_url, last_request_version);
                    }
                    else if (std::regex_match(s, m, response_line))
                    {
                        // Store response data for later use
                        try
                        {
                            auto response_code = std::stoi(m[2].str());
                            packet.set_response_data(static_cast<ResponseCode>(response_code));
                        }
                        catch (...)
                        {
                            error = true;
                            Log::error("HTTPProtocol",
                                       Format("Invalid response code: {1}", Str(m[2].str())));
                        }
                    }
                }
                else
                {
                    if (std::distance(colon, s.end()) > 2)
                    {
                        // Headers are case-insensitive: https://tools.ietf.org/html/rfc7230#section-3.2
                        packet.headers()[util::to_lower_copy({s.begin(), colon})] = {colon + 2, s.end()};
                    }
                }
            }
        }

        return actual_header_bytes_received;
    }

    void HTTPProtocol::packet_consumed()
    {
        content_bytes_received_in_current_part = 0;

        if (error || total_content_bytes_received >= incoming_content_length)
        {
            // All chunks of the current request has been received.
            total_bytes_received = 0;
            incoming_content_length = 0;
            total_content_bytes_received = 0;
            actual_header_size = 0;
            state = State::reading_headers;
        }

        error = false;
    }

    void HTTPProtocol::reset()
    {
        // Simulate an error to force protocol to be completely reset.
        error = true;
        packet_consumed();
    }

}<|endoftext|>