<commit_before>#include "QuickItemPainter.h"

#include <QAbstractTextDocumentLayout>
#include <QPainter>
#include <QQuickItem>
#include <QQuickWindow>
#include <QTextDocument>

#include "StyledText.h"

QuickItemPainter::QuickItemPainter(QPainter* _painter, QQuickWindow* _window) : m_painter(_painter), m_window(_window)
{
}

namespace {
  bool inherits(const QMetaObject* _metaObject, const QString& _name)
  {
    if(_metaObject->className() == _name)
    {
      return true;
    } else if(_metaObject->superClass()) {
      return inherits(_metaObject->superClass(), _name);
    } else {
      return false;
    }
  }
}

void QuickItemPainter::paintQuickRectangle(QQuickItem* _item)
{
  // Print rectangle
  const QRect rect = _item->mapRectToScene(_item->boundingRect()).toRect(); // TODO should it be set on the QPainter ?
  const QColor color = _item->property("color").value<QColor>();
  const QObject* border = _item->property("border").value<QObject*>();
  const qreal border_width = border->property("width").value<qreal>();
  const QColor border_color = border->property("color").value<QColor>();
  const qreal radius = _item->property("radius").value<qreal>();

  m_painter->setBrush(color);

  if(border_width > 0 and not (border_width == 1 and border_color == QColor(Qt::black))) // FIXME this is wrong, but there is no other clean way to detect if a border is valid or not
  {
    m_painter->setPen(QPen(border_color, border_width));
  } else {
    m_painter->setPen(Qt::NoPen);
  }

  if(radius > 0)
  {
    m_painter->drawRoundedRect(rect, radius, radius);
  } else {
    m_painter->drawRect(rect);
  }

}

void QuickItemPainter::paintQuickText(QQuickItem* _item)
{
  const QRect rect = _item->mapRectToScene(_item->boundingRect()).toRect(); // TODO should it be set on the QPainter ?
  const QFont font = _item->property("font").value<QFont>();
  const QString text = _item->property("text").value<QString>();
  const QColor color = _item->property("color").value<QColor>();
  const int wrapMode = _item->property("wrapMode").value<int>();
  int textFormat = _item->property("textFormat").value<int>();
  const int horizontalAlignment = _item->property("horizontalAlignment").value<int>();
  const int verticalAlignment   = _item->property("verticalAlignment").value<int>();

  QTextOption textOption;
  textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
  textOption.setAlignment((Qt::Alignment)(horizontalAlignment | verticalAlignment));

  if(textFormat == Qt::AutoText) /* Text.AutoText */
  {
    textFormat = Qt::mightBeRichText(text) ? 4 : Qt::PlainText;
  }

  switch (textFormat)
  {
  case Qt::PlainText: // Text.PlainText
    {
      m_painter->setFont(font);
      m_painter->setPen(color);
      m_painter->drawText(rect, text, textOption);
    }
    break;
  default:
  case 4: // Text.StyledText
    {
      bool fontModified;
      QTextLayout textLayout;
      textLayout.setFont(font);
      textLayout.setTextOption(textOption);
      QTextCharFormat defaultFormat;
      defaultFormat.setForeground(color);

      QList<StyledTextImgTag*> tags;
      StyledText::parse(text, textLayout, tags, QUrl(), qmlContext(_item), true, &fontModified, defaultFormat);

      textLayout.beginLayout();
      int height = 0;
      const int leading = 0;
      while (1) {
          QTextLine line = textLayout.createLine();
          if (!line.isValid())
              break;

          line.setLineWidth(_item->width());
          height += leading;
          line.setPosition(QPointF(0, height));
          height += line.height();
      }
      textLayout.endLayout();

      m_painter->setRenderHint(QPainter::Antialiasing, true);
      textLayout.draw(m_painter, rect.topLeft());
    }
    break;
  case Qt::RichText: // Text.RichText
    {
      QTextDocument doc;
      doc.setTextWidth(rect.width());
      doc.setDefaultTextOption(textOption);
      doc.setDefaultFont(font);

      doc.setHtml(text);

      QAbstractTextDocumentLayout::PaintContext context;

      context.palette.setColor(QPalette::Text, color);

      QAbstractTextDocumentLayout *layout = doc.documentLayout();
      m_painter->translate(rect.topLeft());
      m_painter->setRenderHint(QPainter::Antialiasing, true);
      layout->draw(m_painter, context);
    }
    break;
  }
}

void QuickItemPainter::paintQuickImage(QQuickItem* _item)
{
  const QUrl url = _item->property("source").value<QUrl>();
  const int fillMode = _item->property("fillMode").value<int>();

  QImage image(url.toLocalFile());

  QRect rect = _item->mapRectToScene(_item->boundingRect()).toRect(); // TODO should it be set on the QPainter ?
  QRect sourceRect(0, 0, image.width(), image.height());

  switch(fillMode)
  {
  default:
    qWarning() << "QuickItemPainter::paintQuickImage unimplemented fill mode: " << fillMode;
  case 0: // Image.Stretch
    break;
  case 1: // Image.PreserveAspectFit
    {
      QSize size = sourceRect.size();
      size.scale(rect.width(), rect.height(), Qt::KeepAspectRatio);
      break;
    }
  case 6: // Image.Pad
    {
      if(sourceRect.width() > rect.width())
      {
        rect.setWidth(sourceRect.width());
      } else {
        sourceRect.setWidth(rect.width());
      }
      if(sourceRect.height() > rect.height())
      {
        rect.setHeight(sourceRect.height());
      } else {
        sourceRect.setHeight(rect.height());
      }
      break;
    }
  }
  m_painter->drawImage(rect, image, sourceRect);
}

void QuickItemPainter::paintItem(QQuickItem* _item)
{
  if(_item->opacity() == 0.0) return;
  if(_item->flags().testFlag(QQuickItem::ItemHasContents))
  {
    m_painter->save();
    if(_item->clip())
    {
      m_painter->setClipping(true);
      m_painter->setClipRect(_item->clipRect());
    }
    if(inherits(_item->metaObject(), "QQuickRectangle"))
    {
      paintQuickRectangle(_item);
    } else if(inherits(_item->metaObject(), "QQuickText"))
    {
      paintQuickText(_item);
    } else if(inherits(_item->metaObject(), "QQuickImage"))
    {
      paintQuickImage(_item);
    } else {
      // Fallback
      qWarning() << "No QuickItemPainter::paintItem implementation for " << _item << " fallback to image grab";
      QRect rect = _item->mapRectToScene(_item->boundingRect()).toRect();
      QImage image = m_window->grabWindow();
      m_painter->drawImage(rect.x(), rect.y(), image, rect.x(), rect.y(), rect.width(), rect.height());
    }
    m_painter->restore();
  }
  foreach(QQuickItem* child, _item->childItems()) // TODO reorder to take into account z-order
  {
    if(child and child->isVisible())
    {
      paintItem(child);
    }
  }
}
<commit_msg>print children in function of their z-order<commit_after>#include "QuickItemPainter.h"

#include <QAbstractTextDocumentLayout>
#include <QPainter>
#include <QQuickItem>
#include <QQuickWindow>
#include <QTextDocument>

#include "StyledText.h"

QuickItemPainter::QuickItemPainter(QPainter* _painter, QQuickWindow* _window) : m_painter(_painter), m_window(_window)
{
}

namespace {
  bool inherits(const QMetaObject* _metaObject, const QString& _name)
  {
    if(_metaObject->className() == _name)
    {
      return true;
    } else if(_metaObject->superClass()) {
      return inherits(_metaObject->superClass(), _name);
    } else {
      return false;
    }
  }
}

void QuickItemPainter::paintQuickRectangle(QQuickItem* _item)
{
  // Print rectangle
  const QRect rect = _item->mapRectToScene(_item->boundingRect()).toRect(); // TODO should it be set on the QPainter ?
  const QColor color = _item->property("color").value<QColor>();
  const QObject* border = _item->property("border").value<QObject*>();
  const qreal border_width = border->property("width").value<qreal>();
  const QColor border_color = border->property("color").value<QColor>();
  const qreal radius = _item->property("radius").value<qreal>();

  m_painter->setBrush(color);

  if(border_width > 0 and not (border_width == 1 and border_color == QColor(Qt::black))) // FIXME this is wrong, but there is no other clean way to detect if a border is valid or not
  {
    m_painter->setPen(QPen(border_color, border_width));
  } else {
    m_painter->setPen(Qt::NoPen);
  }

  if(radius > 0)
  {
    m_painter->drawRoundedRect(rect, radius, radius);
  } else {
    m_painter->drawRect(rect);
  }

}

