<commit_before>// Copyright (C) 2019 - 2020 by Pedro Mendes, Rector and Visitors of the
// University of Virginia, University of Heidelberg, and University
// of Connecticut School of Medicine.
// All rights reserved.

// Copyright (C) 2017 - 2018 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and University of
// of Connecticut School of Medicine.
// All rights reserved.

// Copyright (C) 2010 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include "CQLayoutsWidget.h"

#include <iostream>

#include "CQMessageBox.h"
#include "CQLayoutsDM.h"
#include "CQSortFilterProxyModel.h"
#include "CQPushButtonDelegate.h"

#include "listviews.h"
#include "qtUtilities.h"
#include "copasi/resourcesUI/CQIconResource.h"

#include "copasi/layout/CLayout.h"
#include "copasi/layout/CListOfLayouts.h"
#include "copasi/model/CModel.h"
#include "copasi/report/CKeyFactory.h"
#include "copasi/CopasiDataModel/CDataModel.h"
#include <copasi/commandline/CConfigurationFile.h>
#include "copasi/core/CRootContainer.h"

#include "copasi/layoutUI/CQNewMainWindow.h"

#ifndef DISABLE_QT_LAYOUT_RENDERING
# include <copasi/qlayout/CQAnimationWindow.h>
#endif //DISABLE_QT_LAYOUT_RENDERING

#include "copasi/layoutUI/CQAutolayoutWizard.h"

#include <copasi/UI/copasiui3window.h>

#include <sstream>

CQLayoutsWidget::CQLayoutsWidget(QWidget *parent)
  : CopasiWidget(parent)
{
  setupUi(this);
  // Create Source Data Model.
  mpLayoutsDM = new CQLayoutsDM(this);
  // Create the Proxy Model for sorting/filtering and set its properties.
  mpProxyModel = new CQSortFilterProxyModel();
  mpProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
  mpProxyModel->setFilterKeyColumn(-1);
  mpProxyModel->setSourceModel(mpLayoutsDM);

#if QT_VERSION >= 0x050000
  mpTblLayouts->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
#endif

  if (CRootContainer::getConfiguration()->resizeToContents())
    {
#if QT_VERSION >= 0x050000
      mpTblLayouts->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
#else
      mpTblLayouts->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
#endif
    }

  mpTblLayouts->verticalHeader()->hide();
  mpTblLayouts->sortByColumn(COL_ROW_NUMBER, Qt::AscendingOrder);
  mpTblLayouts->setModel(mpProxyModel);
  mpPushButtonDelegate = new CQPushButtonDelegate(CQIconResource::icon(CQIconResource::unknown), QString(), CQPushButtonDelegate::PushButton, this);
  mpTblLayouts->setItemDelegateForColumn(COL_SHOW, mpPushButtonDelegate);
  // Connect the table widget
  connect(mpLayoutsDM, SIGNAL(notifyGUI(ListViews::ObjectType, ListViews::Action, const CCommonName &)),
          this, SLOT(protectedNotify(ListViews::ObjectType, ListViews::Action, const CCommonName &)));
  connect(mpLayoutsDM, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
          this, SLOT(dataChanged(const QModelIndex &, const QModelIndex &)));
  connect(this, SIGNAL(initFilter()), this, SLOT(slotFilterChanged()));
  connect(mpLEFilter, SIGNAL(textChanged(const QString &)),
          this, SLOT(slotFilterChanged()));
  connect(mpPushButtonDelegate, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotShowLayout(const QModelIndex &)));
  connect(mpTblLayouts, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotSelectionChanged()));
}

// virtual
CQLayoutsWidget::~CQLayoutsWidget()
{
  pdelete(mpProxyModel);
}

// virtual
bool CQLayoutsWidget::updateProtected(ListViews::ObjectType objectType, ListViews::Action action, const CCommonName & cn)
{
  if (!mIgnoreUpdates)
    {
      enterProtected();
    }

  return true;
}

// virtual
bool CQLayoutsWidget::leaveProtected()
{
  return true;
}

void CQLayoutsWidget::deleteLayoutWindows()
{
  LayoutWindowMap::iterator it = mLayoutWindowMap.begin(), endit = mLayoutWindowMap.end();

  while (it != endit)
    {
      delete it->second;
      ++it;
    }

  mLayoutWindowMap.clear();
}

void CQLayoutsWidget::deleteSelectedLayouts()
{
  const QItemSelectionModel *pSelectionModel = mpTblLayouts->selectionModel();
  QModelIndexList mappedSelRows;
  size_t i, imax = mpLayoutsDM->rowCount();

  for (i = 0; i < imax; i++)
    {
      if (pSelectionModel->isRowSelected((int) i, QModelIndex()))
        {
          mappedSelRows.append(mpProxyModel->mapToSource(mpProxyModel->index((int) i, 0)));
        }
    }

  if (mappedSelRows.empty()) return;

  // We need to make sure that we remove the window mapped for each layout
  QModelIndexList::const_iterator it = mappedSelRows.begin();
  QModelIndexList::const_iterator end = mappedSelRows.end();
  assert(mpDataModel != NULL);
  CListOfLayouts *pListOfLayouts = mpDataModel->getListOfLayouts();

  for (; it != end; ++it)
    {
      LayoutWindowMap::iterator itWindow = mLayoutWindowMap.find((*pListOfLayouts)[it->row()].getKey());

      if (itWindow != mLayoutWindowMap.end())
        {
          mLayoutWindowMap.erase(itWindow);
          delete itWindow->second;
        }
    }

  mpLayoutsDM->removeRows(mappedSelRows);
}

void CQLayoutsWidget::updateDeleteBtns()
{
  mpBtnDelete->setEnabled(mpTblLayouts->selectionModel()->selectedRows().size() > 0);
  mpBtnClear->setEnabled(mpProxyModel->rowCount() > 0);
}

// virtual
bool CQLayoutsWidget::enterProtected()
{
  QByteArray State = mpTblLayouts->horizontalHeader()->saveState();
  blockSignals(true);

  assert(mpDataModel != NULL);
  CListOfLayouts *pListOfLayouts = mpDataModel->getListOfLayouts();
  mpLayoutsDM->setListOfLayouts(pListOfLayouts);

  // check if we have at least a compartment
  // that we can lay out.

  if (mpDataModel != NULL &&
      mpDataModel->getModel() != NULL &&
      mpDataModel->getModel()->getCompartments().size() > 0)
    {
      mpBtnNew->setEnabled(true);
    }
  else
    {
      mpBtnNew->setEnabled(false);
    }

  // We need to make sure that we have a window mapped for each layout
  CListOfLayouts::const_iterator it = pListOfLayouts->begin();
  CListOfLayouts::const_iterator end = pListOfLayouts->end();

  for (; it != end; ++it)
    {
      LayoutWindowMap::iterator pos = mLayoutWindowMap.find(it->getKey());

      // if this layout does not have an entry in the layout window map, add one
      if (pos == mLayoutWindowMap.end())
        {
          mLayoutWindowMap.insert(std::pair<std::string, LayoutWindow *>(it->getKey(), (LayoutWindow *)NULL));
        }
    }

  updateDeleteBtns();
  mpTblLayouts->horizontalHeader()->restoreState(State);
  blockSignals(false);

  dataChanged(QModelIndex(), QModelIndex());
  emit initFilter();

  return true;
}

void CQLayoutsWidget::showButtons()
{
  int i, imax = mpLayoutsDM->rowCount();

  for (i = 0; i < imax; ++i)
    {
      this->mpTblLayouts->openPersistentEditor(mpProxyModel->index(i, COL_SHOW, QModelIndex()));
    }
}

bool hasLayout(const CListOfLayouts &layouts, const std::string &name)
{
  for (size_t i = 0; i < layouts.size(); ++i)
    {
      const CLayout *layout = &layouts[i];
      const std::string &current = layout->getObjectName();

      if (current == name)
        return true;
    }

  return false;
}

// virtual
void CQLayoutsWidget::slotBtnNewClicked()
{
  const CModel *pModel = mpDataModel->getModel();
  assert(pModel != NULL);
  std::string name = "COPASI autolayout";
  int ncount = 1;

  while (hasLayout(*(mpDataModel->getListOfLayouts()), name))
    {
      std::stringstream str;
      str << "COPASI autolayout " << ncount++;
      name = str.str();
    }

  CQAutolayoutWizard pWizard(*pModel);

  if (pWizard.exec() != QDialog::Accepted)
    return;

  // add the layout to the datamodel
  std::map<std::string, std::string> m;
  CListOfLayouts *pListOfLayouts = mpDataModel->getListOfLayouts();
  // create the random layout
  CCopasiSpringLayout::Parameters p;
  CLayout *pLayout = CCopasiSpringLayout::createLayout(
                       mpDataModel, pWizard.getSelectedCompartments(),
                       pWizard.getSelectedReactions(),
                       pWizard.getSelectedMetabolites(),
                       pWizard.getSideMetabolites(),
                       &p);
  pLayout->setObjectName(name);
  pListOfLayouts->addLayout(pLayout, m);
  // update the table
  mpLayoutsDM->insertRows(mpLayoutsDM->rowCount(), 1);
  dataChanged(QModelIndex(), QModelIndex());
  LayoutWindow *window = createLayoutWindow(pListOfLayouts->size() - 1, pLayout);
  CQNewMainWindow *pWin = dynamic_cast<CQNewMainWindow *>(window);
#ifndef DISABLE_QT_LAYOUT_RENDERING
  CQAnimationWindow *pAnim = dynamic_cast<CQAnimationWindow *>(window);

  if (pAnim != NULL)
    {
      pAnim->show();
      // now we create the spring layout
      pAnim->slotAutoLayout();
    }
  else
#endif //DISABLE_QT_LAYOUT_RENDERING
    if (pWin != NULL)
      {
        pWin->updateRenderer();
        pWin->setMode();
        // show the new layout
        pWin->show();
        pWin->redrawNow();
        // now we create the spring layout
        pWin->slotRunSpringLayout();
      }
    else
      {
        delete pLayout;
      }
}

// virtual
void CQLayoutsWidget::slotBtnDeleteClicked()
{
  if (mpTblLayouts->hasFocus())
    {deleteSelectedLayouts();}
}

// virtual
void CQLayoutsWidget::slotBtnClearClicked()
{
  int ret = CQMessageBox::question(this, tr("Confirm Delete"), "Delete all Layouts?",
                                   QMessageBox::Yes | QMessageBox::No, QMessageBox::No);

  if (ret == QMessageBox::Yes)
    {
      mpLayoutsDM->clear();
      deleteLayoutWindows();
    }
}

// virtual
void CQLayoutsWidget::slotSelectionChanged()
{
  updateDeleteBtns();
}

// virtual
void CQLayoutsWidget::slotDoubleClicked(const QModelIndex proxyIndex)
{
  QModelIndex index = mpProxyModel->mapToSource(proxyIndex);
  int row = index.row();

  if (row >= mpLayoutsDM->rowCount() || row < 0) return;

  slotShowLayout(index);
}

// virtual
void CQLayoutsWidget::dataChanged(const QModelIndex & /* topLeft */,
                                  const QModelIndex & /* bottomRight */)
{
  if (CRootContainer::getConfiguration()->resizeToContents())
    {
      mpTblLayouts->resizeColumnsToContents();
    }

  updateDeleteBtns();
  showButtons();
}

// virtual
void CQLayoutsWidget::slotFilterChanged()
{
  QString Filter = mpLEFilter->text();

  if (Filter.isEmpty())
    {
      mpProxyModel->setFilterRegExp(QRegExp());
      return;
    }

  QRegExp regExp(Filter, Qt::CaseInsensitive, QRegExp::RegExp);
  mpProxyModel->setFilterRegExp(regExp);

  while (mpProxyModel->canFetchMore(QModelIndex()))
    mpProxyModel->fetchMore(QModelIndex());
}

/**
 * This creates a new layout window and return a pointer to it.
 * In case of an error, NULL is returned.
 */
CQLayoutsWidget::LayoutWindow *CQLayoutsWidget::createLayoutWindow(int row, CLayout *pLayout)
{
  if (pLayout == NULL || row < 0) return NULL;

  LayoutWindow *pWin = NULL;
#ifndef DISABLE_QT_LAYOUT_RENDERING

  if (CRootContainer::getConfiguration()->useOpenGL())
    {
      pWin = new CQNewMainWindow(mpDataModel);
      (static_cast<CQNewMainWindow *>(pWin))->slotLayoutChanged(row);
    }
  else
    {
      pWin = new CQAnimationWindow(pLayout, mpDataModel);
    }

#else
  pWin = new CQNewMainWindow(mpDataModel);
  (static_cast<CQNewMainWindow *>(pWin))->slotLayoutChanged(row);
#endif //DISABLE_QT_LAYOUT_RENDERING
  std::string title = "COPASI Diagram: "  + pLayout->getObjectName();
  pWin->setWindowTitle(title.c_str());
  pWin->addToMainWindow();
  pWin->resize(900, 600);
  mLayoutWindowMap[pLayout->getKey()] = pWin;
  return pWin;
}

void CQLayoutsWidget::slotShowLayout(const QModelIndex &index)
{
  int row = index.row();
  assert(mpDataModel != NULL);
  CListOfLayouts *pListOfLayouts = mpDataModel->getListOfLayouts();
  CLayout *pLayout = &pListOfLayouts->operator[](row);
  std::string Key = pLayout->getKey();

  if (pLayout != NULL)
    {
      // check if we already have a widget for the layout
      // if yes, open it, else create one and add it to the map
      LayoutWindow *pLayoutWindow = NULL;
      LayoutWindowMap::iterator pos = mLayoutWindowMap.find(Key);

      if (pos != mLayoutWindowMap.end())
        {
          pLayoutWindow = pos->second;
        }

      if (pLayoutWindow == NULL)
        {
          pLayoutWindow = createLayoutWindow(row, pLayout);
          // need to add it to the list, so the window can be deleted later
          mLayoutWindowMap[pLayout->getKey()] = pLayoutWindow;
        }

      if (pLayoutWindow != NULL)
        {
          CQNewMainWindow *cqWin = dynamic_cast<CQNewMainWindow *>(pLayoutWindow);

          if (cqWin != NULL)
            {
              cqWin ->slotLayoutChanged(row);
              cqWin ->setMode();
            }

          pLayoutWindow->show();
          pLayoutWindow->showNormal();
          pLayoutWindow->activateWindow();
          pLayoutWindow->addToMainWindow();
        }
    }
  else
    {
      //std::cerr << "Could not find layout." << std::endl;
    }
}
<commit_msg>- issue 2965: allow to compile without opengl legacy widget<commit_after>// Copyright (C) 2019 - 2021 by Pedro Mendes, Rector and Visitors of the
// University of Virginia, University of Heidelberg, and University
// of Connecticut School of Medicine.
// All rights reserved.

// Copyright (C) 2017 - 2018 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and University of
// of Connecticut School of Medicine.
// All rights reserved.

// Copyright (C) 2010 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include "CQLayoutsWidget.h"

#include <iostream>

#include "CQMessageBox.h"
#include "CQLayoutsDM.h"
#include "CQSortFilterProxyModel.h"
#include "CQPushButtonDelegate.h"

#include "listviews.h"
#include "qtUtilities.h"
#include "copasi/resourcesUI/CQIconResource.h"

#include "copasi/layout/CLayout.h"
#include "copasi/layout/CListOfLayouts.h"
#include "copasi/model/CModel.h"
#include "copasi/report/CKeyFactory.h"
#include "copasi/CopasiDataModel/CDataModel.h"
#include <copasi/commandline/CConfigurationFile.h>
#include "copasi/core/CRootContainer.h"

#include <copasi/layout/CCopasiSpringLayout.h>

#if WITH_LEGACY_OPENGL
#include "copasi/layoutUI/CQNewMainWindow.h"
#endif

#ifndef DISABLE_QT_LAYOUT_RENDERING
# include <copasi/qlayout/CQAnimationWindow.h>
#endif //DISABLE_QT_LAYOUT_RENDERING

#include "copasi/layoutUI/CQAutolayoutWizard.h"

#include <copasi/UI/copasiui3window.h>

#include <sstream>

CQLayoutsWidget::CQLayoutsWidget(QWidget *parent)
  : CopasiWidget(parent)
{
  setupUi(this);
  // Create Source Data Model.
  mpLayoutsDM = new CQLayoutsDM(this);
  // Create the Proxy Model for sorting/filtering and set its properties.
  mpProxyModel = new CQSortFilterProxyModel();
  mpProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
  mpProxyModel->setFilterKeyColumn(-1);
  mpProxyModel->setSourceModel(mpLayoutsDM);

#if QT_VERSION >= 0x050000
  mpTblLayouts->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
#endif

  if (CRootContainer::getConfiguration()->resizeToContents())
    {
#if QT_VERSION >= 0x050000
      mpTblLayouts->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
#else
      mpTblLayouts->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
#endif
    }

  mpTblLayouts->verticalHeader()->hide();
  mpTblLayouts->sortByColumn(COL_ROW_NUMBER, Qt::AscendingOrder);
  mpTblLayouts->setModel(mpProxyModel);
  mpPushButtonDelegate = new CQPushButtonDelegate(CQIconResource::icon(CQIconResource::unknown), QString(), CQPushButtonDelegate::PushButton, this);
  mpTblLayouts->setItemDelegateForColumn(COL_SHOW, mpPushButtonDelegate);
  // Connect the table widget
  connect(mpLayoutsDM, SIGNAL(notifyGUI(ListViews::ObjectType, ListViews::Action, const CCommonName &)),
          this, SLOT(protectedNotify(ListViews::ObjectType, ListViews::Action, const CCommonName &)));
  connect(mpLayoutsDM, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
          this, SLOT(dataChanged(const QModelIndex &, const QModelIndex &)));
  connect(this, SIGNAL(initFilter()), this, SLOT(slotFilterChanged()));
  connect(mpLEFilter, SIGNAL(textChanged(const QString &)),
          this, SLOT(slotFilterChanged()));
  connect(mpPushButtonDelegate, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotShowLayout(const QModelIndex &)));
  connect(mpTblLayouts, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotSelectionChanged()));
}

// virtual
CQLayoutsWidget::~CQLayoutsWidget()
{
  pdelete(mpProxyModel);
}

// virtual
bool CQLayoutsWidget::updateProtected(ListViews::ObjectType objectType, ListViews::Action action, const CCommonName & cn)
{
  if (!mIgnoreUpdates)
    {
      enterProtected();
    }

  return true;
}

// virtual
bool CQLayoutsWidget::leaveProtected()
{
  return true;
}

void CQLayoutsWidget::deleteLayoutWindows()
{
  LayoutWindowMap::iterator it = mLayoutWindowMap.begin(), endit = mLayoutWindowMap.end();

  while (it != endit)
    {
      delete it->second;
      ++it;
    }

  mLayoutWindowMap.clear();
}

void CQLayoutsWidget::deleteSelectedLayouts()
{
  const QItemSelectionModel *pSelectionModel = mpTblLayouts->selectionModel();
  QModelIndexList mappedSelRows;
  size_t i, imax = mpLayoutsDM->rowCount();

  for (i = 0; i < imax; i++)
    {
      if (pSelectionModel->isRowSelected((int) i, QModelIndex()))
        {
          mappedSelRows.append(mpProxyModel->mapToSource(mpProxyModel->index((int) i, 0)));
        }
    }

  if (mappedSelRows.empty()) return;

  // We need to make sure that we remove the window mapped for each layout
  QModelIndexList::const_iterator it = mappedSelRows.begin();
  QModelIndexList::const_iterator end = mappedSelRows.end();
  assert(mpDataModel != NULL);
  CListOfLayouts *pListOfLayouts = mpDataModel->getListOfLayouts();

  for (; it != end; ++it)
    {
      LayoutWindowMap::iterator itWindow = mLayoutWindowMap.find((*pListOfLayouts)[it->row()].getKey());

      if (itWindow != mLayoutWindowMap.end())
        {
          mLayoutWindowMap.erase(itWindow);
          delete itWindow->second;
        }
    }

  mpLayoutsDM->removeRows(mappedSelRows);
}

void CQLayoutsWidget::updateDeleteBtns()
{
  mpBtnDelete->setEnabled(mpTblLayouts->selectionModel()->selectedRows().size() > 0);
  mpBtnClear->setEnabled(mpProxyModel->rowCount() > 0);
}

// virtual
bool CQLayoutsWidget::enterProtected()
{
  QByteArray State = mpTblLayouts->horizontalHeader()->saveState();
  blockSignals(true);

  assert(mpDataModel != NULL);
  CListOfLayouts *pListOfLayouts = mpDataModel->getListOfLayouts();
  mpLayoutsDM->setListOfLayouts(pListOfLayouts);

  // check if we have at least a compartment
  // that we can lay out.

  if (mpDataModel != NULL &&
      mpDataModel->getModel() != NULL &&
      mpDataModel->getModel()->getCompartments().size() > 0)
    {
      mpBtnNew->setEnabled(true);
    }
  else
    {
      mpBtnNew->setEnabled(false);
    }

  // We need to make sure that we have a window mapped for each layout
  CListOfLayouts::const_iterator it = pListOfLayouts->begin();
  CListOfLayouts::const_iterator end = pListOfLayouts->end();

  for (; it != end; ++it)
    {
      LayoutWindowMap::iterator pos = mLayoutWindowMap.find(it->getKey());

      // if this layout does not have an entry in the layout window map, add one
      if (pos == mLayoutWindowMap.end())
        {
          mLayoutWindowMap.insert(std::pair<std::string, LayoutWindow *>(it->getKey(), (LayoutWindow *)NULL));
        }
    }

  updateDeleteBtns();
  mpTblLayouts->horizontalHeader()->restoreState(State);
  blockSignals(false);

  dataChanged(QModelIndex(), QModelIndex());
  emit initFilter();

  return true;
}

void CQLayoutsWidget::showButtons()
{
  int i, imax = mpLayoutsDM->rowCount();

  for (i = 0; i < imax; ++i)
    {
      this->mpTblLayouts->openPersistentEditor(mpProxyModel->index(i, COL_SHOW, QModelIndex()));
    }
}

bool hasLayout(const CListOfLayouts &layouts, const std::string &name)
{
  for (size_t i = 0; i < layouts.size(); ++i)
    {
      const CLayout *layout = &layouts[i];
      const std::string &current = layout->getObjectName();

      if (current == name)
        return true;
    }

  return false;
}

// virtual
void CQLayoutsWidget::slotBtnNewClicked()
{
  const CModel *pModel = mpDataModel->getModel();
  assert(pModel != NULL);
  std::string name = "COPASI autolayout";
  int ncount = 1;

  while (hasLayout(*(mpDataModel->getListOfLayouts()), name))
    {
      std::stringstream str;
      str << "COPASI autolayout " << ncount++;
      name = str.str();
    }

  CQAutolayoutWizard pWizard(*pModel);

  if (pWizard.exec() != QDialog::Accepted)
    return;

  // add the layout to the datamodel
  std::map<std::string, std::string> m;
  CListOfLayouts *pListOfLayouts = mpDataModel->getListOfLayouts();
  // create the random layout
  CCopasiSpringLayout::Parameters p;
  CLayout *pLayout = CCopasiSpringLayout::createLayout(
                       mpDataModel, pWizard.getSelectedCompartments(),
                       pWizard.getSelectedReactions(),
                       pWizard.getSelectedMetabolites(),
                       pWizard.getSideMetabolites(),
                       &p);
  pLayout->setObjectName(name);
  pListOfLayouts->addLayout(pLayout, m);
  // update the table
  mpLayoutsDM->insertRows(mpLayoutsDM->rowCount(), 1);
  dataChanged(QModelIndex(), QModelIndex());
  LayoutWindow *window = createLayoutWindow(pListOfLayouts->size() - 1, pLayout);
#ifndef DISABLE_QT_LAYOUT_RENDERING
  CQAnimationWindow *pAnim = dynamic_cast<CQAnimationWindow *>(window);

  if (pAnim != NULL)
    {
      pAnim->show();
      // now we create the spring layout
      pAnim->slotAutoLayout();
    }
  else
#endif //DISABLE_QT_LAYOUT_RENDERING
#if WITH_LEGACY_OPENGL
    CQNewMainWindow * pWin = dynamic_cast< CQNewMainWindow * >(window);

  if (pWin != NULL)
    {
      pWin->updateRenderer();
      pWin->setMode();
      // show the new layout
      pWin->show();
      pWin->redrawNow();
      // now we create the spring layout
      pWin->slotRunSpringLayout();
    }
  else
#endif // WITH_LEGACY_OPENGL
    {
      delete pLayout;
    }
}