void QuickItemPainter::paintQuickText(QQuickItem* _item)
{
  const QRect rect = _item->mapRectToScene(_item->boundingRect()).toRect(); // TODO should it be set on the QPainter ?
  const QFont font = _item->property("font").value<QFont>();
  const QString text = _item->property("text").value<QString>();
  const QColor color = _item->property("color").value<QColor>();
  const int wrapMode = _item->property("wrapMode").value<int>();
  int textFormat = _item->property("textFormat").value<int>();
  const int horizontalAlignment = _item->property("horizontalAlignment").value<int>();
  const int verticalAlignment   = _item->property("verticalAlignment").value<int>();

  QTextOption textOption;
  textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
  textOption.setAlignment((Qt::Alignment)(horizontalAlignment | verticalAlignment));

  if(textFormat == Qt::AutoText) /* Text.AutoText */
  {
    textFormat = Qt::mightBeRichText(text) ? 4 : Qt::PlainText;
  }

  switch (textFormat)
  {
  case Qt::PlainText: // Text.PlainText
    {
      m_painter->setFont(font);
      m_painter->setPen(color);
      m_painter->drawText(rect, text, textOption);
    }
    break;
  default:
  case 4: // Text.StyledText
    {
      bool fontModified;
      QTextLayout textLayout;
      textLayout.setFont(font);
      textLayout.setTextOption(textOption);
      QTextCharFormat defaultFormat;
      defaultFormat.setForeground(color);

      QList<StyledTextImgTag*> tags;
      StyledText::parse(text, textLayout, tags, QUrl(), qmlContext(_item), true, &fontModified, defaultFormat);

      textLayout.beginLayout();
      int height = 0;
      const int leading = 0;
      while (1) {
          QTextLine line = textLayout.createLine();
          if (!line.isValid())
              break;

          line.setLineWidth(_item->width());
          height += leading;
          line.setPosition(QPointF(0, height));
          height += line.height();
      }
      textLayout.endLayout();

      m_painter->setRenderHint(QPainter::Antialiasing, true);
      textLayout.draw(m_painter, rect.topLeft());
    }
    break;
  case Qt::RichText: // Text.RichText
    {
      QTextDocument doc;
      doc.setTextWidth(rect.width());
      doc.setDefaultTextOption(textOption);
      doc.setDefaultFont(font);

      doc.setHtml(text);

      QAbstractTextDocumentLayout::PaintContext context;

      context.palette.setColor(QPalette::Text, color);

      QAbstractTextDocumentLayout *layout = doc.documentLayout();
      m_painter->translate(rect.topLeft());
      m_painter->setRenderHint(QPainter::Antialiasing, true);
      layout->draw(m_painter, context);
    }
    break;
  }
}

void QuickItemPainter::paintQuickImage(QQuickItem* _item)
{
  const QUrl url = _item->property("source").value<QUrl>();
  const int fillMode = _item->property("fillMode").value<int>();

  QImage image(url.toLocalFile());

  QRect rect = _item->mapRectToScene(_item->boundingRect()).toRect(); // TODO should it be set on the QPainter ?
  QRect sourceRect(0, 0, image.width(), image.height());

  switch(fillMode)
  {
  default:
    qWarning() << "QuickItemPainter::paintQuickImage unimplemented fill mode: " << fillMode;
  case 0: // Image.Stretch
    break;
  case 1: // Image.PreserveAspectFit
    {
      QSize size = sourceRect.size();
      size.scale(rect.width(), rect.height(), Qt::KeepAspectRatio);
      break;
    }
  case 6: // Image.Pad
    {
      if(sourceRect.width() > rect.width())
      {
        rect.setWidth(sourceRect.width());
      } else {
        sourceRect.setWidth(rect.width());
      }
      if(sourceRect.height() > rect.height())
      {
        rect.setHeight(sourceRect.height());
      } else {
        sourceRect.setHeight(rect.height());
      }
      break;
    }
  }
  m_painter->drawImage(rect, image, sourceRect);
}

void QuickItemPainter::paintItem(QQuickItem* _item)
{
  if(_item->opacity() == 0.0) return;
  if(_item->flags().testFlag(QQuickItem::ItemHasContents))
  {
    m_painter->save();
    if(_item->clip())
    {
      m_painter->setClipping(true);
      m_painter->setClipRect(_item->clipRect());
    }
    if(inherits(_item->metaObject(), "QQuickRectangle"))
    {
      paintQuickRectangle(_item);
    } else if(inherits(_item->metaObject(), "QQuickText"))
    {
      paintQuickText(_item);
    } else if(inherits(_item->metaObject(), "QQuickImage"))
    {
      paintQuickImage(_item);
    } else {
      // Fallback
      qWarning() << "No QuickItemPainter::paintItem implementation for " << _item << " fallback to image grab";
      QRect rect = _item->mapRectToScene(_item->boundingRect()).toRect();
      QImage image = m_window->grabWindow();
      m_painter->drawImage(rect.x(), rect.y(), image, rect.x(), rect.y(), rect.width(), rect.height());
    }
    m_painter->restore();
  }
  QList<QQuickItem*> children = _item->childItems();
  std::stable_sort(children.begin(), children.end(), ZCompare());
  foreach(QQuickItem* child, children) // TODO reorder to take into account z-order
  {
    if(child and child->isVisible())
    {
      paintItem(child);
    }
  }
}
<|endoftext|>


<commit_before>/*
 *   CrissCross
 *   A multi-purpose cross-platform library.
 *
 *   A product of Uplink Laboratories.
 *
 *   (c) 2006-2010 Steven Noonan.
 *   Licensed under the New BSD License.
 *
 */

#include <crisscross/universal_include.h>
#include <crisscross/stopwatch.h>

#if defined (TARGET_OS_MACOSX)
#include <mach/mach.h>
#include <mach/mach_time.h>
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_NDSFIRMWARE)
#include <sys/time.h>
#include <time.h>
#elif defined (TARGET_OS_WINDOWS)
#include <windows.h>
#endif

namespace CrissCross
{
	namespace System
	{
		struct StopwatchImpl {
#if defined (TARGET_OS_WINDOWS)
			LARGE_INTEGER m_start, m_finish;
			double m_tickInterval;

			void RecalculateFrequency();
#elif defined (TARGET_OS_MACOSX)
			uint64_t m_start;
			uint64_t m_finish;
			mach_timebase_info_data_t m_timebase;
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			struct timeval m_start;
			struct timeval m_finish;
#elif defined (TARGET_OS_NDSFIRMWARE)
			/* Nothing here :) */
#else
#error No target OS defined (did you forget to include crisscross/universal_include.h?)
#endif
		};
		Stopwatch::Stopwatch()
		{
			m_impl = new StopwatchImpl;
#if defined (TARGET_OS_WINDOWS)
			m_impl->RecalculateFrequency();
#elif defined (TARGET_OS_MACOSX)
			mach_timebase_info(&m_timebase);
#endif

			/* We start it here for static Stopwatch instances */
			/* where it's impractical to do an initial Start() call */
			Start();
		}

		Stopwatch::~Stopwatch()
		{
			delete m_impl;
		}

		void Stopwatch::Start()
		{
#if defined (TARGET_OS_WINDOWS)
			m_impl->RecalculateFrequency();
			QueryPerformanceCounter(&m_impl->m_start);
#elif defined (TARGET_OS_MACOSX)
			m_impl->m_start = mach_absolute_time();
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			gettimeofday(&m_impl->m_start, NULL);
#elif defined (TARGET_OS_NDSFIRMWARE)
			TIMER0_CR = 0;
			TIMER1_CR = 0;
			TIMER0_DATA = 0;
			TIMER1_DATA = 0;
			TIMER1_CR = TIMER_ENABLE | TIMER_CASCADE;
			TIMER0_CR = TIMER_ENABLE | TIMER_DIV_1;
#endif
		}

		void Stopwatch::Stop()
		{
#if defined (TARGET_OS_WINDOWS)
			QueryPerformanceCounter(&m_impl->m_finish);
#elif defined (TARGET_OS_MACOSX)
			m_impl->m_finish = mach_absolute_time();
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			gettimeofday(&m_impl->m_finish, NULL);
#elif defined (TARGET_OS_NDSFIRMWARE)
			TIMER0_CR = 0;
#endif
		}

#if defined (TARGET_OS_WINDOWS)
		void StopwatchImpl::RecalculateFrequency()
		{
			CoreAssert(this != NULL);

			LARGE_INTEGER freq;
			QueryPerformanceFrequency(&freq);
			m_tickInterval = 1.0 / (double)freq.QuadPart;
		}
#endif

		double Stopwatch::Elapsed()
		{
			CoreAssert(this != NULL);

#if defined (TARGET_OS_WINDOWS)
			return ((double)m_impl->m_finish.QuadPart - (double)m_impl->m_start.QuadPart) * m_impl->m_tickInterval;
#elif defined (TARGET_OS_MACOSX)
			uint64_t elapsed = m_impl->m_finish - m_impl->m_start;
			return double (elapsed) * (m_impl->m_timebase.numer / m_impl->m_timebase.denom) / 1000000000.0;
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			return (double)(m_impl->m_finish.tv_sec - m_impl->m_start.tv_sec) +
			       ((double)(m_impl->m_finish.tv_usec) - (double)(m_impl->m_start.tv_usec)) / 1000000.0;
#elif defined (TARGET_OS_NDSFIRMWARE)
			return (TIMER0_DATA | (TIMER1_DATA << 16)) / 33513982.0;
#endif
		}

		unsigned long Stopwatch::ElapsedMS()
		{
			CoreAssert(this != NULL);

#if defined (TARGET_OS_WINDOWS)
			return (unsigned long)(((double)m_impl->m_finish.QuadPart - (double)m_impl->m_start.QuadPart) * m_impl->m_tickInterval * 1000.0);
#elif defined (TARGET_OS_MACOSX)
			uint64_t elapsed = m_impl->m_finish - m_impl->m_start;
			return double (elapsed) * (m_impl->m_timebase.numer / m_impl->m_timebase.denom) / 1000000.0;
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			return (unsigned long)((m_impl->m_finish.tv_sec - m_impl->m_start.tv_sec) * 1000 +
			                       (m_impl->m_finish.tv_usec - m_impl->m_start.tv_usec) / 1000);
#elif defined (TARGET_OS_NDSFIRMWARE)
			return (TIMER0_DATA | (TIMER1_DATA << 16)) / 33514;
#endif
		}
	}
}
<commit_msg>stopwatch: fix incorrect reference to m_timebase<commit_after>/*
 *   CrissCross
 *   A multi-purpose cross-platform library.
 *
 *   A product of Uplink Laboratories.
 *
 *   (c) 2006-2010 Steven Noonan.
 *   Licensed under the New BSD License.
 *
 */

#include <crisscross/universal_include.h>
#include <crisscross/stopwatch.h>

#if defined (TARGET_OS_MACOSX)
#include <mach/mach.h>
#include <mach/mach_time.h>
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_NDSFIRMWARE)
#include <sys/time.h>
#include <time.h>
#elif defined (TARGET_OS_WINDOWS)
#include <windows.h>
#endif

namespace CrissCross
{
	namespace System
	{
		struct StopwatchImpl {
#if defined (TARGET_OS_WINDOWS)
			LARGE_INTEGER m_start, m_finish;
			double m_tickInterval;

			void RecalculateFrequency();
#elif defined (TARGET_OS_MACOSX)
			uint64_t m_start;
			uint64_t m_finish;
			mach_timebase_info_data_t m_timebase;
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			struct timeval m_start;
			struct timeval m_finish;
#elif defined (TARGET_OS_NDSFIRMWARE)
			/* Nothing here :) */
#else
#error No target OS defined (did you forget to include crisscross/universal_include.h?)
#endif
		};
		Stopwatch::Stopwatch()
		{
			m_impl = new StopwatchImpl;
#if defined (TARGET_OS_WINDOWS)
			m_impl->RecalculateFrequency();
#elif defined (TARGET_OS_MACOSX)
			mach_timebase_info(&m_impl->m_timebase);
#endif

			/* We start it here for static Stopwatch instances */
			/* where it's impractical to do an initial Start() call */
			Start();
		}

		Stopwatch::~Stopwatch()
		{
			delete m_impl;
		}

		void Stopwatch::Start()
		{
#if defined (TARGET_OS_WINDOWS)
			m_impl->RecalculateFrequency();
			QueryPerformanceCounter(&m_impl->m_start);
#elif defined (TARGET_OS_MACOSX)
			m_impl->m_start = mach_absolute_time();
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			gettimeofday(&m_impl->m_start, NULL);
#elif defined (TARGET_OS_NDSFIRMWARE)
			TIMER0_CR = 0;
			TIMER1_CR = 0;
			TIMER0_DATA = 0;
			TIMER1_DATA = 0;
			TIMER1_CR = TIMER_ENABLE | TIMER_CASCADE;
			TIMER0_CR = TIMER_ENABLE | TIMER_DIV_1;
#endif
		}

		void Stopwatch::Stop()
		{
#if defined (TARGET_OS_WINDOWS)
			QueryPerformanceCounter(&m_impl->m_finish);
#elif defined (TARGET_OS_MACOSX)
			m_impl->m_finish = mach_absolute_time();
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			gettimeofday(&m_impl->m_finish, NULL);
#elif defined (TARGET_OS_NDSFIRMWARE)
			TIMER0_CR = 0;
#endif
		}

#if defined (TARGET_OS_WINDOWS)
		void StopwatchImpl::RecalculateFrequency()
		{
			CoreAssert(this != NULL);

			LARGE_INTEGER freq;
			QueryPerformanceFrequency(&freq);
			m_tickInterval = 1.0 / (double)freq.QuadPart;
		}
#endif

		double Stopwatch::Elapsed()
		{
			CoreAssert(this != NULL);

#if defined (TARGET_OS_WINDOWS)
			return ((double)m_impl->m_finish.QuadPart - (double)m_impl->m_start.QuadPart) * m_impl->m_tickInterval;
#elif defined (TARGET_OS_MACOSX)
			uint64_t elapsed = m_impl->m_finish - m_impl->m_start;
			return double (elapsed) * (m_impl->m_timebase.numer / m_impl->m_timebase.denom) / 1000000000.0;
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			return (double)(m_impl->m_finish.tv_sec - m_impl->m_start.tv_sec) +
			       ((double)(m_impl->m_finish.tv_usec) - (double)(m_impl->m_start.tv_usec)) / 1000000.0;
#elif defined (TARGET_OS_NDSFIRMWARE)
			return (TIMER0_DATA | (TIMER1_DATA << 16)) / 33513982.0;
#endif
		}

		unsigned long Stopwatch::ElapsedMS()
		{
			CoreAssert(this != NULL);

#if defined (TARGET_OS_WINDOWS)
			return (unsigned long)(((double)m_impl->m_finish.QuadPart - (double)m_impl->m_start.QuadPart) * m_impl->m_tickInterval * 1000.0);
#elif defined (TARGET_OS_MACOSX)
			uint64_t elapsed = m_impl->m_finish - m_impl->m_start;
			return double (elapsed) * (m_impl->m_timebase.numer / m_impl->m_timebase.denom) / 1000000.0;
#elif defined (TARGET_OS_LINUX) || defined (TARGET_OS_FREEBSD) || \
			defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
			return (unsigned long)((m_impl->m_finish.tv_sec - m_impl->m_start.tv_sec) * 1000 +
			                       (m_impl->m_finish.tv_usec - m_impl->m_start.tv_usec) / 1000);
#elif defined (TARGET_OS_NDSFIRMWARE)
			return (TIMER0_DATA | (TIMER1_DATA << 16)) / 33514;
#endif
		}
	}
}
<|endoftext|>


<commit_before>#include <coffee/CCore>
#include <coffee/CGraphics>
#include <coffee/CFFMedia>

#include <coffee/graphics_apis/opengl/include/glfunctions.h>

using namespace Coffee;
using namespace Coffee::CGraphicsData;
using namespace Coffee::CGraphicsWrappers;
using namespace Coffee::CFFMedia;

class CDRenderer : public CDisplay::CGLBindingRenderer
{
public:
    CDRenderer():
        CGLBindingRenderer(0)
    {
        m_msg_filter = coffee_graphics_debug_filter_all;
    }