// virtual
void CQLayoutsWidget::slotBtnDeleteClicked()
{
  if (mpTblLayouts->hasFocus())
    {deleteSelectedLayouts();}
}

// virtual
void CQLayoutsWidget::slotBtnClearClicked()
{
  int ret = CQMessageBox::question(this, tr("Confirm Delete"), "Delete all Layouts?",
                                   QMessageBox::Yes | QMessageBox::No, QMessageBox::No);

  if (ret == QMessageBox::Yes)
    {
      mpLayoutsDM->clear();
      deleteLayoutWindows();
    }
}

// virtual
void CQLayoutsWidget::slotSelectionChanged()
{
  updateDeleteBtns();
}

// virtual
void CQLayoutsWidget::slotDoubleClicked(const QModelIndex proxyIndex)
{
  QModelIndex index = mpProxyModel->mapToSource(proxyIndex);
  int row = index.row();

  if (row >= mpLayoutsDM->rowCount() || row < 0) return;

  slotShowLayout(index);
}

// virtual
void CQLayoutsWidget::dataChanged(const QModelIndex & /* topLeft */,
                                  const QModelIndex & /* bottomRight */)
{
  if (CRootContainer::getConfiguration()->resizeToContents())
    {
      mpTblLayouts->resizeColumnsToContents();
    }

  updateDeleteBtns();
  showButtons();
}

// virtual
void CQLayoutsWidget::slotFilterChanged()
{
  QString Filter = mpLEFilter->text();

  setFilterExpression(mpProxyModel, Filter.isEmpty(), Filter);

  while (mpProxyModel->canFetchMore(QModelIndex()))
    mpProxyModel->fetchMore(QModelIndex());
}

/**
 * This creates a new layout window and return a pointer to it.
 * In case of an error, NULL is returned.
 */
CQLayoutsWidget::LayoutWindow *CQLayoutsWidget::createLayoutWindow(int row, CLayout *pLayout)
{
  if (pLayout == NULL || row < 0) return NULL;

  LayoutWindow *pWin = NULL;
#ifndef DISABLE_QT_LAYOUT_RENDERING
#  if WITH_LEGACY_OPENGL

  if (CRootContainer::getConfiguration()->useOpenGL())
    {
      pWin = new CQNewMainWindow(mpDataModel);
      (static_cast<CQNewMainWindow *>(pWin))->slotLayoutChanged(row);
    }
  else
#endif
    {
      pWin = new CQAnimationWindow(pLayout, mpDataModel);
    }

#else
  pWin = new CQNewMainWindow(mpDataModel);
  (static_cast<CQNewMainWindow *>(pWin))->slotLayoutChanged(row);
#endif //DISABLE_QT_LAYOUT_RENDERING
  std::string title = "COPASI Diagram: "  + pLayout->getObjectName();
  pWin->setWindowTitle(title.c_str());
  pWin->addToMainWindow();
  pWin->resize(900, 600);
  mLayoutWindowMap[pLayout->getKey()] = pWin;
  return pWin;
}

void CQLayoutsWidget::slotShowLayout(const QModelIndex &index)
{
  int row = index.row();
  assert(mpDataModel != NULL);
  CListOfLayouts *pListOfLayouts = mpDataModel->getListOfLayouts();
  CLayout *pLayout = &pListOfLayouts->operator[](row);
  std::string Key = pLayout->getKey();

  if (pLayout != NULL)
    {
      // check if we already have a widget for the layout
      // if yes, open it, else create one and add it to the map
      LayoutWindow *pLayoutWindow = NULL;
      LayoutWindowMap::iterator pos = mLayoutWindowMap.find(Key);

      if (pos != mLayoutWindowMap.end())
        {
          pLayoutWindow = pos->second;
        }

      if (pLayoutWindow == NULL)
        {
          pLayoutWindow = createLayoutWindow(row, pLayout);
          // need to add it to the list, so the window can be deleted later
          mLayoutWindowMap[pLayout->getKey()] = pLayoutWindow;
        }

      if (pLayoutWindow != NULL)
        {
#if WITH_LEGACY_OPENGL
          CQNewMainWindow *cqWin = dynamic_cast<CQNewMainWindow *>(pLayoutWindow);

          if (cqWin != NULL)
            {
              cqWin ->slotLayoutChanged(row);
              cqWin ->setMode();
            }

#endif

          pLayoutWindow->show();
          pLayoutWindow->showNormal();
          pLayoutWindow->activateWindow();
          pLayoutWindow->addToMainWindow();
        }
    }
  else
    {
      //std::cerr << "Could not find layout." << std::endl;
    }
}
<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/function/CFunction.cpp,v $
   $Revision: 1.46 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/06/29 18:47:03 $
   End CVS Header */

#include "copasi.h"

#include "CFunction.h"

CFunction::CFunction(const std::string & name,
                     const CCopasiContainer * pParent,
                     const CEvaluationTree::Type & type):
    CEvaluationTree(name, pParent, type),
    mVariables(),
    mUsageDescriptions(),
    mpCallParameters(NULL)
{}

CFunction::CFunction(const CFunction & src,
                     const CCopasiContainer * pParent):
    CEvaluationTree(src, pParent),
    mVariables(src.mVariables),
    mUsageDescriptions(src.mUsageDescriptions),
    mpCallParameters(NULL)
{}

CFunction::~CFunction()
{}

bool CFunction::setInfix(const std::string & infix)
{
  if (!CEvaluationTree::setInfix(infix)) return false;
  if (!initVariables()) return false;

  return true;
}

bool CFunction::compile()
{return compileNodes();}

unsigned C_INT32 CFunction::getVariableIndex(const std::string & name) const
  {
    CFunctionParameter::DataType VariableType;
    return mVariables.findParameterByName(name, VariableType);
  }

const C_FLOAT64 & CFunction::getVariableValue(const unsigned C_INT32 & index) const
  {return *(*mpCallParameters)[index].value;}

void CFunction::setReversible(const TriLogic & reversible)
{mReversible = reversible;}

const TriLogic & CFunction::isReversible() const
  {return mReversible;}

CFunctionParameters & CFunction::getVariables()
{return mVariables;}

const CFunctionParameters & CFunction::getVariables() const
  {return mVariables;}

bool CFunction::addVariable(const std::string & name,
                            const std::string & usage,
                            const CFunctionParameter::DataType & type)
{return mVariables.add(name, type, usage);}

CCopasiVectorNS < CUsageRange > & CFunction::getUsageDescriptions()
{return mUsageDescriptions;}

const CCopasiVectorNS < CUsageRange > & CFunction::getUsageDescriptions() const
  {return mUsageDescriptions;}

const C_FLOAT64 & CFunction::calcValue(const CCallParameters<C_FLOAT64> & callParameters)
{
  mpCallParameters = & callParameters;

  try
    {
      return mValue = mpRoot->value();
    }
  catch (...)
    {
      return mValue = std::numeric_limits<C_FLOAT64>::quiet_NaN();
    }
}

bool CFunction::dependsOn(const C_FLOAT64 * parameter,
                          const CCallParameters<C_FLOAT64> & callParameters) const
  {
    CCallParameters<C_FLOAT64>::const_iterator it = callParameters.begin();
    CCallParameters<C_FLOAT64>::const_iterator end = callParameters.end();

    while (it != end && parameter != it->value) it++;

    if (it != end)
      return true;
    else
      return false;
  }

void CFunction::addUsage(const std::string& usage,
                         const unsigned C_INT32 & lowerBound,
                         const unsigned C_INT32 & upperBound)
{
  CUsageRange *u;
  u = new CUsageRange();
  u->setUsage(usage);
  u->setLow(lowerBound);
  u->setHigh(upperBound);
  mUsageDescriptions.add(u);
}

void CFunction::load(CReadConfig & configBuffer,
                     CReadConfig::Mode mode)
{
  //  cleanup();

  if (configBuffer.getVersion() < "4")
    {
      C_INT32 Type;
      CUsageRange UsageDescription;

      mode = CReadConfig::SEARCH;
      configBuffer.getVariable("User-defined", "C_INT32", &Type, mode);

      switch (Type)
        {
        case 1:
          setType(UserDefined);
          break;

        default:
          fatalError();
        }

      configBuffer.getVariable("Reversible", "C_INT32", &mReversible);

      configBuffer.getVariable("Substrates", "C_INT32", &Type);
      UsageDescription.setUsage("SUBSTRATE");
      if (Type == 0)
        UsageDescription.setRange(Type, CRange::Infinity);
      else
        UsageDescription.setRange(Type);
      mUsageDescriptions.add(UsageDescription);

      configBuffer.getVariable("Products", "C_INT32", &Type);
      UsageDescription.setUsage("PRODUCT");
      if (Type == 0)
        UsageDescription.setRange(Type, CRange::Infinity);
      else
        UsageDescription.setRange(Type);
      mUsageDescriptions.add(UsageDescription);

      mode = CReadConfig::SEARCH;
    }
  else
    fatalError();

  std::string tmp;
  configBuffer.getVariable("FunctionName", "string", &tmp, mode);
  setObjectName(tmp);

  configBuffer.getVariable("Description", "string", &tmp);
  setInfix(tmp);

  if (configBuffer.getVersion() >= "4")
    {
      unsigned C_INT32 Size;
      configBuffer.getVariable("Reversible", "C_INT32", &mReversible);
      configBuffer.getVariable("UsageDescriptionSize", "C_INT32", &Size);
      mUsageDescriptions.load(configBuffer, Size);
      mVariables.load(configBuffer);
    }

  // For older file version the parameters have to be build from information
  // dependend on the function type. Luckilly, only user defined functions are
  // the only ones occuring in those files.

  guessModifierUsageRange();
}

bool CFunction::initVariables()
{
  if (mpNodeList == NULL) return false;

  std::vector< CEvaluationNode * >::iterator it
  = mpNodeList->begin();
  std::vector< CEvaluationNode * >::iterator end
  = mpNodeList->end();

  for (; it != end; ++it)
    if (CEvaluationNode::type((*it)->getType()) == CEvaluationNode::VARIABLE)
      mVariables.add((*it)->getData(), CFunctionParameter::FLOAT64, "VARIABLE");

  return true;
}

bool CFunction::guessModifierUsageRange()
{
  unsigned C_INT32 imax = mVariables.getNumberOfParametersByUsage("MODIFIER");

  if (imax != 0)
    {
      unsigned C_INT32 pos = 0;

      if (mVariables.getParameterByUsage("MODIFIER", pos).getType() == CFunctionParameter::VFLOAT64)
        addUsage("MODIFIER", 0, CRange::Infinity);
      else
        addUsage("MODIFIER", imax, CRange::NoRange);
    }

  return true;
}
<commit_msg>make constructors also initialise mReversibility<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/function/CFunction.cpp,v $
   $Revision: 1.47 $
   $Name:  $
   $Author: ssahle $
   $Date: 2005/07/29 12:23:38 $
   End CVS Header */

#include "copasi.h"

#include "CFunction.h"

CFunction::CFunction(const std::string & name,
                     const CCopasiContainer * pParent,
                     const CEvaluationTree::Type & type):
    CEvaluationTree(name, pParent, type),
    mVariables(),
    mUsageDescriptions(),
    mpCallParameters(NULL),
    mReversible(TriUnspecified)
{}

CFunction::CFunction(const CFunction & src,
                     const CCopasiContainer * pParent):
    CEvaluationTree(src, pParent),
    mVariables(src.mVariables),
    mUsageDescriptions(src.mUsageDescriptions),
    mpCallParameters(NULL),
    mReversible(src.mReversible)
{}

CFunction::~CFunction()
{}

bool CFunction::setInfix(const std::string & infix)
{
  if (!CEvaluationTree::setInfix(infix)) return false;
  if (!initVariables()) return false;

  return true;
}

bool CFunction::compile()
{return compileNodes();}

unsigned C_INT32 CFunction::getVariableIndex(const std::string & name) const
  {
    CFunctionParameter::DataType VariableType;
    return mVariables.findParameterByName(name, VariableType);
  }