    void run()
    {
        //FFMPEG stuff here
        coffee_ffmedia_init(nullptr,false);

        //Open video file
        CResource testfile("test.mp4");
        coffee_file_pull(testfile);
        //Create a video player for the data
        CFFVideoPlayer* video = coffee_ffmedia_create_player(testfile);

        if(!video)
            return;

        //Define video format
        CFFVideoDescriptor v_fmt;
        v_fmt.video.size.w = 1280;
        v_fmt.video.size.h = 720;
        //Create a decoding context
        CFFDecodeContext* dCtxt = coffee_ffmedia_create_decodecontext(video,v_fmt);
        //

        //OpenGL stuff

        const CVec3 vertexdata[] = {
            CVec3(-1.f, 1.f, 0.f),
            CVec3( 1.f, 1.f, 0.f),
            CVec3(-1.f,-1.f, 0.f),
            CVec3( 1.f,-1.f, 0.f),
        };

        const CVec2 texdata[] = {
            CVec2(0.f, 0.f), //1
            CVec2(1.f, 0.f), //2
            CVec2(0.f, 1.f), //3
            CVec2(1.f, 1.f), //4
        };

        constexpr uint32 indexdata[] = {
            0, 1, 2, 1, 2, 3,
        };
        constexpr byte_t vshader_src[] = {
            "#version 330\n"
            "layout(location = 0) in vec3 position;"
            "layout(location = 1) in vec2 texcoord;"
            "uniform mat4 transform;"
            "out gl_PerVertex {"
            "   vec4 gl_Position;"
            "};"
            "out VData {"
            "   vec2 vtex;"
            "} vdata;"
            "void main(){"
            "   vdata.vtex = texcoord;"
            "   gl_Position = transform * vec4(position,1.0);"
            "}"
        };

        constexpr byte_t fshader_src[] = {
            "#version 330\n"
            "layout(location = 0) out vec4 Out_color;"
            "uniform sampler2D diffsamp;"
            "in VData {"
            "   vec2 vtex;"
            "} vdata;"
            "void main(){"
            "   vec4 smp = texture(diffsamp,vdata.vtex);"
            "   Out_color = smp;"
            "}"
        };
        //Construct a shader pipeline
        CSimplePipeline pipeline;
        pipeline.create(vshader_src,fshader_src);

        //Define buffers
        CBuffer vertexbuffer;
        CBuffer texcrdbuffer;
        CBuffer indexbuffer;
        {
            vertexbuffer.type = CBufferType::Array;
            indexbuffer.type = CBufferType::Index;

            coffee_graphics_alloc(vertexbuffer);
            coffee_graphics_alloc(texcrdbuffer);
            coffee_graphics_alloc(indexbuffer);

            coffee_graphics_activate(vertexbuffer);
            coffee_graphics_activate(texcrdbuffer);
            coffee_graphics_activate(indexbuffer);

            coffee_graphics_buffer_store(vertexbuffer,vertexdata,sizeof(vertexdata),
                                         CBufferUsage::StaticDraw);

            coffee_graphics_buffer_store(texcrdbuffer,texdata,sizeof(texdata),
                                         CBufferUsage::StaticDraw);

            coffee_graphics_buffer_store(indexbuffer,indexdata,sizeof(indexdata),
                                         CBufferUsage::StaticDraw);
        }
        //Define vertex attributes
        CVertexDescription vdescriptor;
        vdescriptor.addAttribute<scalar,3,CDataType::Scalar>(0,vertexdata);
        vdescriptor.addAttribute<scalar,2,CDataType::Scalar>(1,texdata);

        vdescriptor.getBinding(0)->binding = 0;
        vdescriptor.getBinding(0)->buffer = &vertexbuffer;
        vdescriptor.getBinding(1)->binding = 1;
        vdescriptor.getBinding(1)->buffer = &texcrdbuffer;
        //Define vertex array object
        CVertexArrayObject vao;
        coffee_graphics_alloc(vao);
        coffee_graphics_bind(vao);
        coffee_graphics_vao_attribute_index_buffer(vao,indexbuffer);
        vdescriptor.applyAttributes(vao);
        vdescriptor.bindAttributes(vao);
        //Define uniform data
        CUniform matrixuni;
        CUniform texuni;

        texuni.object_name = "diffsamp";
        matrixuni.object_name = "transform";

        coffee_graphics_uniform_get(pipeline.frag,texuni);
        coffee_graphics_uniform_get(pipeline.vert,matrixuni);

        //Create a video target
        CByteData initTexture;
        initTexture.size = coffee_ffmedia_video_framesize(CSize(v_fmt.video.size.w,
                                                                v_fmt.video.size.h));
        initTexture.data = (byte_t*)c_alloc(initTexture.size);

        CRGBA* pixels = (CRGBA*)initTexture.data;

        C_UNUSED(pixels);

        CFFVideoTarget trg = {};
        trg.v.location = initTexture.data;

        bool status = coffee_ffmedia_decode_frame(video,dCtxt,&trg);

        C_UNUSED(status);

        //Define output texture
        CBufferedTexture<2> texture;
        texture.createTexture(v_fmt.video.size,CTexIntFormat::RGBA8,
                              CTexType::Tex2D,1,initTexture,CTexFormat::RGBA);

        c_free(initTexture.data);

        coffee_graphics_tex_load(texture.sampler(),texture.texture());

        //

        //Bind a pipeline
        coffee_graphics_bind(pipeline.data_ref());

        //Set uniforms
        CGCamera camera;
        camera.aspect = 1.6f;
        camera.fieldOfView = 60.f;
        camera.position = CVec3(0,0,-3);

        CMat4 cam_matrix = coffee_graphics_gen_perspective(camera)
                * coffee_graphics_gen_transform(camera);

        CTransform quad_trans;
        quad_trans.position = CVec3(0,0,0);
        quad_trans.scale = CVec3(1.6,1.0,1.0);

        CMat4 quad_matrix = coffee_graphics_gen_transform(quad_trans);

        CNode root;
        root.transform = &cam_matrix;
        CNode quad;
        quad.parent = &root;
        quad.transform = &quad_matrix;

        CMat4 final_transform = coffee_node_get_transform(&quad);

        coffee_graphics_uniform_set_texhandle(pipeline.frag,texuni,
                                              texture.sampler().bhandle);
        glProgramUniformMatrix4fv(pipeline.vert.handle,matrixuni.index,
                                  1,GL_FALSE,(scalar*)&final_transform);
        //

        //Create a drawcall
        CGLDrawCall drawcall = {};
        drawcall.count = sizeof(indexdata)/sizeof(indexdata[0]);
        drawcall.instanceCount = 1;

        double timeout = this->contextTime();
        int counter;

        this->showWindow();
        while(!this->closeFlag())
        {
            coffee_graphics_clear(CClearFlag::Color);

            //FFMPEG
            trg.v.location = texture.buffers().current().data;
            coffee_ffmedia_decode_frame(video,dCtxt,&trg);

            texture.uploadData(CTexFormat::RGBA,0);
            //

            coffee_graphics_draw_indexed(CPrimitiveMode::Triangles,&drawcall);
            texture.advance();

            counter++;
            if((this->contextTime()-timeout)>=1.0)
            {
                timeout = this->contextTime();
                cDebug("Framerate: {0}",counter);
                counter=0;
            }

            this->swapBuffers();
            this->pollEvents();
        }

        //Free all the FFMPEG data
        coffee_ffmedia_free_decodecontext(dCtxt);
        coffee_ffmedia_free_player(video);
        coffee_file_free(testfile);
    }

    void eventHandleI(const CIEvent &e, c_cptr data)
    {
        CSDL2Renderer::eventHandleI(e,data);
        if(e.type == CIEvent::Keyboard)
        {
            const CIKeyEvent* kev = (const CIKeyEvent*)data;
            if(kev->key == CK_Escape)
                this->closeWindow();
        }
    }
};

int32 coffee_main(int32, byte_t**)
{
    coffee_file_set_resource_prefix("sample_data/");

    CDisplay::CDRendererBase* renderer = new CDRenderer;
    std::atomic_bool sync;
    sync.store(false);
    CDisplay::CDWindowProperties props = CDisplay::coffee_get_default_visual();
    props.contextProperties.flags = props.contextProperties.flags|
            CDisplay::CGLContextProperties::GLDebug|
            CDisplay::CGLContextProperties::GLAutoResize/*|
            CDisplay::CGLContextProperties::GLVSync*/;
    props.flags = CDisplay::CDWindowProperties::Resizable;

    std::future<void> status = CDisplay::coffee_display_start_async(&sync,renderer,props);

    status.get();

    return 0;
}

COFFEE_APPLICATION_MAIN(coffee_main)
<commit_msg> - Add legacy support<commit_after>#include <coffee/CCore>
#include <coffee/CGraphics>
#include <coffee/CFFMedia>

#include <coffee/graphics_apis/opengl/include/glfunctions.h>

using namespace Coffee;
using namespace Coffee::CGraphicsData;
using namespace Coffee::CGraphicsWrappers;
using namespace Coffee::CFFMedia;

class CDRenderer : public CDisplay::CGLBindingRenderer
{
public:
    CDRenderer():
        CGLBindingRenderer(0)
    {
        m_msg_filter = coffee_graphics_debug_filter_all;
    }