const C_FLOAT64 & CFunction::getVariableValue(const unsigned C_INT32 & index) const
  {return *(*mpCallParameters)[index].value;}

void CFunction::setReversible(const TriLogic & reversible)
{mReversible = reversible;}

const TriLogic & CFunction::isReversible() const
  {return mReversible;}

CFunctionParameters & CFunction::getVariables()
{return mVariables;}

const CFunctionParameters & CFunction::getVariables() const
  {return mVariables;}

bool CFunction::addVariable(const std::string & name,
                            const std::string & usage,
                            const CFunctionParameter::DataType & type)
{return mVariables.add(name, type, usage);}

CCopasiVectorNS < CUsageRange > & CFunction::getUsageDescriptions()
{return mUsageDescriptions;}

const CCopasiVectorNS < CUsageRange > & CFunction::getUsageDescriptions() const
  {return mUsageDescriptions;}

const C_FLOAT64 & CFunction::calcValue(const CCallParameters<C_FLOAT64> & callParameters)
{
  mpCallParameters = & callParameters;

  try
    {
      return mValue = mpRoot->value();
    }
  catch (...)
    {
      return mValue = std::numeric_limits<C_FLOAT64>::quiet_NaN();
    }
}

bool CFunction::dependsOn(const C_FLOAT64 * parameter,
                          const CCallParameters<C_FLOAT64> & callParameters) const
  {
    CCallParameters<C_FLOAT64>::const_iterator it = callParameters.begin();
    CCallParameters<C_FLOAT64>::const_iterator end = callParameters.end();

    while (it != end && parameter != it->value) it++;

    if (it != end)
      return true;
    else
      return false;
  }

void CFunction::addUsage(const std::string& usage,
                         const unsigned C_INT32 & lowerBound,
                         const unsigned C_INT32 & upperBound)
{
  CUsageRange *u;
  u = new CUsageRange();
  u->setUsage(usage);
  u->setLow(lowerBound);
  u->setHigh(upperBound);
  mUsageDescriptions.add(u);
}

void CFunction::load(CReadConfig & configBuffer,
                     CReadConfig::Mode mode)
{
  //  cleanup();

  if (configBuffer.getVersion() < "4")
    {
      C_INT32 Type;
      CUsageRange UsageDescription;

      mode = CReadConfig::SEARCH;
      configBuffer.getVariable("User-defined", "C_INT32", &Type, mode);

      switch (Type)
        {
        case 1:
          setType(UserDefined);
          break;

        default:
          fatalError();
        }

      configBuffer.getVariable("Reversible", "C_INT32", &mReversible);

      configBuffer.getVariable("Substrates", "C_INT32", &Type);
      UsageDescription.setUsage("SUBSTRATE");
      if (Type == 0)
        UsageDescription.setRange(Type, CRange::Infinity);
      else
        UsageDescription.setRange(Type);
      mUsageDescriptions.add(UsageDescription);

      configBuffer.getVariable("Products", "C_INT32", &Type);
      UsageDescription.setUsage("PRODUCT");
      if (Type == 0)
        UsageDescription.setRange(Type, CRange::Infinity);
      else
        UsageDescription.setRange(Type);
      mUsageDescriptions.add(UsageDescription);

      mode = CReadConfig::SEARCH;
    }
  else
    fatalError();

  std::string tmp;
  configBuffer.getVariable("FunctionName", "string", &tmp, mode);
  setObjectName(tmp);

  configBuffer.getVariable("Description", "string", &tmp);
  setInfix(tmp);

  if (configBuffer.getVersion() >= "4")
    {
      unsigned C_INT32 Size;
      configBuffer.getVariable("Reversible", "C_INT32", &mReversible);
      configBuffer.getVariable("UsageDescriptionSize", "C_INT32", &Size);
      mUsageDescriptions.load(configBuffer, Size);
      mVariables.load(configBuffer);
    }

  // For older file version the parameters have to be build from information
  // dependend on the function type. Luckilly, only user defined functions are
  // the only ones occuring in those files.

  guessModifierUsageRange();
}

bool CFunction::initVariables()
{
  if (mpNodeList == NULL) return false;

  std::vector< CEvaluationNode * >::iterator it
  = mpNodeList->begin();
  std::vector< CEvaluationNode * >::iterator end
  = mpNodeList->end();

  for (; it != end; ++it)
    if (CEvaluationNode::type((*it)->getType()) == CEvaluationNode::VARIABLE)
      mVariables.add((*it)->getData(), CFunctionParameter::FLOAT64, "VARIABLE");

  return true;
}

bool CFunction::guessModifierUsageRange()
{
  unsigned C_INT32 imax = mVariables.getNumberOfParametersByUsage("MODIFIER");

  if (imax != 0)
    {
      unsigned C_INT32 pos = 0;

      if (mVariables.getParameterByUsage("MODIFIER", pos).getType() == CFunctionParameter::VFLOAT64)
        addUsage("MODIFIER", 0, CRange::Infinity);
      else
        addUsage("MODIFIER", imax, CRange::NoRange);
    }

  return true;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <boost/asio.hpp>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/service.h>

#include "vtrc-common/vtrc-pool-pair.h"

#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-exception.h"
#include "vtrc-common/vtrc-protocol-layer.h"

#include "vtrc-client-base/vtrc-client.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"
#include "protocol/vtrc-service.pb.h"
#include "protocol/vtrc-errors.pb.h"

#include <boost/random.hpp>
#include <boost/random/random_device.hpp>

#include "vtrc-thread.h"
#include "vtrc-ref.h"
#include "vtrc-bind.h"
#include "vtrc-condition-variable.h"
#include "vtrc-chrono.h"

using namespace vtrc;

void on_connect( const boost::system::error_code &err )
{
    std::cout << "connected "
              << err.value( ) << " "
              << err.message( ) << "\n";
}

struct work_time {
    typedef vtrc::chrono::high_resolution_clock::time_point time_point;
    time_point start_;
    work_time( )
        :start_(vtrc::chrono::high_resolution_clock::now( ))
    {}
    ~work_time( )
    {
        time_point::duration stop(
                    vtrc::chrono::high_resolution_clock::now( ) - start_);
        std::cout << "call time: " << stop << "\n";
    }
};

class ping_impl: public vtrc_service::internal {

    client::vtrc_client *c_;

public:

    ping_impl( client::vtrc_client *c )
        :c_( c )
    {}

    void ping(::google::protobuf::RpcController* controller,
                         const ::vtrc_service::ping_req* request,
                         ::vtrc_service::pong_res* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder chold(done);
        std::cout << "ping event rcvd "
                  << c_->connection( )
                     ->get_call_context( )
                     ->get_lowlevel_message( )->id( )
                  << " " << vtrc::this_thread::get_id( ) << " "
                  //<< vtrc::chrono::high_resolution_clock::now( )
                  << "\n";

        return;

        const vtrc::common::call_context *cc =
                    vtrc::common::call_context::get( c_->connection( ) );

        vtrc::shared_ptr<google::protobuf::RpcChannel>
                ch(c_->create_channel( common::rpc_channel::USE_CONTEXT_CALL ));

        vtrc_service::test_message      mi;
        vtrc_service::test_rpc::Stub s( ch.get( ) );

        s.test2( NULL, &mi, &mi, NULL );

        //if( done ) done->Run( );
    }
};

class test_ev: public vtrc_service::test_events
{
    vtrc::common::connection_iface *c_;
public:
    test_ev( vtrc::common::connection_iface *c )
        :c_( c )
    {}

    void test(::google::protobuf::RpcController* controller,
                         const ::vtrc_service::test_message* request,
                         ::vtrc_service::test_message* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder ch(done);
        std::cout << "test event rcvd "
                  << c_->get_call_context( )->get_lowlevel_message( )->id( )
                  << " " << vtrc::this_thread::get_id( ) << " "
                  << "\n";
    }

};

void run_client( vtrc::shared_ptr<client::vtrc_client> cl, bool wait)
{
    vtrc::shared_ptr<google::protobuf::RpcChannel>
            ch(cl->create_channel( wait ? common::rpc_channel::DISABLE_WAIT
                                        : common::rpc_channel::DEFAULT ));
    vtrc_service::test_rpc::Stub s( ch.get( ) );

    vtrc_service::test_message mi;
    vtrc_service::test_message mir;

    size_t last = 0;

    std::string ts(1024 * 800, 0);

    std::cout << "this thread: "
              << vtrc::this_thread::get_id( ) << " "
              << "\n";

    for( int i=0; i<29999999999; ++i ) {
        try {

            if( wait )
                vtrc::this_thread::sleep_for(
                            vtrc::chrono::microseconds(500) );
            work_time wt;
            //mi.set_b( ts );
            s.test( NULL, &mi, &mir, NULL );
            last = i; //mir.id( );
            std::cout << "response: " << last << "\n";
            //cl.reset( );
        } catch( const vtrc::common::exception &ex ) {
            std::cout << "call error: "
                      << " code (" << ex.code( ) << ")"
                      << " category (" << ex.category( ) << ")"
                      << " what: " << ex.what( )
                      << " (" << ex.additional( ) << ")"
                      << "\n";
            //if( i % 100 == 0 )
            std::cout << i << "\n";
            if( ex.category( ) == vtrc_errors::CATEGORY_SYSTEM ) break;
            if( ex.code( ) == vtrc_errors::ERR_COMM ) break;
        } catch( const std::exception &ex ) {
            //std::cout << "call error: " << ex.what( ) << "\n";
        }
    }
}

void on_init_error(const vtrc_errors::container &cont, const char *message )
{
    std::cout << "Client init error: " << message << "\n";
}

void on_connect( )
{
    std::cout << "on_connect\n";
}

void on_ready( vtrc::condition_variable &cond )
{
    std::cout << "on_ready\n";
    cond.notify_all( );
}

void on_disconnect( vtrc::condition_variable &cond )
{
    std::cout << "on_disconnect\n";
    cond.notify_all( );
}

int main( )
{
    common::pool_pair pp(2, 2);
    vtrc::shared_ptr<client::vtrc_client> cl(client::vtrc_client::create(pp));

    //cl->set_session_key( "1234" );

    vtrc::mutex              mut;
    vtrc::condition_variable cond;

    cl->get_on_connect( ).connect( boost::bind( on_connect ) );
    cl->get_on_ready( ).connect( boost::bind( on_ready, vtrc::ref(cond) ));
    cl->get_on_disconnect( ).connect( boost::bind( on_disconnect, vtrc::ref(cond) ));
    cl->get_on_init_error( ).connect( boost::bind( on_init_error, _1, _2 ) );

    //cl->connect( "/tmp/test.socket" );
    //cl->connect( "192.168.56.101", "44667" );
    //cl->connect( "\\\\.\\pipe\\test_pipe");
    cl->connect( "127.0.0.1", "44667" );
    //cl->connect( "::1", "44668" );
    ///cl->async_connect( "127.0.0.1", "44667", on_connect );

    cl->assign_rpc_handler( vtrc::shared_ptr<test_ev>(new test_ev(cl->connection( ).get( ))) );
    cl->assign_rpc_handler( vtrc::shared_ptr<ping_impl>(new ping_impl(cl.get( ))) );

    vtrc::unique_lock<vtrc::mutex>  lck(mut);
    cond.wait( lck, vtrc::bind( &client::vtrc_client::ready, cl ) );

    std::cout << "start program\n";

    //vtrc::thread( run_client, cl, true ).detach( );
    //vtrc::thread( run_client, cl, false ).detach( );

    vtrc::thread r( run_client, cl, false );

    //cond.wait( lck );
    r.join( );

    pp.stop_all( );
    pp.join_all( );

    return 0;

}
<commit_msg>proto<commit_after>#include <iostream>
#include <boost/asio.hpp>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/service.h>

#include "vtrc-common/vtrc-pool-pair.h"

#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-exception.h"
#include "vtrc-common/vtrc-protocol-layer.h"

#include "vtrc-client-base/vtrc-client.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"
#include "protocol/vtrc-service.pb.h"
#include "protocol/vtrc-errors.pb.h"

#include <boost/random.hpp>
#include <boost/random/random_device.hpp>

#include "vtrc-thread.h"
#include "vtrc-ref.h"
#include "vtrc-bind.h"
#include "vtrc-condition-variable.h"
#include "vtrc-chrono.h"

using namespace vtrc;

void on_connect( const boost::system::error_code &err )
{
    std::cout << "connected "
              << err.value( ) << " "
              << err.message( ) << "\n";
}

struct work_time {
    typedef vtrc::chrono::high_resolution_clock::time_point time_point;
    time_point start_;
    work_time( )
        :start_(vtrc::chrono::high_resolution_clock::now( ))
    {}
    ~work_time( )
    {
        time_point::duration stop(
                    vtrc::chrono::high_resolution_clock::now( ) - start_);
        std::cout << "call time: " << stop << "\n";
    }
};

class ping_impl: public vtrc_service::internal {

    client::vtrc_client *c_;

public:

    ping_impl( client::vtrc_client *c )
        :c_( c )
    {}

    void ping(::google::protobuf::RpcController* controller,
                         const ::vtrc_service::ping_req* request,
                         ::vtrc_service::pong_res* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder chold(done);
        std::cout << "ping event rcvd "
                  << c_->connection( )
                     ->get_call_context( )
                     ->get_lowlevel_message( )->id( )
                  << " " << vtrc::this_thread::get_id( ) << " "
                  //<< vtrc::chrono::high_resolution_clock::now( )
                  << "\n";

        return;

        const vtrc::common::call_context *cc =
                    vtrc::common::call_context::get( c_->connection( ) );

        vtrc::shared_ptr<google::protobuf::RpcChannel>
                ch(c_->create_channel( common::rpc_channel::USE_CONTEXT_CALL ));

        vtrc_service::test_message      mi;
        vtrc_service::test_rpc::Stub s( ch.get( ) );

        s.test2( NULL, &mi, &mi, NULL );

        //if( done ) done->Run( );
    }
};

class test_ev: public vtrc_service::test_events
{
    vtrc::common::connection_iface *c_;
public:
    test_ev( vtrc::common::connection_iface *c )
        :c_( c )
    {}

    void test(::google::protobuf::RpcController* controller,
                         const ::vtrc_service::test_message* request,
                         ::vtrc_service::test_message* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder ch(done);
        std::cout << "test event rcvd "
                  << c_->get_call_context( )->get_lowlevel_message( )->id( )
                  << " " << vtrc::this_thread::get_id( ) << " "
                  << "\n";
    }

};

void run_client( vtrc::shared_ptr<client::vtrc_client> cl, bool wait)
{
    vtrc::shared_ptr<google::protobuf::RpcChannel>
            ch(cl->create_channel( wait ? common::rpc_channel::DISABLE_WAIT
                                        : common::rpc_channel::DEFAULT ));
    vtrc_service::test_rpc::Stub s( ch.get( ) );

    vtrc_service::test_message mi;
    vtrc_service::test_message mir;

    size_t last = 0;

    std::string ts(1024 * 800, 0);

    std::cout << "this thread: "
              << vtrc::this_thread::get_id( ) << " "
              << "\n";

    for( int i=0; i<29999999999; ++i ) {
        try {

            if( wait )
                vtrc::this_thread::sleep_for(
                            vtrc::chrono::microseconds(500) );
            work_time wt;
            //mi.set_b( ts );
            s.test( NULL, &mi, &mir, NULL );
            last = i; //mir.id( );
            std::cout << "response: " << last << "\n";
            //cl.reset( );
        } catch( const vtrc::common::exception &ex ) {
            std::cout << "call error: "
                      << " code (" << ex.code( ) << ")"
                      << " category (" << ex.category( ) << ")"
                      << " what: " << ex.what( )
                      << " (" << ex.additional( ) << ")"
                      << "\n";
            //if( i % 100 == 0 )
            std::cout << i << "\n";
            if( ex.category( ) == vtrc_errors::CATEGORY_SYSTEM ) break;
            if( ex.code( ) == vtrc_errors::ERR_COMM ) break;
        } catch( const std::exception &ex ) {
            //std::cout << "call error: " << ex.what( ) << "\n";
        }
    }
}

void on_init_error(const vtrc_errors::container &cont, const char *message )
{
    std::cout << "Client init error: " << message << "\n";
    std::cout << cont.DebugString( );
}

void on_connect( )
{
    std::cout << "on_connect\n";
}

void on_ready( vtrc::condition_variable &cond )
{
    std::cout << "on_ready\n";
    cond.notify_all( );
}

void on_disconnect( vtrc::condition_variable &cond )
{
    std::cout << "on_disconnect\n";
    cond.notify_all( );
}

int main( )
{
    common::pool_pair pp(2, 2);
    vtrc::shared_ptr<client::vtrc_client> cl(client::vtrc_client::create(pp));

    cl->set_session_key( "1234" );

    vtrc::mutex              mut;
    vtrc::condition_variable cond;

    cl->get_on_connect( ).connect( boost::bind( on_connect ) );
    cl->get_on_ready( ).connect( boost::bind( on_ready, vtrc::ref(cond) ));
    cl->get_on_disconnect( ).connect( boost::bind( on_disconnect, vtrc::ref(cond) ));
    cl->get_on_init_error( ).connect( boost::bind( on_init_error, _1, _2 ) );

    //cl->connect( "/tmp/test.socket" );
    //cl->connect( "192.168.56.101", "44667" );
    //cl->connect( "\\\\.\\pipe\\test_pipe");
    cl->connect( "127.0.0.1", "44667" );
    //cl->connect( "::1", "44668" );
    ///cl->async_connect( "127.0.0.1", "44667", on_connect );

    cl->assign_rpc_handler( vtrc::shared_ptr<test_ev>(new test_ev(cl->connection( ).get( ))) );
    cl->assign_rpc_handler( vtrc::shared_ptr<ping_impl>(new ping_impl(cl.get( ))) );

    vtrc::unique_lock<vtrc::mutex>  lck(mut);
    cond.wait( lck, vtrc::bind( &client::vtrc_client::ready, cl ) );

    std::cout << "start program\n";

    //vtrc::thread( run_client, cl, true ).detach( );
    //vtrc::thread( run_client, cl, false ).detach( );

    vtrc::thread r( run_client, cl, false );

    //cond.wait( lck );
    r.join( );

    pp.stop_all( );
    pp.join_all( );

    return 0;

}
<|endoftext|>


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

#include "views/widget/gtk_views_fixed.h"

#include "base/logging.h"

// We store whether we use the widget's allocated size as a property. Ideally
// we would stash this in GtkFixedChild, but GtkFixed doesn't allow subclassing
// gtk_fixed_put. Alternatively we could subclass GtkContainer and use our own
// API (effectively duplicating GtkFixed), but that means folks could no longer
// use the GtkFixed API else where in Chrome. For now I'm going with this route.
static const char* kUseAllocatedSize = "__VIEWS_USE_ALLOCATED_SIZE__";
static const char* kRequisitionWidth = "__VIEWS_REQUISITION_WIDTH__";
static const char* kRequisitionHeight = "__VIEWS_REQUISITION_HEIGHT__";

G_BEGIN_DECLS

G_DEFINE_TYPE(GtkViewsFixed, gtk_views_fixed, GTK_TYPE_FIXED)

static void gtk_views_fixed_size_allocate(GtkWidget* widget,
                                          GtkAllocation* allocation) {
  widget->allocation = *allocation;
  if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) {
    gdk_window_move_resize(widget->window, allocation->x, allocation->y,
                           allocation->width, allocation->height);
  }

  int border_width = GTK_CONTAINER(widget)->border_width;
  GList* children = GTK_FIXED(widget)->children;
  while (children) {
    GtkFixedChild* child = reinterpret_cast<GtkFixedChild*>(children->data);
    children = children->next;

    if (GTK_WIDGET_VISIBLE(child->widget)) {
      GtkAllocation child_allocation;

      int width, height;
      bool use_allocated_size =
          gtk_views_fixed_get_widget_size(child->widget, &width, &height);
      if (use_allocated_size) {
        // NOTE: even though the size isn't changing, we have to call
        // size_allocate, otherwise things like buttons won't repaint.
        child_allocation.width = width;
        child_allocation.height = height;
      } else {
        GtkRequisition child_requisition;
        gtk_widget_get_child_requisition(child->widget, &child_requisition);
        child_allocation.width = child_requisition.width;
        child_allocation.height = child_requisition.height;
      }
      child_allocation.x = child->x + border_width;
      child_allocation.y = child->y + border_width;

      if (GTK_WIDGET_NO_WINDOW(widget)) {
        child_allocation.x += widget->allocation.x;
        child_allocation.y += widget->allocation.y;
      }

      gtk_widget_size_allocate(child->widget, &child_allocation);
    }
  }
}

static void gtk_views_fixed_class_init(GtkViewsFixedClass* views_fixed_class) {
  GtkWidgetClass* widget_class =
      reinterpret_cast<GtkWidgetClass*>(views_fixed_class);
  widget_class->size_allocate = gtk_views_fixed_size_allocate;
}

static void gtk_views_fixed_init(GtkViewsFixed* fixed) {
}

GtkWidget* gtk_views_fixed_new(void) {
  return GTK_WIDGET(g_object_new(GTK_TYPE_VIEWS_FIXED, NULL));
}

void gtk_views_fixed_set_widget_size(GtkWidget* widget,
                                     int width, int height) {
  // Remember the allocation request, and set this widget up to use it.
  bool use_requested_size = (width != 0 && height != 0);
  g_object_set_data(G_OBJECT(widget), kUseAllocatedSize,
                    reinterpret_cast<gpointer>(use_requested_size ? 1 : 0));
  g_object_set_data(G_OBJECT(widget), kRequisitionWidth,
                    reinterpret_cast<gpointer>(width));
  g_object_set_data(G_OBJECT(widget), kRequisitionHeight,
                    reinterpret_cast<gpointer>(height));

  gtk_widget_queue_resize(widget);
}

bool gtk_views_fixed_get_widget_size(GtkWidget* widget,
                                     int* width, int* height) {
  DCHECK(width);
  DCHECK(height);
  *width = reinterpret_cast<glong>(g_object_get_data(G_OBJECT(widget),
                                                     kRequisitionWidth));
  *height = reinterpret_cast<glong>(g_object_get_data(G_OBJECT(widget),
                                                      kRequisitionHeight));
  return (g_object_get_data(G_OBJECT(widget), kUseAllocatedSize) != 0);
}

G_END_DECLS
<commit_msg>widget-gtk: Make it possible to grab focus.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/widget/gtk_views_fixed.h"

#include "base/logging.h"

// We store whether we use the widget's allocated size as a property. Ideally
// we would stash this in GtkFixedChild, but GtkFixed doesn't allow subclassing
// gtk_fixed_put. Alternatively we could subclass GtkContainer and use our own
// API (effectively duplicating GtkFixed), but that means folks could no longer
// use the GtkFixed API else where in Chrome. For now I'm going with this route.
static const char* kUseAllocatedSize = "__VIEWS_USE_ALLOCATED_SIZE__";
static const char* kRequisitionWidth = "__VIEWS_REQUISITION_WIDTH__";
static const char* kRequisitionHeight = "__VIEWS_REQUISITION_HEIGHT__";

G_BEGIN_DECLS

G_DEFINE_TYPE(GtkViewsFixed, gtk_views_fixed, GTK_TYPE_FIXED)

static void gtk_views_fixed_size_allocate(GtkWidget* widget,
                                          GtkAllocation* allocation) {
  widget->allocation = *allocation;
  if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) {
    gdk_window_move_resize(widget->window, allocation->x, allocation->y,
                           allocation->width, allocation->height);
  }

  int border_width = GTK_CONTAINER(widget)->border_width;
  GList* children = GTK_FIXED(widget)->children;
  while (children) {
    GtkFixedChild* child = reinterpret_cast<GtkFixedChild*>(children->data);
    children = children->next;

    if (GTK_WIDGET_VISIBLE(child->widget)) {
      GtkAllocation child_allocation;

      int width, height;
      bool use_allocated_size =
          gtk_views_fixed_get_widget_size(child->widget, &width, &height);
      if (use_allocated_size) {
        // NOTE: even though the size isn't changing, we have to call
        // size_allocate, otherwise things like buttons won't repaint.
        child_allocation.width = width;
        child_allocation.height = height;
      } else {
        GtkRequisition child_requisition;
        gtk_widget_get_child_requisition(child->widget, &child_requisition);
        child_allocation.width = child_requisition.width;
        child_allocation.height = child_requisition.height;
      }
      child_allocation.x = child->x + border_width;
      child_allocation.y = child->y + border_width;

      if (GTK_WIDGET_NO_WINDOW(widget)) {
        child_allocation.x += widget->allocation.x;
        child_allocation.y += widget->allocation.y;
      }

      gtk_widget_size_allocate(child->widget, &child_allocation);
    }
  }
}