    void run()
    {
        //FFMPEG stuff here
        coffee_ffmedia_init(nullptr,false);

        //Open video file
        CResource testfile("test.mp4");
        coffee_file_pull(testfile);
        //Create a video player for the data
        CFFVideoPlayer* video = coffee_ffmedia_create_player(testfile);

        if(!video)
            return;

        //Define video format
        CFFVideoDescriptor v_fmt;
        v_fmt.video.size.w = 1280;
        v_fmt.video.size.h = 720;
        //Create a decoding context
        CFFDecodeContext* dCtxt = coffee_ffmedia_create_decodecontext(video,v_fmt);
        //

        //OpenGL stuff

        const CVec3 vertexdata[] = {
            CVec3(-1.f, 1.f, 0.f),
            CVec3( 1.f, 1.f, 0.f),
            CVec3(-1.f,-1.f, 0.f),
            CVec3( 1.f,-1.f, 0.f),
        };

        const CVec2 texdata[] = {
            CVec2(0.f, 0.f), //1
            CVec2(1.f, 0.f), //2
            CVec2(0.f, 1.f), //3
            CVec2(1.f, 1.f), //4
        };

        constexpr uint32 indexdata[] = {
            0, 1, 2, 1, 2, 3,
        };
        constexpr byte_t vshader_src[] = {
            "#version 330\n"
            "layout(location = 0) in vec3 position;"
            "layout(location = 1) in vec2 texcoord;"
            "uniform mat4 transform;"
            "out gl_PerVertex {"
            "   vec4 gl_Position;"
            "};"
            "out VData {"
            "   vec2 vtex;"
            "} vdata;"
            "void main(){"
            "   vdata.vtex = texcoord;"
            "   gl_Position = transform * vec4(position,1.0);"
            "}"
        };

        constexpr byte_t fshader_src[] = {
            "#version 330\n"
            "layout(location = 0) out vec4 Out_color;"
            "uniform sampler2D diffsamp;"
            "in VData {"
            "   vec2 vtex;"
            "} vdata;"
            "void main(){"
            "   vec4 smp = texture(diffsamp,vdata.vtex);"
            "   Out_color = smp;"
            "}"
        };
        //Construct a shader pipeline
        CSimplePipeline pipeline;
        pipeline.create(vshader_src,fshader_src);

        //Define buffers
        CBuffer vertexbuffer;
        CBuffer texcrdbuffer;
        CBuffer indexbuffer;
        {
            vertexbuffer.type = CBufferType::Array;
            indexbuffer.type = CBufferType::Index;

            coffee_graphics_alloc(vertexbuffer);
            coffee_graphics_alloc(texcrdbuffer);
            coffee_graphics_alloc(indexbuffer);

            coffee_graphics_activate(vertexbuffer);
            coffee_graphics_activate(texcrdbuffer);
            coffee_graphics_activate(indexbuffer);

            coffee_graphics_buffer_store(vertexbuffer,vertexdata,sizeof(vertexdata),
                                         CBufferUsage::StaticDraw);

            coffee_graphics_buffer_store(texcrdbuffer,texdata,sizeof(texdata),
                                         CBufferUsage::StaticDraw);

            coffee_graphics_buffer_store(indexbuffer,indexdata,sizeof(indexdata),
                                         CBufferUsage::StaticDraw);
        }
        //Define vertex attributes
        CVertexDescription vdescriptor;
        vdescriptor.addAttribute<scalar,3,CDataType::Scalar>(0,vertexdata);
        vdescriptor.addAttribute<scalar,2,CDataType::Scalar>(1,texdata);

        vdescriptor.getBinding(0)->binding = 0;
        vdescriptor.getBinding(0)->buffer = &vertexbuffer;
        vdescriptor.getBinding(1)->binding = 1;
        vdescriptor.getBinding(1)->buffer = &texcrdbuffer;
        //Define vertex array object
        CVertexArrayObject vao;
        coffee_graphics_alloc(vao);
        coffee_graphics_bind(vao);
        coffee_graphics_vao_attribute_index_buffer(vao,indexbuffer);
        vdescriptor.applyAttributes(vao);
        vdescriptor.bindAttributes(vao);
        //Define uniform data
        CUniform matrixuni;
        CUniform texuni;

        texuni.object_name = "diffsamp";
        matrixuni.object_name = "transform";

        coffee_graphics_uniform_get(pipeline.frag,texuni);
        coffee_graphics_uniform_get(pipeline.vert,matrixuni);

        //Create a video target
        CByteData initTexture;
        initTexture.size = coffee_ffmedia_video_framesize(CSize(v_fmt.video.size.w,
                                                                v_fmt.video.size.h));
        initTexture.data = (byte_t*)c_alloc(initTexture.size);

        CRGBA* pixels = (CRGBA*)initTexture.data;

        C_UNUSED(pixels);

        CFFVideoTarget trg = {};
        trg.v.location = initTexture.data;

        bool status = coffee_ffmedia_decode_frame(video,dCtxt,&trg);

        C_UNUSED(status);

        //Define output texture
        CBufferedTexture<2> texture;
        texture.createTexture(v_fmt.video.size,CTexIntFormat::RGBA8,
                              CTexType::Tex2D,1,initTexture,CTexFormat::RGBA);

        c_free(initTexture.data);

        coffee_graphics_tex_load_safe(texture.sampler(),texture.texture());

        //

        //Bind a pipeline
        coffee_graphics_bind(pipeline.data_ref());

        //Set uniforms
        CGCamera camera;
        camera.aspect = 1.6f;
        camera.fieldOfView = 60.f;
        camera.position = CVec3(0,0,-3);

        CMat4 cam_matrix = coffee_graphics_gen_perspective(camera)
                * coffee_graphics_gen_transform(camera);

        CTransform quad_trans;
        quad_trans.position = CVec3(0,0,0);
        quad_trans.scale = CVec3(1.6,1.0,1.0);

        CMat4 quad_matrix = coffee_graphics_gen_transform(quad_trans);

        CNode root;
        root.transform = &cam_matrix;
        CNode quad;
        quad.parent = &root;
        quad.transform = &quad_matrix;

        CMat4 final_transform = coffee_node_get_transform(&quad);

        coffee_graphics_uniform_set_texhandle_safe(pipeline.frag,texuni,
                                                   texture.sampler().unit);
        glProgramUniformMatrix4fv(pipeline.vert.handle,matrixuni.index,
                                  1,GL_FALSE,(scalar*)&final_transform);
        //

        //Create a drawcall
        CGLDrawCall drawcall = {};
        drawcall.count = sizeof(indexdata)/sizeof(indexdata[0]);
        drawcall.instanceCount = 1;

        double timeout = this->contextTime();
        int counter;

        this->showWindow();
        while(!this->closeFlag())
        {
            coffee_graphics_clear(CClearFlag::Color);

            //FFMPEG
            trg.v.location = texture.buffers().current().data;
            coffee_ffmedia_decode_frame(video,dCtxt,&trg);

            texture.uploadData(CTexFormat::RGBA,0);
            //

            coffee_graphics_draw_indexed(CPrimitiveMode::Triangles,&drawcall);
            texture.advance();

            counter++;
            if((this->contextTime()-timeout)>=1.0)
            {
                timeout = this->contextTime();
                cDebug("Framerate: {0}",counter);
                counter=0;
            }

            this->swapBuffers();
            this->pollEvents();
        }

        //Free all the FFMPEG data
        coffee_ffmedia_free_decodecontext(dCtxt);
        coffee_ffmedia_free_player(video);
        coffee_file_free(testfile);

        for(const std::pair<CString,CString>& ft : CDisplay::coffee_glbinding_get_graphics_feature_level())
        {
            cBasicPrint("{0} : {1}",ft.first.c_str(),ft.second.c_str());
        }
    }

    void eventHandleI(const CIEvent &e, c_cptr data)
    {
        CSDL2Renderer::eventHandleI(e,data);
        if(e.type == CIEvent::Keyboard)
        {
            const CIKeyEvent* kev = (const CIKeyEvent*)data;
            if(kev->key == CK_Escape)
                this->closeWindow();
        }
    }
};

int32 coffee_main(int32, byte_t**)
{
    coffee_file_set_resource_prefix("sample_data/");

    CDisplay::CDRendererBase* renderer = new CDRenderer;
    std::atomic_bool sync;
    sync.store(false);
    CDisplay::CDWindowProperties props = CDisplay::coffee_get_default_visual();
    props.contextProperties.flags = props.contextProperties.flags|
            CDisplay::CGLContextProperties::GLDebug|
            CDisplay::CGLContextProperties::GLFeatureLevelProfile|
            CDisplay::CGLContextProperties::GLAutoResize/*|
            CDisplay::CGLContextProperties::GLVSync*/;
    props.flags = CDisplay::CDWindowProperties::Resizable;

    std::future<void> status = CDisplay::coffee_display_start_async(&sync,renderer,props);

    status.get();

    return 0;
}

COFFEE_APPLICATION_MAIN(coffee_main)
<|endoftext|>


<commit_before><commit_msg>Expose option to force the sync history type when opening a realm (#966)<commit_after><|endoftext|>


<commit_before>#ifndef BONJOUR_DNSD_CALLBACK_FUNC_DEF_H__
#define BONJOUR_DNSD_CALLBACK_FUNC_DEF_H__

#include <boost/function.hpp>

#include <ddnspp/bonjourpp/dnsdapi.hpp>
#include <ddnspp/bonjourpp/bonjourerror.hpp>
#include <ddnspp/bonjourpp/txtrecords.hpp>
#include <ddnspp/bonjourpp/prototype.hpp>
#include <ddnspp/bonjourpp/nat_status.hpp>

namespace air{namespace bonjour {

	/// Event callback for air::bonjour::LocalService
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,					/// _1 flags
		air::bonjour::BonjourError,			/// _2 error
		std::string,						/// _3 service name
		std::string,						/// _4 service type
		std::string							/// _5 domian
		)
		>		LocalServiceEvtCallback;

	/// Event callback  for air::bonjour::RemoteService
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,					/// _1 flags
		boost::uint32_t,					/// _2 interfaceIndex
		air::bonjour::BonjourError,			/// _3 error
		std::string,						/// _4 service name (for subsequent use in the ServiceResolver )
		std::string,						/// _5 service type
		std::string							/// _6 domian
		)
		>
		RemoteServiceEvtCallback;

	/// Event callback  for air::bonjour::ServiceResolver
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,					/// _1 flags
		boost::uint32_t,					/// _2 interfaceIndex
		air::bonjour::BonjourError,			/// _3 error
		std::string,						/// _4 service name(fullname, format:<servicename>.<protocol>.<domain>)
		std::string,						/// _5 host name ,This name can  be passed to functions like gethostbyname() to identify the host's IP address.
		boost::uint16_t,					/// _6 port
		TxtRecordDecoderPtr					/// _7 TxtRecordDecoder (include a copy of dns record)
		)
		>		ServiceResolverEvtCallback;

	/// Event callback  for air::bonjour::AddressResolver
	/// @note   After the TTL expires, the client should consider the result no longer valid
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,			/// _1 flags
		boost::uint32_t,			/// _2 interfaceIndex
		air::bonjour::BonjourError,	/// _3 error
		std::string,				/// _4 hostname the hostname that you ask for rsolve address
		boost::asio::ip::address,	/// _5 address	rsolved address
		boost::uint32_t				/// _6 TTL indicates how long the client may legitimately hold onto this result(address), in seconds.
		)
		>		AddressResolverEvtCallback;

	/// Event callback  for air::bonjour::DomainEumerater
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,					/// _1 flags
		boost::uint32_t,					/// _2 interfaceIndex
		air::bonjour::BonjourError,			/// _3 error
		std::string							/// _4 replyDomain
		)
		>
		EnumerationEvtCallback;

	/// Event callback  for air::bonjour::NatMappingService
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,			/// _1 flags,Currently unused, reserved for future use
		boost::uint32_t,			/// _2 interfaceIndex
		air::bonjour::BonjourError,	/// _3 error
		boost::uint16_t,			/// _6 internal port
		boost::asio::ip::address,	/// _4 external address
		boost::uint16_t,			/// _5 external port,may be different than the requested port
		air::bonjour::ProtoType,	/// _6 protocol used for nat mapping
		boost::uint32_t,			/// _7 TTL , in seconds.indicates The lifetime of the NAT port mapping created on the gateway.
		air::bonjour::NatStatus		/// _8 NatStatus ,used to check nat status if error==true
		)
		>		NatMapingEvtCallback;

}//namespace
}//namespace
#endif//BONJOUR_DNSD_CALLBACK_FUNC_DEF_H__<commit_msg>copy comment to callback func<commit_after>#ifndef BONJOUR_DNSD_CALLBACK_FUNC_DEF_H__
#define BONJOUR_DNSD_CALLBACK_FUNC_DEF_H__

#include <boost/function.hpp>

#include <ddnspp/bonjourpp/dnsdapi.hpp>
#include <ddnspp/bonjourpp/bonjourerror.hpp>
#include <ddnspp/bonjourpp/txtrecords.hpp>
#include <ddnspp/bonjourpp/prototype.hpp>
#include <ddnspp/bonjourpp/nat_status.hpp>

namespace air{namespace bonjour {