static void gtk_views_fixed_class_init(GtkViewsFixedClass* views_fixed_class) {
  GtkWidgetClass* widget_class =
      reinterpret_cast<GtkWidgetClass*>(views_fixed_class);
  widget_class->size_allocate = gtk_views_fixed_size_allocate;
}

static void gtk_views_fixed_init(GtkViewsFixed* fixed) {
  GTK_WIDGET_SET_FLAGS(GTK_WIDGET(fixed), GTK_CAN_FOCUS);
}

GtkWidget* gtk_views_fixed_new(void) {
  return GTK_WIDGET(g_object_new(GTK_TYPE_VIEWS_FIXED, NULL));
}

void gtk_views_fixed_set_widget_size(GtkWidget* widget,
                                     int width, int height) {
  // Remember the allocation request, and set this widget up to use it.
  bool use_requested_size = (width != 0 && height != 0);
  g_object_set_data(G_OBJECT(widget), kUseAllocatedSize,
                    reinterpret_cast<gpointer>(use_requested_size ? 1 : 0));
  g_object_set_data(G_OBJECT(widget), kRequisitionWidth,
                    reinterpret_cast<gpointer>(width));
  g_object_set_data(G_OBJECT(widget), kRequisitionHeight,
                    reinterpret_cast<gpointer>(height));

  gtk_widget_queue_resize(widget);
}

bool gtk_views_fixed_get_widget_size(GtkWidget* widget,
                                     int* width, int* height) {
  DCHECK(width);
  DCHECK(height);
  *width = reinterpret_cast<glong>(g_object_get_data(G_OBJECT(widget),
                                                     kRequisitionWidth));
  *height = reinterpret_cast<glong>(g_object_get_data(G_OBJECT(widget),
                                                      kRequisitionHeight));
  return (g_object_get_data(G_OBJECT(widget), kUseAllocatedSize) != 0);
}

G_END_DECLS
<|endoftext|>


<commit_before>#include "SDBPRequestMessage.h"