	/// Event callback  for air::bonjour::DomainEumerater
	/*
	 *
	 * Asynchronously enumerate domains available for browsing and registration.
	 *
	 * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains
	 * are to be found.
	 *
	 * Note that the names returned are (like all of DNS-SD) UTF-8 strings,
	 * and are escaped using standard DNS escaping rules.
	 * (See "Notes on DNS Name Escaping" earlier in this file for more details.)
	 * A graphical browser displaying a hierarchical tree-structured view should cut
	 * the names at the bare dots to yield individual labels, then de-escape each
	 * label according to the escaping rules, and then display the resulting UTF-8 text.
	 *
	 * Parameters:
	 *
	 *
	 * flags:           Possible values are:
	 *                  kDNSServiceFlagsMoreComing
	 *                  kDNSServiceFlagsAdd
	 *                  kDNSServiceFlagsDefault
	 *
	 * interfaceIndex:  Specifies the interface on which the domain exists. (The index for a given
	 *                  interface is determined via the if_nametoindex() family of calls.)
	 *
	 * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise indicates
	 *                  the failure that occurred (other parameters are undefined if errorCode is nonzero).
	 *
	 * replyDomain:     The name of the domain.
	 *
	 *
	 */
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,					/// _1 flags
		boost::uint32_t,					/// _2 interfaceIndex
		air::bonjour::BonjourError,			/// _3 error
		std::string							/// _4 replyDomain
		)
		>
		EnumerationEvtCallback;

	/// Event callback for air::bonjour::LocalService
	/*
	 * Parameters:
	 *
	 *
	 * flags:           When a name is successfully registered, the callback will be
	 *                  invoked with the kDNSServiceFlagsAdd flag set. When Wide-Area
	 *                  DNS-SD is in use, it is possible for a single service to get
	 *                  more than one success callback (e.g. one in the "local" multicast
	 *                  DNS domain, and another in a wide-area unicast DNS domain).
	 *                  If a successfully-registered name later suffers a name conflict
	 *                  or similar problem and has to be deregistered, the callback will
	 *                  be invoked with the kDNSServiceFlagsAdd flag not set. The callback
	 *                  is *not* invoked in the case where the caller explicitly terminates
	 *                  the service registration by calling DNSServiceRefDeallocate(ref);
	 *
	 * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
	 *                  indicate the failure that occurred (including name conflicts,
	 *                  if the kDNSServiceFlagsNoAutoRename flag was used when registering.)
	 *                  Other parameters are undefined if errorCode is nonzero.
	 *
	 * name:            The service name registered (if the application did not specify a name in
	 *                  DNSServiceRegister(), this indicates what name was automatically chosen).
	 *
	 * regtype:         The type of service registered, as it was passed to the callout.
	 *
	 * domain:          The domain on which the service was registered (if the application did not
	 *                  specify a domain in DNSServiceRegister(), this indicates the default domain
	 *                  on which the service was registered).
	 *
	 *
	 */
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,					/// _1 flags
		air::bonjour::BonjourError,			/// _2 errorCode
		std::string,						/// _3 service name
		std::string,						/// _4 service type
		std::string							/// _5 domian
		)
		>		LocalServiceEvtCallback;

	/// Event callback  for air::bonjour::RemoteService
	/* Parameters:
	 *
	 *
	 * flags:           Possible values are kDNSServiceFlagsMoreComing and kDNSServiceFlagsAdd.
	 *                  See flag definitions for details.
	 *
	 * interfaceIndex:  The interface on which the service is advertised. This index should
	 *                  be passed to DNSServiceResolve() when resolving the service.
	 *
	 * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise will
	 *                  indicate the failure that occurred. Other parameters are undefined if
	 *                  the errorCode is nonzero.
	 *
	 * serviceName:     The discovered service name. This name should be displayed to the user,
	 *                  and stored for subsequent use in the DNSServiceResolve() call.
	 *
	 * serviceType:     The service type, which is usually (but not always) the same as was passed
	 *                  to DNSServiceBrowse(). One case where the discovered service type may
	 *                  not be the same as the requested service type is when using subtypes:
	 *                  The client may want to browse for only those ftp servers that allow
	 *                  anonymous connections. The client will pass the string "_ftp._tcp,_anon"
	 *                  to DNSServiceBrowse(), but the type of the service that's discovered
	 *                  is simply "_ftp._tcp". The regtype for each discovered service instance
	 *                  should be stored along with the name, so that it can be passed to
	 *                  DNSServiceResolve() when the service is later resolved.
	 *
	 * domain:          The domain of the discovered service instance. This may or may not be the
	 *                  same as the domain that was passed to DNSServiceBrowse(). The domain for each
	 *                  discovered service instance should be stored along with the name, so that
	 *                  it can be passed to DNSServiceResolve() when the service is later resolved.
	 *
	 *
	 */
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,					/// _1 flags
		boost::uint32_t,					/// _2 interfaceIndex
		air::bonjour::BonjourError,			/// _3 error
		std::string,						/// _4 service name (for subsequent use in the ServiceResolver )
		std::string,						/// _5 service type
		std::string							/// _6 domian
		)
		>
		RemoteServiceEvtCallback;

	/// Event callback  for air::bonjour::ServiceResolver
	/*
	 *
	 * Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and
	 * txt record.
	 *
	 * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use
	 * DNSServiceQueryRecord() instead, as it is more efficient for this task.
	 *
	 * Note: When the desired results have been returned, the client MUST terminate the resolve by calling
	 * DNSServiceRefDeallocate().
	 *
	 * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record
	 * and a single TXT record. To resolve non-standard services with multiple SRV or TXT records,
	 * DNSServiceQueryRecord() should be used.
	 *
	 * Parameters:
	 *
	 *
	 * flags:           Possible values: kDNSServiceFlagsMoreComing
	 *
	 * interfaceIndex:  The interface on which the service was resolved.
	 *
	 * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise will
	 *                  indicate the failure that occurred. Other parameters are undefined if
	 *                  the errorCode is nonzero.
	 *
	 * fullname:        The full service domain name, in the form <servicename>.<protocol>.<domain>.
	 *                  (This name is escaped following standard DNS rules, making it suitable for
	 *                  passing to standard system DNS APIs such as res_query(), or to the
	 *                  special-purpose functions included in this API that take fullname parameters.
	 *                  See "Notes on DNS Name Escaping" earlier in this file for more details.)
	 *
	 * hosttarget:      The target hostname of the machine providing the service. This name can
	 *                  be passed to functions like gethostbyname() to identify the host's IP address.
	 *
	 * port:            The port, in network byte order, on which connections are accepted for this service.
	 *
	 * txtRecord:       The service's primary txt record, in standard txt record format.
	 *
	 * NOTE: In earlier versions of this header file, the txtRecord parameter was declared "const char *"
	 * This is incorrect, since it contains length bytes which are values in the range 0 to 255, not -128 to +127.
	 * Depending on your compiler settings, this change may cause signed/unsigned mismatch warnings.
	 * These should be fixed by updating your own callback function definition to match the corrected
	 * function signature using "const unsigned char *txtRecord". Making this change may also fix inadvertent
	 * bugs in your callback function, where it could have incorrectly interpreted a length byte with value 250
	 * as being -6 instead, with various bad consequences ranging from incorrect operation to software crashes.
	 * If you need to maintain portable code that will compile cleanly with both the old and new versions of
	 * this header file, you should update your callback function definition to use the correct unsigned value,
	 * and then in the place where you pass your callback function to DNSServiceResolve(), use a cast to eliminate
	 * the compiler warning, e.g.:
	 *   DNSServiceResolve(sd, flags, index, name, regtype, domain, (DNSServiceResolveReply)MyCallback, context);
	 * This will ensure that your code compiles cleanly without warnings (and more importantly, works correctly)
	 * with both the old header and with the new corrected version.
	 *
	 */
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,					/// _1 flags
		boost::uint32_t,					/// _2 interfaceIndex
		air::bonjour::BonjourError,			/// _3 error
		std::string,						/// _4 service name(fullname, format:<servicename>.<protocol>.<domain>)
		std::string,						/// _5 host name ,This name can  be passed to functions like gethostbyname() to identify the host's IP address.
		boost::uint16_t,					/// _6 port
		TxtRecordDecoderPtr					/// _7 TxtRecordDecoder (include a copy of dns record)
		)
		>		ServiceResolverEvtCallback;

	/// Event callback  for air::bonjour::AddressResolver
	/*
	 *
	 * Queries for the IP address of a hostname by using either Multicast or Unicast DNS.
	 *
	 * parameters:
	 *
	 *
	 * flags:           Possible values are kDNSServiceFlagsMoreComing and
	 *                  kDNSServiceFlagsAdd.
	 *
	 * interfaceIndex:  The interface to which the answers pertain.
	 *
	 * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
	 *                  indicate the failure that occurred.  Other parameters are
	 *                  undefined if errorCode is nonzero.
	 *
	 * hostname:        The fully qualified domain name of the host to be queried for.
	 *
	 * address:         IPv4 or IPv6 address.
	 *
	 * ttl:             If the client wishes to cache the result for performance reasons,
	 *                  the TTL indicates how long the client may legitimately hold onto
	 *                  this result, in seconds. After the TTL expires, the client should
	 *                  consider the result no longer valid, and if it requires this data
	 *                  again, it should be re-fetched with a new query. Of course, this
	 *                  only applies to clients that cancel the asynchronous operation when
	 *                  they get a result. Clients that leave the asynchronous operation
	 *                  running can safely assume that the data remains valid until they
	 *                  get another callback telling them otherwise.
	 *
	 *
	 */
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,			/// _1 flags
		boost::uint32_t,			/// _2 interfaceIndex
		air::bonjour::BonjourError,	/// _3 error
		std::string,				/// _4 hostname the hostname that you ask for rsolve address
		boost::asio::ip::address,	/// _5 address	rsolved address
		boost::uint32_t				/// _6 TTL indicates how long the client may legitimately hold onto this result(address), in seconds.
		)
		>		AddressResolverEvtCallback;

	/// Event callback  for air::bonjour::NatMappingService
	/*
	 *
	 * Request a port mapping in the NAT gateway, which maps a port on the local machine
	 * to an external port on the NAT.
	 *
	 * The port mapping will be renewed indefinitely until the client process exits, or
	 * explicitly terminates the port mapping request by calling DNSServiceRefDeallocate().
	 * The client callback will be invoked, informing the client of the NAT gateway's
	 * external IP address and the external port that has been allocated for this client.
	 * The client should then record this external IP address and port using whatever
	 * directory service mechanism it is using to enable peers to connect to it.
	 * (Clients advertising services using Wide-Area DNS-SD DO NOT need to use this API
	 * -- when a client calls DNSServiceRegister() NAT mappings are automatically created
	 * and the external IP address and port for the service are recorded in the global DNS.
	 * Only clients using some directory mechanism other than Wide-Area DNS-SD need to use
	 * this API to explicitly map their own ports.)
	 *
	 * It's possible that the client callback could be called multiple times, for example
	 * if the NAT gateway's IP address changes, or if a configuration change results in a
	 * different external port being mapped for this client. Over the lifetime of any long-lived
	 * port mapping, the client should be prepared to handle these notifications of changes
	 * in the environment, and should update its recorded address and/or port as appropriate.
	 *
	 * NOTE: There are two unusual aspects of how the DNSServiceNATPortMappingCreate API works,
	 * which were intentionally designed to help simplify client code:
	 *
	 *  1. It's not an error to request a NAT mapping when the machine is not behind a NAT gateway.
	 *     In other NAT mapping APIs, if you request a NAT mapping and the machine is not behind a NAT
	 *     gateway, then the API returns an error code -- it can't get you a NAT mapping if there's no
	 *     NAT gateway. The DNSServiceNATPortMappingCreate API takes a different view. Working out
	 *     whether or not you need a NAT mapping can be tricky and non-obvious, particularly on
	 *     a machine with multiple active network interfaces. Rather than make every client recreate
	 *     this logic for deciding whether a NAT mapping is required, the PortMapping API does that
	 *     work for you. If the client calls the PortMapping API when the machine already has a
	 *     routable public IP address, then instead of complaining about it and giving an error,
	 *     the PortMapping API just invokes your callback, giving the machine's public address
	 *     and your own port number. This means you don't need to write code to work out whether
	 *     your client needs to call the PortMapping API -- just call it anyway, and if it wasn't
	 *     necessary, no harm is done:
	 *
	 *     - If the machine already has a routable public IP address, then your callback
	 *       will just be invoked giving your own address and port.
	 *     - If a NAT mapping is required and obtained, then your callback will be invoked
	 *       giving you the external address and port.
	 *     - If a NAT mapping is required but not obtained from the local NAT gateway,
	 *       or the machine has no network connectivity, then your callback will be
	 *       invoked giving zero address and port.
	 *
	 *  2. In other NAT mapping APIs, if a laptop computer is put to sleep and woken up on a new
	 *     network, it's the client's job to notice this, and work out whether a NAT mapping
	 *     is required on the new network, and make a new NAT mapping request if necessary.
	 *     The DNSServiceNATPortMappingCreate API does this for you, automatically.
	 *     The client just needs to make one call to the PortMapping API, and its callback will
	 *     be invoked any time the mapping state changes. This property complements point (1) above.
	 *     If the client didn't make a NAT mapping request just because it determined that one was
	 *     not required at that particular moment in time, the client would then have to monitor
	 *     for network state changes to determine if a NAT port mapping later became necessary.
	 *     By unconditionally making a NAT mapping request, even when a NAT mapping not to be
	 *     necessary, the PortMapping API will then begin monitoring network state changes on behalf of
	 *     the client, and if a NAT mapping later becomes necessary, it will automatically create a NAT
	 *     mapping and inform the client with a new callback giving the new address and port information.
	 *
	 * parameters:
	 *
	 *
	 * flags:           Currently unused, reserved for future use.
	 *
	 * interfaceIndex:  The interface through which the NAT gateway is reached.
	 *
	 * errorCode:       Will be kDNSServiceErr_NoError on success.
	 *                  Will be kDNSServiceErr_DoubleNAT when the NAT gateway is itself behind one or
	 *                  more layers of NAT, in which case the other parameters have the defined values.
	 *                  For other failures, will indicate the failure that occurred, and the other
	 *                  parameters are undefined.
	 *
	 * externalAddress: Four byte IPv4 address in network byte order.
	 *
	 * protocol:        Will be kDNSServiceProtocol_UDP or kDNSServiceProtocol_TCP or both.
	 *
	 * internalPort:    The port on the local machine that was mapped.
	 *
	 * externalPort:    The actual external port in the NAT gateway that was mapped.
	 *                  This is likely to be different than the requested external port.
	 *
	 * ttl:             The lifetime of the NAT port mapping created on the gateway.
	 *                  This controls how quickly stale mappings will be garbage-collected
	 *                  if the client machine crashes, suffers a power failure, is disconnected
	 *                  from the network, or suffers some other unfortunate demise which
	 *                  causes it to vanish without explicitly removing its NAT port mapping.
	 *                  It's possible that the ttl value will differ from the requested ttl value.
	 *
	 *
	 */
	typedef boost::function
		<
		void
		(
		DNSServiceFlags,			/// _1 flags,Currently unused, reserved for future use
		boost::uint32_t,			/// _2 interfaceIndex
		air::bonjour::BonjourError,	/// _3 error
		boost::uint16_t,			/// _6 internal port
		boost::asio::ip::address,	/// _4 external address
		boost::uint16_t,			/// _5 external port,may be different than the requested port
		air::bonjour::ProtoType,	/// _6 protocol used for nat mapping
		boost::uint32_t,			/// _7 TTL , in seconds.indicates The lifetime of the NAT port mapping created on the gateway.
		air::bonjour::NatStatus		/// _8 NatStatus ,used to check nat status if error==true
		)
		>		NatMapingEvtCallback;

}//namespace
}//namespace
#endif//BONJOUR_DNSD_CALLBACK_FUNC_DEF_H__<|endoftext|>