bool SDBPRequestMessage::Read(ReadBuffer& buffer)
{
    int         read;
    unsigned    i, numNodes;
    uint64_t    nodeID;

    if (buffer.GetLength() < 1)
        return false;

    switch (buffer.GetCharAt(0))
    {
        /* Master query */
        case CLIENTREQUEST_GET_MASTER:
            read = buffer.Readf("%c:%U",
             &request->type, &request->commandID);
            break;

        /* Get config state: databases, tables, shards, quora */
        case CLIENTREQUEST_GET_CONFIG_STATE:
            read = buffer.Readf("%c:%U",
             &request->type, &request->commandID);
            break;

        /* Quorum management */
        case CLIENTREQUEST_CREATE_QUORUM:
            read = buffer.Readf("%c:%U:%c:%U",
             &request->type, &request->commandID, &request->productionType,
             numNodes);
            if (read < 0 || read == (signed)buffer.GetLength())
                return false;
            buffer.Advance(read);
            for (i = 0; i < numNodes; i++)
            {
                read = buffer.Readf(":%U", nodeID);
                if (read < 0)
                    return false;
                buffer.Advance(read);
                request->nodes.Append(nodeID);
            }
            if (buffer.GetLength() == 0)
                return true;
            else
                return false;
            break;

        /* Database management */
        case CLIENTREQUEST_CREATE_DATABASE:
            read = buffer.Readf("%c:%U:%c:%#B",
             &request->type, &request->commandID, &request->productionType,
             &request->name);
            break;
        case CLIENTREQUEST_RENAME_DATABASE:
            read = buffer.Readf("%c:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->name);
            break;
        case CLIENTREQUEST_DELETE_DATABASE:
            read = buffer.Readf("%c:%U:%U",
             &request->type, &request->commandID, &request->databaseID);
            break;

        /* Table management */
        case CLIENTREQUEST_CREATE_TABLE:
            read = buffer.Readf("%c:%U:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->quorumID, &request->name);
            break;
        case CLIENTREQUEST_RENAME_TABLE:
            read = buffer.Readf("%c:%U:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID, &request->name);
            break;
        case CLIENTREQUEST_DELETE_TABLE:
            read = buffer.Readf("%c:%U:%U:%U",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID);
            break;

        /* Data operations */
        case CLIENTREQUEST_GET:
            read = buffer.Readf("%c:%U:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID, &request->key);
            break;
        case CLIENTREQUEST_SET:
            read = buffer.Readf("%c:%U:%U:%U:%#B:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID, &request->key, &request->value);
            break;
        case CLIENTREQUEST_DELETE:
            read = buffer.Readf("%c:%U:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID, &request->key);
            break;
        default:
            return false;
    }

    return (read == (signed)buffer.GetLength() ? true : false);
}

bool SDBPRequestMessage::Write(Buffer& buffer)
{
    uint64_t*   it;

    switch (request->type)
    {
        /* Master query */
        case CLIENTREQUEST_GET_MASTER:
            buffer.Writef("%c:%U",
             request->type, request->commandID);
            return true;

        /* Get config state: databases, tables, shards, quora */
        case CLIENTREQUEST_GET_CONFIG_STATE:
            buffer.Writef("%c:%U",
             request->type, request->commandID);
            return true;

        /* Quorum management */
        case CLIENTREQUEST_CREATE_QUORUM:
            buffer.Writef("%c:%U:%c:%U",
             request->type, request->commandID, request->productionType,
             request->nodes.GetLength());
            for (it = request->nodes.First(); it != NULL; it = request->nodes.Next(it))
                buffer.Appendf(":%U", *it);

        /* Database management */
        case CLIENTREQUEST_CREATE_DATABASE:
            buffer.Writef("%c:%U:%c:%#B",
             request->type, request->commandID, request->productionType,
             &request->name);
            return true;
        case CLIENTREQUEST_RENAME_DATABASE:
            buffer.Writef("%c:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             &request->name);
            return true;
        case CLIENTREQUEST_DELETE_DATABASE:
            buffer.Writef("%c:%U:%U",
             request->type, request->commandID, request->databaseID);
            return true;

        /* Table management */
        case CLIENTREQUEST_CREATE_TABLE:
            buffer.Writef("%c:%U:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             request->quorumID, &request->name);
            return true;
        case CLIENTREQUEST_RENAME_TABLE:
            buffer.Writef("%c:%U:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             request->tableID, &request->name);
            return true;
        case CLIENTREQUEST_DELETE_TABLE:
            buffer.Writef("%c:%U:%U:%U",
             request->type, request->commandID, request->databaseID,
             request->tableID);
            return true;

        /* Data operations */
        case CLIENTREQUEST_GET:
            buffer.Writef("%c:%U:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             request->tableID, &request->key);
            return true;
        case CLIENTREQUEST_SET:
            buffer.Writef("%c:%U:%U:%U:%#B:%#B",
             request->type, request->commandID, request->databaseID,
             request->tableID, &request->key, &request->value);
            return true;
        case CLIENTREQUEST_DELETE:
            buffer.Writef("%c:%U:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             request->tableID, &request->key);
            return true;

        default:
            return false;
    }

    return true;
}
<commit_msg>Fixed Readf bug in SDBPRequestMessage.<commit_after>#include "SDBPRequestMessage.h"

bool SDBPRequestMessage::Read(ReadBuffer& buffer)
{
    int         read;
    unsigned    i, numNodes;
    uint64_t    nodeID;

    if (buffer.GetLength() < 1)
        return false;

    switch (buffer.GetCharAt(0))
    {
        /* Master query */
        case CLIENTREQUEST_GET_MASTER:
            read = buffer.Readf("%c:%U",
             &request->type, &request->commandID);
            break;

        /* Get config state: databases, tables, shards, quora */
        case CLIENTREQUEST_GET_CONFIG_STATE:
            read = buffer.Readf("%c:%U",
             &request->type, &request->commandID);
            break;

        /* Quorum management */
        case CLIENTREQUEST_CREATE_QUORUM:
            read = buffer.Readf("%c:%U:%c:%u",
             &request->type, &request->commandID, &request->productionType,
             &numNodes);
            if (read < 0 || read == (signed)buffer.GetLength())
                return false;
            buffer.Advance(read);
            for (i = 0; i < numNodes; i++)
            {
                read = buffer.Readf(":%U", &nodeID);
                if (read < 0)
                    return false;
                buffer.Advance(read);
                request->nodes.Append(nodeID);
            }
            if (buffer.GetLength() == 0)
                return true;
            else
                return false;
            break;

        /* Database management */
        case CLIENTREQUEST_CREATE_DATABASE:
            read = buffer.Readf("%c:%U:%c:%#B",
             &request->type, &request->commandID, &request->productionType,
             &request->name);
            break;
        case CLIENTREQUEST_RENAME_DATABASE:
            read = buffer.Readf("%c:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->name);
            break;
        case CLIENTREQUEST_DELETE_DATABASE:
            read = buffer.Readf("%c:%U:%U",
             &request->type, &request->commandID, &request->databaseID);
            break;

        /* Table management */
        case CLIENTREQUEST_CREATE_TABLE:
            read = buffer.Readf("%c:%U:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->quorumID, &request->name);
            break;
        case CLIENTREQUEST_RENAME_TABLE:
            read = buffer.Readf("%c:%U:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID, &request->name);
            break;
        case CLIENTREQUEST_DELETE_TABLE:
            read = buffer.Readf("%c:%U:%U:%U",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID);
            break;

        /* Data operations */
        case CLIENTREQUEST_GET:
            read = buffer.Readf("%c:%U:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID, &request->key);
            break;
        case CLIENTREQUEST_SET:
            read = buffer.Readf("%c:%U:%U:%U:%#B:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID, &request->key, &request->value);
            break;
        case CLIENTREQUEST_DELETE:
            read = buffer.Readf("%c:%U:%U:%U:%#B",
             &request->type, &request->commandID, &request->databaseID,
             &request->tableID, &request->key);
            break;
        default:
            return false;
    }

    return (read == (signed)buffer.GetLength() ? true : false);
}

bool SDBPRequestMessage::Write(Buffer& buffer)
{
    uint64_t*   it;

    switch (request->type)
    {
        /* Master query */
        case CLIENTREQUEST_GET_MASTER:
            buffer.Writef("%c:%U",
             request->type, request->commandID);
            return true;

        /* Get config state: databases, tables, shards, quora */
        case CLIENTREQUEST_GET_CONFIG_STATE:
            buffer.Writef("%c:%U",
             request->type, request->commandID);
            return true;

        /* Quorum management */
        case CLIENTREQUEST_CREATE_QUORUM:
            buffer.Writef("%c:%U:%c:%U",
             request->type, request->commandID, request->productionType,
             request->nodes.GetLength());
            for (it = request->nodes.First(); it != NULL; it = request->nodes.Next(it))
                buffer.Appendf(":%U", *it);

        /* Database management */
        case CLIENTREQUEST_CREATE_DATABASE:
            buffer.Writef("%c:%U:%c:%#B",
             request->type, request->commandID, request->productionType,
             &request->name);
            return true;
        case CLIENTREQUEST_RENAME_DATABASE:
            buffer.Writef("%c:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             &request->name);
            return true;
        case CLIENTREQUEST_DELETE_DATABASE:
            buffer.Writef("%c:%U:%U",
             request->type, request->commandID, request->databaseID);
            return true;

        /* Table management */
        case CLIENTREQUEST_CREATE_TABLE:
            buffer.Writef("%c:%U:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             request->quorumID, &request->name);
            return true;
        case CLIENTREQUEST_RENAME_TABLE:
            buffer.Writef("%c:%U:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             request->tableID, &request->name);
            return true;
        case CLIENTREQUEST_DELETE_TABLE:
            buffer.Writef("%c:%U:%U:%U",
             request->type, request->commandID, request->databaseID,
             request->tableID);
            return true;

        /* Data operations */
        case CLIENTREQUEST_GET:
            buffer.Writef("%c:%U:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             request->tableID, &request->key);
            return true;
        case CLIENTREQUEST_SET:
            buffer.Writef("%c:%U:%U:%U:%#B:%#B",
             request->type, request->commandID, request->databaseID,
             request->tableID, &request->key, &request->value);
            return true;
        case CLIENTREQUEST_DELETE:
            buffer.Writef("%c:%U:%U:%U:%#B",
             request->type, request->commandID, request->databaseID,
             request->tableID, &request->key);
            return true;

        default:
            return false;
    }

    return true;
}
<|endoftext|>


<commit_before>#include "QtcDbViewerPlugin.h"
#include "Constants.h"
#include "WMain.h"

#include <QCoreApplication>
#include <QTranslator>

#include <QtPlugin>

#include <coreplugin/icore.h>
#include <coreplugin/imode.h>
#include <utils/icon.h>
#include <coreplugin/actionmanager/actionmanager.h>

using namespace QtcDbViewer::Internal;

const Utils::Icon MODE_DATABASE_CLASSIC(
        QLatin1String(":/icons/database.png"));
const Utils::Icon MODE_DATABASE_FLAT({
        {QLatin1String(":/icons/database_mask.png"), Utils::Theme::IconsBaseColor}});
const Utils::Icon MODE_DATABASE_FLAT_ACTIVE({
        {QLatin1String(":/icons/database_mask.png"), Utils::Theme::IconsModeDesignActiveColor}});

QtcDbViewerPlugin::QtcDbViewerPlugin () :
  IPlugin () {
  // Create your members
}

QtcDbViewerPlugin::~QtcDbViewerPlugin () {
  // Unregister objects from the plugin manager's object pool
  // Delete members
}

bool QtcDbViewerPlugin::initialize (const QStringList &arguments, QString *errorString) {
  // Register objects in the plugin manager's object pool
  // Load settings
  // Add actions to menus
  // Connect to other plugins' signals
  // In the initialize function, a plugin can be sure that the plugins it
  // depends on have initialized their members.

  Q_UNUSED (arguments)
  Q_UNUSED (errorString)

  initLanguage ();

  auto context = Core::Context (Constants::QTCDBVIEWER_CONTEXT);

  auto viewer = new WMain;
  auto buttons = viewer->findChildren<QToolButton *>();
  for (auto button: buttons) {
    if (button->toolTip ().isEmpty ()) {
      continue;
    }
    auto *proxyAction = new QAction (button->toolTip (), button);
    connect (proxyAction, SIGNAL (triggered (bool)), button, SIGNAL (clicked (bool)));

    auto id = Core::Id::fromString (QStringLiteral ("QtcDbViewer.") + button->objectName ());
    auto *cmd = Core::ActionManager::registerAction (proxyAction, id, context);
    cmd->setDefaultKeySequence (button->shortcut ().toString ());
    button->setShortcut (QString ());
    connect (cmd, &Core::Command::keySequenceChanged, [button, proxyAction, cmd]() {
      QString tooltip = proxyAction->text ();
      if (!cmd->keySequence ().isEmpty ()) {
        tooltip += QString (QStringLiteral (" (%1)")).arg (cmd->keySequence ().toString ());
      }
      button->setToolTip (tooltip);
    });
    cmd->keySequenceChanged ();
  }

  Core::IMode *dbViewMode = new Core::IMode;
  dbViewMode->setId (Constants::QTCDBVIEWER_ID);
  dbViewMode->setContext (context);
  dbViewMode->setDisplayName (tr ("Db Viewer"));
  dbViewMode->setIcon (Utils::Icon::modeIcon (MODE_DATABASE_CLASSIC,
                                              MODE_DATABASE_FLAT, MODE_DATABASE_FLAT_ACTIVE));
  dbViewMode->setPriority (10);
  dbViewMode->setWidget (viewer);
  addAutoReleasedObject (dbViewMode);

  return true;
}

void QtcDbViewerPlugin::initLanguage () {
  const QString &language = Core::ICore::userInterfaceLanguage ();
  if (!language.isEmpty ()) {
    QStringList paths;
    paths << Core::ICore::resourcePath () << Core::ICore::userResourcePath ();
    const QString &trFile = QLatin1String ("QtcDbViewer_") + language;
    QTranslator *translator = new QTranslator (this);
    foreach (const QString &path, paths) {
      if (translator->load (trFile, path + QLatin1String ("/translations"))) {
        qApp->installTranslator (translator);
        break;
      }
    }
  }
}

void QtcDbViewerPlugin::extensionsInitialized () {
  // Retrieve objects from the plugin manager's object pool
  // In the extensionsInitialized function, a plugin can be sure that all
  // plugins that depend on it are completely initialized.
}

ExtensionSystem::IPlugin::ShutdownFlag QtcDbViewerPlugin::aboutToShutdown () {
  // Save settings
  // Disconnect from signals that are not needed during shutdown
  // Hide UI (if you add UI that is not in the main window directly)
  return SynchronousShutdown;
}
<commit_msg>Code reformat.<commit_after>#include "QtcDbViewerPlugin.h"
#include "Constants.h"
#include "WMain.h"

#include <QCoreApplication>
#include <QTranslator>

#include <QtPlugin>

#include <coreplugin/icore.h>
#include <coreplugin/imode.h>
#include <utils/icon.h>
#include <coreplugin/actionmanager/actionmanager.h>

using namespace QtcDbViewer::Internal;

const Utils::Icon MODE_DATABASE_CLASSIC (
  QLatin1String (":/icons/database.png"));
const Utils::Icon MODE_DATABASE_FLAT ({
  {QLatin1String (":/icons/database_mask.png"), Utils::Theme::IconsBaseColor}
});
const Utils::Icon MODE_DATABASE_FLAT_ACTIVE ({
  {QLatin1String (":/icons/database_mask.png"), Utils::Theme::IconsModeDesignActiveColor}
});

QtcDbViewerPlugin::QtcDbViewerPlugin () :
  IPlugin () {
  // Create your members
}

QtcDbViewerPlugin::~QtcDbViewerPlugin () {
  // Unregister objects from the plugin manager's object pool
  // Delete members
}

bool QtcDbViewerPlugin::initialize (const QStringList &arguments, QString *errorString) {
  // Register objects in the plugin manager's object pool
  // Load settings
  // Add actions to menus
  // Connect to other plugins' signals
  // In the initialize function, a plugin can be sure that the plugins it
  // depends on have initialized their members.

  Q_UNUSED (arguments)
  Q_UNUSED (errorString)

  initLanguage ();

  auto context = Core::Context (Constants::QTCDBVIEWER_CONTEXT);

  auto viewer = new WMain;
  auto buttons = viewer->findChildren<QToolButton *>();
  for (auto button: buttons) {
    if (button->toolTip ().isEmpty ()) {
      continue;
    }
    auto *proxyAction = new QAction (button->toolTip (), button);
    connect (proxyAction, SIGNAL (triggered (bool)), button, SIGNAL (clicked (bool)));

    auto id = Core::Id::fromString (QStringLiteral ("QtcDbViewer.") + button->objectName ());
    auto *cmd = Core::ActionManager::registerAction (proxyAction, id, context);
    cmd->setDefaultKeySequence (button->shortcut ().toString ());
    button->setShortcut (QString ());
    connect (cmd, &Core::Command::keySequenceChanged, [button, proxyAction, cmd]() {
      QString tooltip = proxyAction->text ();
      if (!cmd->keySequence ().isEmpty ()) {
        tooltip += QString (QStringLiteral (" (%1)")).arg (cmd->keySequence ().toString ());
      }
      button->setToolTip (tooltip);
    });
    cmd->keySequenceChanged ();
  }

  Core::IMode *dbViewMode = new Core::IMode;
  dbViewMode->setId (Constants::QTCDBVIEWER_ID);
  dbViewMode->setContext (context);
  dbViewMode->setDisplayName (tr ("Db Viewer"));
  dbViewMode->setIcon (Utils::Icon::modeIcon (MODE_DATABASE_CLASSIC,
                                              MODE_DATABASE_FLAT, MODE_DATABASE_FLAT_ACTIVE));
  dbViewMode->setPriority (10);
  dbViewMode->setWidget (viewer);
  addAutoReleasedObject (dbViewMode);

  return true;
}

void QtcDbViewerPlugin::initLanguage () {
  const QString &language = Core::ICore::userInterfaceLanguage ();
  if (!language.isEmpty ()) {
    QStringList paths;
    paths << Core::ICore::resourcePath () << Core::ICore::userResourcePath ();
    const QString &trFile = QLatin1String ("QtcDbViewer_") + language;
    QTranslator *translator = new QTranslator (this);
    foreach (const QString &path, paths) {
      if (translator->load (trFile, path + QLatin1String ("/translations"))) {
        qApp->installTranslator (translator);
        break;
      }
    }
  }
}

void QtcDbViewerPlugin::extensionsInitialized () {
  // Retrieve objects from the plugin manager's object pool
  // In the extensionsInitialized function, a plugin can be sure that all
  // plugins that depend on it are completely initialized.
}

ExtensionSystem::IPlugin::ShutdownFlag QtcDbViewerPlugin::aboutToShutdown () {
  // Save settings
  // Disconnect from signals that are not needed during shutdown
  // Hide UI (if you add UI that is not in the main window directly)
  return SynchronousShutdown;
}
<|endoftext|>


<commit_before><commit_msg>Allow time-formatted log file names<commit_after><|endoftext|>


<commit_before>//===- MIRPrinter.cpp - MIR serialization format printer ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the class that prints out the LLVM IR and machine
// functions using the MIR serialization format.
//
//===----------------------------------------------------------------------===//

#include "MIRPrinter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"

using namespace llvm;

namespace {

/// This class prints out the machine functions using the MIR serialization
/// format.
class MIRPrinter {
  raw_ostream &OS;
  DenseMap<const uint32_t *, unsigned> RegisterMaskIds;

public:
  MIRPrinter(raw_ostream &OS) : OS(OS) {}

  void print(const MachineFunction &MF);

  void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo);
  void convert(const Module &M, yaml::MachineBasicBlock &YamlMBB,
               const MachineBasicBlock &MBB);

private:
  void initRegisterMaskIds(const MachineFunction &MF);
};

/// This class prints out the machine instructions using the MIR serialization
/// format.
class MIPrinter {
  const Module &M;
  raw_ostream &OS;
  const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds;

public:
  MIPrinter(const Module &M, raw_ostream &OS,
            const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds)
      : M(M), OS(OS), RegisterMaskIds(RegisterMaskIds) {}

  void print(const MachineInstr &MI);
  void printMBBReference(const MachineBasicBlock &MBB);
  void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
};

} // end anonymous namespace

namespace llvm {
namespace yaml {

/// This struct serializes the LLVM IR module.
template <> struct BlockScalarTraits<Module> {
  static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
    Mod.print(OS, nullptr);
  }
  static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
    llvm_unreachable("LLVM Module is supposed to be parsed separately");
    return "";
  }
};

} // end namespace yaml
} // end namespace llvm

void MIRPrinter::print(const MachineFunction &MF) {
  initRegisterMaskIds(MF);

  yaml::MachineFunction YamlMF;
  YamlMF.Name = MF.getName();
  YamlMF.Alignment = MF.getAlignment();
  YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
  YamlMF.HasInlineAsm = MF.hasInlineAsm();
  convert(YamlMF, MF.getRegInfo());

  int I = 0;
  const auto &M = *MF.getFunction()->getParent();
  for (const auto &MBB : MF) {
    // TODO: Allow printing of non sequentially numbered MBBs.
    // This is currently needed as the basic block references get their index
    // from MBB.getNumber(), thus it should be sequential so that the parser can
    // map back to the correct MBBs when parsing the output.
    assert(MBB.getNumber() == I++ &&
           "Can't print MBBs that aren't sequentially numbered");
    (void)I;
    yaml::MachineBasicBlock YamlMBB;
    convert(M, YamlMBB, MBB);
    YamlMF.BasicBlocks.push_back(YamlMBB);
  }
  yaml::Output Out(OS);
  Out << YamlMF;
}

void MIRPrinter::convert(yaml::MachineFunction &MF,
                         const MachineRegisterInfo &RegInfo) {
  MF.IsSSA = RegInfo.isSSA();
  MF.TracksRegLiveness = RegInfo.tracksLiveness();
  MF.TracksSubRegLiveness = RegInfo.subRegLivenessEnabled();
}

void MIRPrinter::convert(const Module &M, yaml::MachineBasicBlock &YamlMBB,
                         const MachineBasicBlock &MBB) {
  assert(MBB.getNumber() >= 0 && "Invalid MBB number");
  YamlMBB.ID = (unsigned)MBB.getNumber();
  // TODO: Serialize unnamed BB references.
  if (const auto *BB = MBB.getBasicBlock())
    YamlMBB.Name = BB->hasName() ? BB->getName() : "<unnamed bb>";
  else
    YamlMBB.Name = "";
  YamlMBB.Alignment = MBB.getAlignment();
  YamlMBB.AddressTaken = MBB.hasAddressTaken();
  YamlMBB.IsLandingPad = MBB.isLandingPad();
  for (const auto *SuccMBB : MBB.successors()) {
    std::string Str;
    raw_string_ostream StrOS(Str);
    MIPrinter(M, StrOS, RegisterMaskIds).printMBBReference(*SuccMBB);
    YamlMBB.Successors.push_back(StrOS.str());
  }

  // Print the machine instructions.
  YamlMBB.Instructions.reserve(MBB.size());
  std::string Str;
  for (const auto &MI : MBB) {
    raw_string_ostream StrOS(Str);
    MIPrinter(M, StrOS, RegisterMaskIds).print(MI);
    YamlMBB.Instructions.push_back(StrOS.str());
    Str.clear();
  }
}

void MIRPrinter::initRegisterMaskIds(const MachineFunction &MF) {
  const auto *TRI = MF.getSubtarget().getRegisterInfo();
  unsigned I = 0;
  for (const uint32_t *Mask : TRI->getRegMasks())
    RegisterMaskIds.insert(std::make_pair(Mask, I++));
}

void MIPrinter::print(const MachineInstr &MI) {
  const auto &SubTarget = MI.getParent()->getParent()->getSubtarget();
  const auto *TRI = SubTarget.getRegisterInfo();
  assert(TRI && "Expected target register info");
  const auto *TII = SubTarget.getInstrInfo();
  assert(TII && "Expected target instruction info");

  unsigned I = 0, E = MI.getNumOperands();
  for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
         !MI.getOperand(I).isImplicit();
       ++I) {
    if (I)
      OS << ", ";
    print(MI.getOperand(I), TRI);
  }

  if (I)
    OS << " = ";
  OS << TII->getName(MI.getOpcode());
  // TODO: Print the instruction flags, machine mem operands.
  if (I < E)
    OS << ' ';

  bool NeedComma = false;
  for (; I < E; ++I) {
    if (NeedComma)
      OS << ", ";
    print(MI.getOperand(I), TRI);
    NeedComma = true;
  }
}

static void printReg(unsigned Reg, raw_ostream &OS,
                     const TargetRegisterInfo *TRI) {
  // TODO: Print Stack Slots.
  // TODO: Print virtual registers.
  if (!Reg)
    OS << '_';
  else if (Reg < TRI->getNumRegs())
    OS << '%' << StringRef(TRI->getName(Reg)).lower();
  else
    llvm_unreachable("Can't print this kind of register yet");
}

void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) {
  OS << "%bb." << MBB.getNumber();
  if (const auto *BB = MBB.getBasicBlock()) {
    if (BB->hasName())
      OS << '.' << BB->getName();
  }
}

void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
  switch (Op.getType()) {
  case MachineOperand::MO_Register:
    // TODO: Print the other register flags.
    if (Op.isImplicit())
      OS << (Op.isDef() ? "implicit-def " : "implicit ");
    if (Op.isDead())
      OS << "dead ";
    printReg(Op.getReg(), OS, TRI);
    // TODO: Print sub register.
    break;
  case MachineOperand::MO_Immediate:
    OS << Op.getImm();
    break;
  case MachineOperand::MO_MachineBasicBlock:
    printMBBReference(*Op.getMBB());
    break;
  case MachineOperand::MO_GlobalAddress:
    // FIXME: Make this faster - print as operand will create a slot tracker to
    // print unnamed values for the whole module every time it's called, which
    // is inefficient.
    Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, &M);
    // TODO: Print offset and target flags.
    break;
  case MachineOperand::MO_RegisterMask: {
    auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask());
    if (RegMaskInfo != RegisterMaskIds.end())
      OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower();
    else
      llvm_unreachable("Can't print this machine register mask yet.");
    break;
  }
  default:
    // TODO: Print the other machine operands.
    llvm_unreachable("Can't print this machine operand at the moment");
  }
}

void llvm::printMIR(raw_ostream &OS, const Module &M) {
  yaml::Output Out(OS);
  Out << const_cast<Module &>(M);
}

void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) {
  MIRPrinter Printer(OS);
  Printer.print(MF);
}
<commit_msg>MIR Printer: Use a module slot tracker to print global address operands. NFC.<commit_after>//===- MIRPrinter.cpp - MIR serialization format printer ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the class that prints out the LLVM IR and machine
// functions using the MIR serialization format.
//
//===----------------------------------------------------------------------===//

#include "MIRPrinter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"

using namespace llvm;

namespace {

/// This class prints out the machine functions using the MIR serialization
/// format.
class MIRPrinter {
  raw_ostream &OS;
  DenseMap<const uint32_t *, unsigned> RegisterMaskIds;

public:
  MIRPrinter(raw_ostream &OS) : OS(OS) {}

  void print(const MachineFunction &MF);

  void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo);
  void convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB,
               const MachineBasicBlock &MBB);

private:
  void initRegisterMaskIds(const MachineFunction &MF);
};

/// This class prints out the machine instructions using the MIR serialization
/// format.
class MIPrinter {
  raw_ostream &OS;
  ModuleSlotTracker &MST;
  const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds;

public:
  MIPrinter(raw_ostream &OS, ModuleSlotTracker &MST,
            const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds)
      : OS(OS), MST(MST), RegisterMaskIds(RegisterMaskIds) {}

  void print(const MachineInstr &MI);
  void printMBBReference(const MachineBasicBlock &MBB);
  void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
};

} // end anonymous namespace

namespace llvm {
namespace yaml {

/// This struct serializes the LLVM IR module.
template <> struct BlockScalarTraits<Module> {
  static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
    Mod.print(OS, nullptr);
  }
  static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
    llvm_unreachable("LLVM Module is supposed to be parsed separately");
    return "";
  }
};

} // end namespace yaml
} // end namespace llvm

void MIRPrinter::print(const MachineFunction &MF) {
  initRegisterMaskIds(MF);

  yaml::MachineFunction YamlMF;
  YamlMF.Name = MF.getName();
  YamlMF.Alignment = MF.getAlignment();
  YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
  YamlMF.HasInlineAsm = MF.hasInlineAsm();
  convert(YamlMF, MF.getRegInfo());

  int I = 0;
  ModuleSlotTracker MST(MF.getFunction()->getParent());
  for (const auto &MBB : MF) {
    // TODO: Allow printing of non sequentially numbered MBBs.
    // This is currently needed as the basic block references get their index
    // from MBB.getNumber(), thus it should be sequential so that the parser can
    // map back to the correct MBBs when parsing the output.
    assert(MBB.getNumber() == I++ &&
           "Can't print MBBs that aren't sequentially numbered");
    (void)I;
    yaml::MachineBasicBlock YamlMBB;
    convert(MST, YamlMBB, MBB);
    YamlMF.BasicBlocks.push_back(YamlMBB);
  }
  yaml::Output Out(OS);
  Out << YamlMF;
}

void MIRPrinter::convert(yaml::MachineFunction &MF,
                         const MachineRegisterInfo &RegInfo) {
  MF.IsSSA = RegInfo.isSSA();
  MF.TracksRegLiveness = RegInfo.tracksLiveness();
  MF.TracksSubRegLiveness = RegInfo.subRegLivenessEnabled();
}

void MIRPrinter::convert(ModuleSlotTracker &MST,
                         yaml::MachineBasicBlock &YamlMBB,
                         const MachineBasicBlock &MBB) {
  assert(MBB.getNumber() >= 0 && "Invalid MBB number");
  YamlMBB.ID = (unsigned)MBB.getNumber();
  // TODO: Serialize unnamed BB references.
  if (const auto *BB = MBB.getBasicBlock())
    YamlMBB.Name = BB->hasName() ? BB->getName() : "<unnamed bb>";
  else
    YamlMBB.Name = "";
  YamlMBB.Alignment = MBB.getAlignment();
  YamlMBB.AddressTaken = MBB.hasAddressTaken();
  YamlMBB.IsLandingPad = MBB.isLandingPad();
  for (const auto *SuccMBB : MBB.successors()) {
    std::string Str;
    raw_string_ostream StrOS(Str);
    MIPrinter(StrOS, MST, RegisterMaskIds).printMBBReference(*SuccMBB);
    YamlMBB.Successors.push_back(StrOS.str());
  }

  // Print the machine instructions.
  YamlMBB.Instructions.reserve(MBB.size());
  std::string Str;
  for (const auto &MI : MBB) {
    raw_string_ostream StrOS(Str);
    MIPrinter(StrOS, MST, RegisterMaskIds).print(MI);
    YamlMBB.Instructions.push_back(StrOS.str());
    Str.clear();
  }
}

void MIRPrinter::initRegisterMaskIds(const MachineFunction &MF) {
  const auto *TRI = MF.getSubtarget().getRegisterInfo();
  unsigned I = 0;
  for (const uint32_t *Mask : TRI->getRegMasks())
    RegisterMaskIds.insert(std::make_pair(Mask, I++));
}

void MIPrinter::print(const MachineInstr &MI) {
  const auto &SubTarget = MI.getParent()->getParent()->getSubtarget();
  const auto *TRI = SubTarget.getRegisterInfo();
  assert(TRI && "Expected target register info");
  const auto *TII = SubTarget.getInstrInfo();
  assert(TII && "Expected target instruction info");

  unsigned I = 0, E = MI.getNumOperands();
  for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
         !MI.getOperand(I).isImplicit();
       ++I) {
    if (I)
      OS << ", ";
    print(MI.getOperand(I), TRI);
  }

  if (I)
    OS << " = ";
  OS << TII->getName(MI.getOpcode());
  // TODO: Print the instruction flags, machine mem operands.
  if (I < E)
    OS << ' ';

  bool NeedComma = false;
  for (; I < E; ++I) {
    if (NeedComma)
      OS << ", ";
    print(MI.getOperand(I), TRI);
    NeedComma = true;
  }
}

static void printReg(unsigned Reg, raw_ostream &OS,
                     const TargetRegisterInfo *TRI) {
  // TODO: Print Stack Slots.
  // TODO: Print virtual registers.
  if (!Reg)
    OS << '_';
  else if (Reg < TRI->getNumRegs())
    OS << '%' << StringRef(TRI->getName(Reg)).lower();
  else
    llvm_unreachable("Can't print this kind of register yet");
}

void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) {
  OS << "%bb." << MBB.getNumber();
  if (const auto *BB = MBB.getBasicBlock()) {
    if (BB->hasName())
      OS << '.' << BB->getName();
  }
}

void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
  switch (Op.getType()) {
  case MachineOperand::MO_Register:
    // TODO: Print the other register flags.
    if (Op.isImplicit())
      OS << (Op.isDef() ? "implicit-def " : "implicit ");
    if (Op.isDead())
      OS << "dead ";
    printReg(Op.getReg(), OS, TRI);
    // TODO: Print sub register.
    break;
  case MachineOperand::MO_Immediate:
    OS << Op.getImm();
    break;
  case MachineOperand::MO_MachineBasicBlock:
    printMBBReference(*Op.getMBB());
    break;
  case MachineOperand::MO_GlobalAddress:
    Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST);
    // TODO: Print offset and target flags.
    break;
  case MachineOperand::MO_RegisterMask: {
    auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask());
    if (RegMaskInfo != RegisterMaskIds.end())
      OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower();
    else
      llvm_unreachable("Can't print this machine register mask yet.");
    break;
  }
  default:
    // TODO: Print the other machine operands.
    llvm_unreachable("Can't print this machine operand at the moment");
  }
}

void llvm::printMIR(raw_ostream &OS, const Module &M) {
  yaml::Output Out(OS);
  Out << const_cast<Module &>(M);
}

void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) {
  MIRPrinter Printer(OS);
  Printer.print(MF);
}
<|endoftext|>