<commit_before>//===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting descriptions of the calling
// conventions supported by this target.
//
//===----------------------------------------------------------------------===//

#include "CallingConvEmitter.h"
#include "Record.h"
#include "CodeGenTarget.h"
using namespace llvm;

void CallingConvEmitter::run(raw_ostream &O) {
  EmitSourceFileHeader("Calling Convention Implementation Fragment", O);

  std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");

  // Emit prototypes for all of the CC's so that they can forward ref each
  // other.
  for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
    O << "static bool " << CCs[i]->getName()
      << "(unsigned ValNo, MVT ValVT,\n"
      << std::string(CCs[i]->getName().size()+13, ' ')
      << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
      << std::string(CCs[i]->getName().size()+13, ' ')
      << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
  }

  // Emit each calling convention description in full.
  for (unsigned i = 0, e = CCs.size(); i != e; ++i)
    EmitCallingConv(CCs[i], O);
}

void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
  ListInit *CCActions = CC->getValueAsListInit("Actions");
  Counter = 0;

  O << "\n\nstatic bool " << CC->getName()
    << "(unsigned ValNo, MVT ValVT,\n"
    << std::string(CC->getName().size()+13, ' ')
    << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
    << std::string(CC->getName().size()+13, ' ')
    << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
  // Emit all of the actions, in order.
  for (unsigned i = 0, e = CCActions->getSize(); i != e; ++i) {
    O << "\n";
    EmitAction(CCActions->getElementAsRecord(i), 2, O);
  }

  O << "\n  return true;  // CC didn't match.\n";
  O << "}\n";
}

void CallingConvEmitter::EmitAction(Record *Action,
                                    unsigned Indent, raw_ostream &O) {
  std::string IndentStr = std::string(Indent, ' ');

  if (Action->isSubClassOf("CCPredicateAction")) {
    O << IndentStr << "if (";

    if (Action->isSubClassOf("CCIfType")) {
      ListInit *VTs = Action->getValueAsListInit("VTs");
      for (unsigned i = 0, e = VTs->getSize(); i != e; ++i) {
        Record *VT = VTs->getElementAsRecord(i);
        if (i != 0) O << " ||\n    " << IndentStr;
        O << "LocVT == " << getEnumName(getValueType(VT));
      }

    } else if (Action->isSubClassOf("CCIf")) {
      O << Action->getValueAsString("Predicate");
    } else {
      Action->dump();
      throw "Unknown CCPredicateAction!";
    }

    O << ") {\n";
    EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
    O << IndentStr << "}\n";
  } else {
    if (Action->isSubClassOf("CCDelegateTo")) {
      Record *CC = Action->getValueAsDef("CC");
      O << IndentStr << "if (!" << CC->getName()
        << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
        << IndentStr << "  return false;\n";
    } else if (Action->isSubClassOf("CCAssignToReg")) {
      ListInit *RegList = Action->getValueAsListInit("RegList");
      if (RegList->getSize() == 1) {
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
        O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n";
      } else {
        O << IndentStr << "static const unsigned RegList" << ++Counter
          << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(RegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
          << Counter << ", " << RegList->getSize() << ")) {\n";
      }
      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
        << "Reg, LocVT, LocInfo));\n";
      O << IndentStr << "  return false;\n";
      O << IndentStr << "}\n";
    } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
      ListInit *RegList = Action->getValueAsListInit("RegList");
      ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
      if (ShadowRegList->getSize() >0 &&
          ShadowRegList->getSize() != RegList->getSize())
        throw "Invalid length of list of shadowed registers";

      if (RegList->getSize() == 1) {
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
        O << getQualifiedName(RegList->getElementAsRecord(0));
        O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
        O << ")) {\n";
      } else {
        unsigned RegListNumber = ++Counter;
        unsigned ShadowRegListNumber = ++Counter;

        O << IndentStr << "static const unsigned RegList" << RegListNumber
          << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(RegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";

        O << IndentStr << "static const unsigned RegList"
          << ShadowRegListNumber << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";

        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
          << RegListNumber << ", " << "RegList" << ShadowRegListNumber
          << ", " << RegList->getSize() << ")) {\n";
      }
      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
        << "Reg, LocVT, LocInfo));\n";
      O << IndentStr << "  return false;\n";
      O << IndentStr << "}\n";
    } else if (Action->isSubClassOf("CCAssignToStack")) {
      int Size = Action->getValueAsInt("Size");
      int Align = Action->getValueAsInt("Align");

      O << IndentStr << "unsigned Offset" << ++Counter
        << " = State.AllocateStack(";
      if (Size)
        O << Size << ", ";
      else
        O << "\n" << IndentStr << "  State.getTarget().getTargetData()"
          "->getTypeAllocSize(LocVT.getTypeForMVT()), ";
      if (Align)
        O << Align;
      else
        O << "\n" << IndentStr << "  State.getTarget().getTargetData()"
          "->getABITypeAlignment(LocVT.getTypeForMVT())";
      O << ");\n" << IndentStr
        << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
        << Counter << ", LocVT, LocInfo));\n";
      O << IndentStr << "return false;\n";
    } else if (Action->isSubClassOf("CCPromoteToType")) {
      Record *DestTy = Action->getValueAsDef("DestTy");
      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
      O << IndentStr << "if (ArgFlags.isSExt())\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"
        << IndentStr << "else if (ArgFlags.isZExt())\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"
        << IndentStr << "else\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
    } else if (Action->isSubClassOf("CCBitConvertToType")) {
      Record *DestTy = Action->getValueAsDef("DestTy");
      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
      O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
    } else if (Action->isSubClassOf("CCPassByVal")) {
      int Size = Action->getValueAsInt("Size");
      int Align = Action->getValueAsInt("Align");
      O << IndentStr
        << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
        << Size << ", " << Align << ", ArgFlags);\n";
      O << IndentStr << "return false;\n";
    } else if (Action->isSubClassOf("CCCustom")) {
      O << IndentStr
        << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
        << "LocVT, LocInfo, ArgFlags, State))\n";
      O << IndentStr << IndentStr << "return false;\n";
    } else {
      Action->dump();
      throw "Unknown CCAction!";
    }
  }
}
<commit_msg>Thread LLVMContext through MVT and related parts of SDISel.<commit_after>//===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting descriptions of the calling
// conventions supported by this target.
//
//===----------------------------------------------------------------------===//

#include "CallingConvEmitter.h"
#include "Record.h"
#include "CodeGenTarget.h"
using namespace llvm;

void CallingConvEmitter::run(raw_ostream &O) {
  EmitSourceFileHeader("Calling Convention Implementation Fragment", O);

  std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");

  // Emit prototypes for all of the CC's so that they can forward ref each
  // other.
  for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
    O << "static bool " << CCs[i]->getName()
      << "(unsigned ValNo, MVT ValVT,\n"
      << std::string(CCs[i]->getName().size()+13, ' ')
      << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
      << std::string(CCs[i]->getName().size()+13, ' ')
      << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
  }

  // Emit each calling convention description in full.
  for (unsigned i = 0, e = CCs.size(); i != e; ++i)
    EmitCallingConv(CCs[i], O);
}

void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
  ListInit *CCActions = CC->getValueAsListInit("Actions");
  Counter = 0;

  O << "\n\nstatic bool " << CC->getName()
    << "(unsigned ValNo, MVT ValVT,\n"
    << std::string(CC->getName().size()+13, ' ')
    << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
    << std::string(CC->getName().size()+13, ' ')
    << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
  // Emit all of the actions, in order.
  for (unsigned i = 0, e = CCActions->getSize(); i != e; ++i) {
    O << "\n";
    EmitAction(CCActions->getElementAsRecord(i), 2, O);
  }

  O << "\n  return true;  // CC didn't match.\n";
  O << "}\n";
}

void CallingConvEmitter::EmitAction(Record *Action,
                                    unsigned Indent, raw_ostream &O) {
  std::string IndentStr = std::string(Indent, ' ');

  if (Action->isSubClassOf("CCPredicateAction")) {
    O << IndentStr << "if (";

    if (Action->isSubClassOf("CCIfType")) {
      ListInit *VTs = Action->getValueAsListInit("VTs");
      for (unsigned i = 0, e = VTs->getSize(); i != e; ++i) {
        Record *VT = VTs->getElementAsRecord(i);
        if (i != 0) O << " ||\n    " << IndentStr;
        O << "LocVT == " << getEnumName(getValueType(VT));
      }

    } else if (Action->isSubClassOf("CCIf")) {
      O << Action->getValueAsString("Predicate");
    } else {
      Action->dump();
      throw "Unknown CCPredicateAction!";
    }

    O << ") {\n";
    EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
    O << IndentStr << "}\n";
  } else {
    if (Action->isSubClassOf("CCDelegateTo")) {
      Record *CC = Action->getValueAsDef("CC");
      O << IndentStr << "if (!" << CC->getName()
        << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
        << IndentStr << "  return false;\n";
    } else if (Action->isSubClassOf("CCAssignToReg")) {
      ListInit *RegList = Action->getValueAsListInit("RegList");
      if (RegList->getSize() == 1) {
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
        O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n";
      } else {
        O << IndentStr << "static const unsigned RegList" << ++Counter
          << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(RegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
          << Counter << ", " << RegList->getSize() << ")) {\n";
      }
      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
        << "Reg, LocVT, LocInfo));\n";
      O << IndentStr << "  return false;\n";
      O << IndentStr << "}\n";
    } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
      ListInit *RegList = Action->getValueAsListInit("RegList");
      ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
      if (ShadowRegList->getSize() >0 &&
          ShadowRegList->getSize() != RegList->getSize())
        throw "Invalid length of list of shadowed registers";

      if (RegList->getSize() == 1) {
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
        O << getQualifiedName(RegList->getElementAsRecord(0));
        O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
        O << ")) {\n";
      } else {
        unsigned RegListNumber = ++Counter;
        unsigned ShadowRegListNumber = ++Counter;

        O << IndentStr << "static const unsigned RegList" << RegListNumber
          << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(RegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";

        O << IndentStr << "static const unsigned RegList"
          << ShadowRegListNumber << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";

        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
          << RegListNumber << ", " << "RegList" << ShadowRegListNumber
          << ", " << RegList->getSize() << ")) {\n";
      }
      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
        << "Reg, LocVT, LocInfo));\n";
      O << IndentStr << "  return false;\n";
      O << IndentStr << "}\n";
    } else if (Action->isSubClassOf("CCAssignToStack")) {
      int Size = Action->getValueAsInt("Size");
      int Align = Action->getValueAsInt("Align");

      O << IndentStr << "unsigned Offset" << ++Counter
        << " = State.AllocateStack(";
      if (Size)
        O << Size << ", ";
      else
        O << "\n" << IndentStr << "  State.getTarget().getTargetData()"
          "->getTypeAllocSize(LocVT.getTypeForMVT(*State.getContext())), ";
      if (Align)
        O << Align;
      else
        O << "\n" << IndentStr << "  State.getTarget().getTargetData()"
          "->getABITypeAlignment(LocVT.getTypeForMVT(*State.getContext()))";
      O << ");\n" << IndentStr
        << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
        << Counter << ", LocVT, LocInfo));\n";
      O << IndentStr << "return false;\n";
    } else if (Action->isSubClassOf("CCPromoteToType")) {
      Record *DestTy = Action->getValueAsDef("DestTy");
      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
      O << IndentStr << "if (ArgFlags.isSExt())\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"
        << IndentStr << "else if (ArgFlags.isZExt())\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"
        << IndentStr << "else\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
    } else if (Action->isSubClassOf("CCBitConvertToType")) {
      Record *DestTy = Action->getValueAsDef("DestTy");
      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
      O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
    } else if (Action->isSubClassOf("CCPassByVal")) {
      int Size = Action->getValueAsInt("Size");
      int Align = Action->getValueAsInt("Align");
      O << IndentStr
        << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
        << Size << ", " << Align << ", ArgFlags);\n";
      O << IndentStr << "return false;\n";
    } else if (Action->isSubClassOf("CCCustom")) {
      O << IndentStr
        << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
        << "LocVT, LocInfo, ArgFlags, State))\n";
      O << IndentStr << IndentStr << "return false;\n";
    } else {
      Action->dump();
      throw "Unknown CCAction!";
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>lb_http: use LbClusterConfig::sticky_mode<commit_after><|endoftext|>