<commit_before>/************************************************
 *  gen.hpp
 *  ESA++
 *
 *  Copyright (c) 2014, Chi-En Wu
 *  Distributed under The BSD 3-Clause License
 ************************************************/

#ifndef ESAPP_GEN_HPP_
#define ESAPP_GEN_HPP_

#include <iterator>
#include <type_traits>

namespace esapp
{

/************************************************
 * Declaration: class generator_iterator
 ************************************************/

template <typename I, typename G>
class generator_iterator
    : public std::iterator<
        std::input_iterator_tag,
        typename std::result_of<G(I &, I const &)>::type,
        ptrdiff_t,
        typename std::add_pointer<
            typename std::add_const<
                typename std::result_of<G(I &, I const &)>::type
            >::type
        >::type,
        typename std::add_lvalue_reference<
            typename std::add_const<
                typename std::result_of<G(I &, I const &)>::type
            >::type
        >::type
    >
{
private: // Private Type(s)
    typedef std::iterator<
        std::input_iterator_tag,
        typename std::result_of<G(I &, I const &)>::type,
        ptrdiff_t,
        typename std::add_pointer<
            typename std::add_const<
                typename std::result_of<G(I &, I const &)>::type
            >::type
        >::type,
        typename std::add_lvalue_reference<
            typename std::add_const<
                typename std::result_of<G(I &, I const &)>::type
            >::type
        >::type
    > base;

public: // Public Type(s)
    typedef typename base::iterator_category iterator_category;
    typedef typename base::value_type value_type;
    typedef typename base::reference reference;
    typedef typename base::pointer pointer;
    typedef typename base::difference_type difference_type;

    typedef I iterator;
    typedef G generator;

public: // Public Method(s)
    generator_iterator(iterator const &begin, iterator const &end,
                       generator const &g);
    template <typename Initializer>
    generator_iterator(iterator const &begin, iterator const &end,
                       generator const &g, Initializer const &init);
    generator_iterator(generator_iterator const &it);

    generator_iterator begin(void) const;
    generator_iterator end(void) const;

    generator_iterator &operator++(void);
    generator_iterator operator++(int);
    reference operator*(void) const;
    pointer operator->(void) const;
    bool operator==(generator_iterator const &it) const;
    bool operator!=(generator_iterator const &it) const;

private: // Private Property(ies)
    iterator begin_, end_;
    generator g_;
    value_type val_;
    bool has_val_;
}; // class generator_iterator

/************************************************
 * Implementation: class generator_iterator
 ************************************************/

template <typename I, typename G>
inline generator_iterator<I, G>::generator_iterator(iterator const &begin,
                                                    iterator const &end,
                                                    generator const &g)
    : begin_(begin), end_(end), g_(g)
{
    operator++();
}

template <typename I, typename G>
template <typename Initializer>
inline generator_iterator<I, G>::generator_iterator(iterator const &begin,
                                                    iterator const &end,
                                                    generator const &g,
                                                    Initializer const &init)
    : begin_(begin), end_(end), g_(g)
{
    init(begin_, end_);
    operator++();
}

template <typename I, typename G>
inline generator_iterator<I, G>::generator_iterator(generator_iterator const &it)
    : begin_(it.begin_), end_(it.end_), g_(it.g_),
      val_(it.val_), has_val_(it.has_val_)
{
    // do nothing
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::generator_iterator
generator_iterator<I, G>::begin(void) const
{
    return *this;
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::generator_iterator
generator_iterator<I, G>::end(void) const
{
    return generator_iterator(end_, end_, g_);
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::generator_iterator &
generator_iterator<I, G>::operator++(void)
{
    has_val_ = begin_ != end_;
    val_ = has_val_ ? g_(begin_, end_) : decltype(val_)();

    return *this;
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::generator_iterator
generator_iterator<I, G>::operator++(int)
{
    generator_iterator it(*this);
    operator++();
    return it;
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::reference
generator_iterator<I, G>::operator*(void) const
{
    return val_;
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::pointer
generator_iterator<I, G>::operator->(void) const
{
    return &val_;
}

template <typename I, typename G>
inline bool generator_iterator<I, G>::operator==(generator_iterator const &it) const
{
    return begin_ == it.begin_ && end_ == it.end_ && g_ == it.g_ &&
           val_ == it.val_ && has_val_ == it.has_val_;
}

template <typename I, typename G>
inline bool generator_iterator<I, G>::operator!=(generator_iterator const &it) const
{
    return !(*this == it);
}

} // namespace esapp

#endif // ESAPP_GEN_HPP_
<commit_msg>Simpify typedefs for generator<commit_after>/************************************************
 *  gen.hpp
 *  ESA++
 *
 *  Copyright (c) 2014, Chi-En Wu
 *  Distributed under The BSD 3-Clause License
 ************************************************/

#ifndef ESAPP_GEN_HPP_
#define ESAPP_GEN_HPP_

#include <iterator>
#include <type_traits>

namespace esapp
{

/************************************************
 * Declaration: class generator_iterator
 ************************************************/

template <typename I, typename G>
class generator_iterator
    : public std::iterator<
        std::input_iterator_tag,
        typename std::result_of<G(I &, I const &)>::type,
        ptrdiff_t,
        typename std::add_pointer<
            typename std::add_const<
                typename std::result_of<G(I &, I const &)>::type
            >::type
        >::type,
        typename std::add_lvalue_reference<
            typename std::add_const<
                typename std::result_of<G(I &, I const &)>::type
            >::type
        >::type
    >
{
public: // Public Type(s)
    typedef std::input_iterator_tag iterator_category;
    typedef typename std::result_of<G(I &, I const &)>::type value_type;
    typedef value_type const &reference;
    typedef value_type const *pointer;
    typedef ptrdiff_t difference_type;

    typedef I iterator;
    typedef G generator;

public: // Public Method(s)
    generator_iterator(iterator const &begin, iterator const &end,
                       generator const &g);
    template <typename Initializer>
    generator_iterator(iterator const &begin, iterator const &end,
                       generator const &g, Initializer const &init);
    generator_iterator(generator_iterator const &it);

    generator_iterator begin(void) const;
    generator_iterator end(void) const;

    generator_iterator &operator++(void);
    generator_iterator operator++(int);
    reference operator*(void) const;
    pointer operator->(void) const;
    bool operator==(generator_iterator const &it) const;
    bool operator!=(generator_iterator const &it) const;

private: // Private Property(ies)
    iterator begin_, end_;
    generator g_;
    value_type val_;
    bool has_val_;
}; // class generator_iterator

/************************************************
 * Implementation: class generator_iterator
 ************************************************/

template <typename I, typename G>
inline generator_iterator<I, G>::generator_iterator(iterator const &begin,
                                                    iterator const &end,
                                                    generator const &g)
    : begin_(begin), end_(end), g_(g)
{
    operator++();
}

template <typename I, typename G>
template <typename Initializer>
inline generator_iterator<I, G>::generator_iterator(iterator const &begin,
                                                    iterator const &end,
                                                    generator const &g,
                                                    Initializer const &init)
    : begin_(begin), end_(end), g_(g)
{
    init(begin_, end_);
    operator++();
}

template <typename I, typename G>
inline generator_iterator<I, G>::generator_iterator(generator_iterator const &it)
    : begin_(it.begin_), end_(it.end_), g_(it.g_),
      val_(it.val_), has_val_(it.has_val_)
{
    // do nothing
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::generator_iterator
generator_iterator<I, G>::begin(void) const
{
    return *this;
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::generator_iterator
generator_iterator<I, G>::end(void) const
{
    return generator_iterator(end_, end_, g_);
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::generator_iterator &
generator_iterator<I, G>::operator++(void)
{
    has_val_ = begin_ != end_;
    val_ = has_val_ ? g_(begin_, end_) : decltype(val_)();

    return *this;
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::generator_iterator
generator_iterator<I, G>::operator++(int)
{
    generator_iterator it(*this);
    operator++();
    return it;
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::reference
generator_iterator<I, G>::operator*(void) const
{
    return val_;
}

template <typename I, typename G>
inline typename generator_iterator<I, G>::pointer
generator_iterator<I, G>::operator->(void) const
{
    return &val_;
}

template <typename I, typename G>
inline bool generator_iterator<I, G>::operator==(generator_iterator const &it) const
{
    return begin_ == it.begin_ && end_ == it.end_ && g_ == it.g_ &&
           val_ == it.val_ && has_val_ == it.has_val_;
}

template <typename I, typename G>
inline bool generator_iterator<I, G>::operator!=(generator_iterator const &it) const
{
    return !(*this == it);
}

} // namespace esapp

#endif // ESAPP_GEN_HPP_
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef URI_HPP
#define URI_HPP

#include <gsl.h>
#include <unordered_map>

namespace uri {

  /**
   * Representation of RFC 3986 URI's.
   * Ref. https://tools.ietf.org/html/rfc3986
   **/
  class URI {
  private:
    /** Non-owning pointer-size type */
    struct Span_t {
      size_t begin;
      size_t end;

      Span_t(const size_t b = 0U, const size_t e = 0U) noexcept
        : begin{b}
        , end{e}
      {}
    }; //< struct Span_t

  public:
    /*
     * Default constructor
     */
    URI() = default;

    /*
     * Default copy and move constructors
     */
    URI(URI&) = default;
    URI(URI&&) = default;

    /*
     * Default destructor
     */
    ~URI() = default;

    /*
     * Default assignment operators
     */
    URI& operator=(const URI&) = default;
    URI& operator=(URI&&) = default;

    //
    // We might do a span-based constructor later.
    // URI(gsl::span<const char>);
    //

    /**
     * @brief Construct using a C-String
     *
     * @param uri : A C-String representing a uri
     */
    URI(const char* uri);

    /**
     * @brief Construct using a string
     *
     * @param uri : A string representing a uri
     */
    URI(const std::string& uri);

    ///////////////////////////////////////////////
    //----------RFC-specified URI parts----------//
    ///////////////////////////////////////////////

    /**
     * @brief Get userinfo.
     *
     * E.g. 'username@'...
     *
     * @return The user's information
     */
    std::string userinfo() const;

    /**
     * @brief Get host.
     *
     * E.g. 'includeos.org', '10.0.0.42' etc.
     *
     * @return The host's information
     */
    std::string host() const;

    /**
     * @brief Get the raw port number in decimal character representation.
     *
     * @return The raw port number as a string
     */
    std::string port_str() const;

    /**
     * @brief Get numeric port number.
     *
     * @warning The RFC doesn't specify dimension. This funcion will truncate
     * any overflowing digits.
     *
     * @return The numeric port number as a 16-bit number
     */
    uint16_t port() const noexcept;

    /** Get the path. E.g. /pictures/logo.png  */
    std::string path() const;

    /** Get the complete unparsed query string. */
    const std::string query() const;

    /** Get the fragment part. E.g. "...#anchor1" */
    const std::string fragment() const;

    ///
    /// Convenience
    ///

    /**
     * Get the URI-decoded value of a query-string key.
     *
     * E.g. for query() => "?name=Bjarne%20Stroustrup",
     * query("name") returns "Bjarne Stroustrup" */
    std::string query(std::string key);

    /** String representation **/
    std::string to_string() const;

  private:

    std::unordered_map<std::string,std::string> queries_;
    Span_t uri_data_;
    Span_t userinfo_;
    Span_t host_;
    Span_t port_str_;
    uint16_t port_ = 0;
    Span_t path_;
    Span_t query_;
    Span_t fragment_;

    static const Span_t zero_span_;

    // A copy of the data, if the string-based constructor was used
    std::string uri_str_;

    /**
     * @brief Parse the given string representing a uri
     * into its given parts according to RFC 3986
     *
     * @param uri : The string representing a uri
     */
    void parse(const std::string& uri);

  }; // class uri::URI

  std::ostream& operator<< (std::ostream&, const URI&);

} // namespace uri

#endif
<commit_msg>Changed API doc for method API::path<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef URI_HPP
#define URI_HPP

#include <gsl.h>
#include <unordered_map>

namespace uri {

  /**
   * Representation of RFC 3986 URI's.
   * Ref. https://tools.ietf.org/html/rfc3986
   **/
  class URI {
  private:
    /** Non-owning pointer-size type */
    struct Span_t {
      size_t begin;
      size_t end;

      Span_t(const size_t b = 0U, const size_t e = 0U) noexcept
        : begin{b}
        , end{e}
      {}
    }; //< struct Span_t

  public:
    /*
     * Default constructor
     */
    URI() = default;

    /*
     * Default copy and move constructors
     */
    URI(URI&) = default;
    URI(URI&&) = default;

    /*
     * Default destructor
     */
    ~URI() = default;

    /*
     * Default assignment operators
     */
    URI& operator=(const URI&) = default;
    URI& operator=(URI&&) = default;

    //
    // We might do a span-based constructor later.
    // URI(gsl::span<const char>);
    //

    /**
     * @brief Construct using a C-String
     *
     * @param uri : A C-String representing a uri
     */
    URI(const char* uri);

    /**
     * @brief Construct using a string
     *
     * @param uri : A string representing a uri
     */
    URI(const std::string& uri);

    ///////////////////////////////////////////////
    //----------RFC-specified URI parts----------//
    ///////////////////////////////////////////////

    /**
     * @brief Get userinfo.
     *
     * E.g. 'username@'...
     *
     * @return The user's information
     */
    std::string userinfo() const;

    /**
     * @brief Get host.
     *
     * E.g. 'includeos.org', '10.0.0.42' etc.
     *
     * @return The host's information
     */
    std::string host() const;

    /**
     * @brief Get the raw port number in decimal character representation.
     *
     * @return The raw port number as a string
     */
    std::string port_str() const;

    /**
     * @brief Get numeric port number.
     *
     * @warning The RFC doesn't specify dimension. This funcion will truncate
     * any overflowing digits.
     *
     * @return The numeric port number as a 16-bit number
     */
    uint16_t port() const noexcept;

    /**
     * @brief Get the path.
     *
     * E.g. /pictures/logo.png
     *
     * @return The path information
     */
    std::string path() const;

    /** Get the complete unparsed query string. */
    const std::string query() const;

    /** Get the fragment part. E.g. "...#anchor1" */
    const std::string fragment() const;

    ///
    /// Convenience
    ///

    /**
     * Get the URI-decoded value of a query-string key.
     *
     * E.g. for query() => "?name=Bjarne%20Stroustrup",
     * query("name") returns "Bjarne Stroustrup" */
    std::string query(std::string key);

    /** String representation **/
    std::string to_string() const;

  private:

    std::unordered_map<std::string,std::string> queries_;
    Span_t uri_data_;
    Span_t userinfo_;
    Span_t host_;
    Span_t port_str_;
    uint16_t port_ = 0;
    Span_t path_;
    Span_t query_;
    Span_t fragment_;

    static const Span_t zero_span_;

    // A copy of the data, if the string-based constructor was used
    std::string uri_str_;

    /**
     * @brief Parse the given string representing a uri
     * into its given parts according to RFC 3986
     *
     * @param uri : The string representing a uri
     */
    void parse(const std::string& uri);

  }; // class uri::URI

  std::ostream& operator<< (std::ostream&, const URI&);

} // namespace uri

#endif
<|endoftext|>


<commit_before>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=========================================================================*/

// QT includes
#include <QChildEvent>
#include <QDebug>
#include <QDialogButtonBox>
#include <QEvent>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QListView>
#include <QPushButton>

// CTK includes
#include "ctkFileDialog.h"

//------------------------------------------------------------------------------
class ctkFileDialogPrivate
{
  Q_DECLARE_PUBLIC(ctkFileDialog);
protected:
  ctkFileDialog* const q_ptr;
public:
  ctkFileDialogPrivate(ctkFileDialog& object);
  void init();
  void observeAcceptButton();

  QPushButton* acceptButton()const;
  QListView* listView()const;

  bool AcceptButtonEnable;
  bool AcceptButtonState;
  bool IgnoreEvent;
};

//------------------------------------------------------------------------------
ctkFileDialogPrivate::ctkFileDialogPrivate(ctkFileDialog& object)
  :q_ptr(&object)
{
  this->IgnoreEvent = false;
  this->AcceptButtonEnable = true;
  this->AcceptButtonState = true;
}

//------------------------------------------------------------------------------
void ctkFileDialogPrivate::init()
{
  Q_Q(ctkFileDialog);

  this->observeAcceptButton();

  QObject::connect(this->listView()->selectionModel(),
                   SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
                   q, SLOT(onSelectionChanged()));
}

//------------------------------------------------------------------------------
QPushButton* ctkFileDialogPrivate::acceptButton()const
{
  Q_Q(const ctkFileDialog);
  QDialogButtonBox* buttonBox = q->findChild<QDialogButtonBox*>();
  Q_ASSERT(buttonBox);
  QDialogButtonBox::StandardButton button =
    (q->acceptMode() == QFileDialog::AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);
  return buttonBox->button(button);
}

//------------------------------------------------------------------------------
QListView* ctkFileDialogPrivate::listView()const
{
  Q_Q(const ctkFileDialog);
  QListView* listView= q->findChild<QListView*>("listView");
  Q_ASSERT(listView);
  return listView;
}

//------------------------------------------------------------------------------
void ctkFileDialogPrivate::observeAcceptButton()
{
  Q_Q(ctkFileDialog);
  QPushButton* button = this->acceptButton();
  Q_ASSERT(button);
  this->AcceptButtonState =
    button->isEnabledTo(qobject_cast<QWidget*>(button->parent()));
  // TODO: catching the event of the enable state is not enough, if the user
  // double click on the file, the dialog will be accepted, that event should
  // be intercepted as well
  button->installEventFilter(q);
}

//------------------------------------------------------------------------------
ctkFileDialog::ctkFileDialog(QWidget *parentWidget,
              const QString &caption,
              const QString &directory,
              const QString &filter)
  :QFileDialog(parentWidget, caption, directory, filter)
  , d_ptr(new ctkFileDialogPrivate(*this))
{
  Q_D(ctkFileDialog);

#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
  this->setOptions(DontUseNativeDialog);
#endif

  d->init();
}

//------------------------------------------------------------------------------
ctkFileDialog::~ctkFileDialog()
{
}

//------------------------------------------------------------------------------
void ctkFileDialog::setBottomWidget(QWidget* widget, const QString& label)
{
  QGridLayout* gridLayout = qobject_cast<QGridLayout*>(this->layout());
  QWidget* oldBottomWidget = this->bottomWidget();
  // remove the old widget from the layout if any
  if (oldBottomWidget)
    {
    if (oldBottomWidget == widget)
      {
      return;
      }
    gridLayout->removeWidget(oldBottomWidget);
    delete oldBottomWidget;
    }
  if (widget == 0)
    {
    return;
    }
  if (!label.isEmpty())
    {
    gridLayout->addWidget(new QLabel(label), 4, 0);
    gridLayout->addWidget(widget,4, 1,1, 1);
    }
  else
    {
    gridLayout->addWidget(widget,4, 0,1, 2);
    }
  // The dialog button box is no longer spanned on 2 rows but on 3 rows if
  // there is a "bottom widget"
  QDialogButtonBox* buttonBox = this->findChild<QDialogButtonBox*>();
  Q_ASSERT(buttonBox);
  gridLayout->removeWidget(buttonBox);
  gridLayout->addWidget(buttonBox, 2, 2, widget ? 3 : 2, 1);
}

//------------------------------------------------------------------------------
QWidget* ctkFileDialog::bottomWidget()const
{
  QGridLayout* gridLayout = qobject_cast<QGridLayout*>(this->layout());
  QLayoutItem* item = gridLayout->itemAtPosition(4,1);
  return item ? item->widget() : 0;
}

//------------------------------------------------------------------------------
void ctkFileDialog::setAcceptButtonEnable(bool enable)
{
  Q_D(ctkFileDialog);
  d->AcceptButtonEnable = enable;
  d->IgnoreEvent = true;
  d->acceptButton()->setEnabled(d->AcceptButtonEnable && d->AcceptButtonState);
  d->IgnoreEvent = false;
}

//------------------------------------------------------------------------------
bool ctkFileDialog::eventFilter(QObject *obj, QEvent *event)
{
  Q_D(ctkFileDialog);
  QPushButton* button = d->acceptButton();
  QDialogButtonBox* dialogButtonBox = qobject_cast<QDialogButtonBox*>(obj);
  if (obj == button && event->type() == QEvent::EnabledChange &&
      !d->IgnoreEvent)
    {
    d->IgnoreEvent = true;
    d->AcceptButtonState = button->isEnabledTo(qobject_cast<QWidget*>(button->parent()));
    button->setEnabled(d->AcceptButtonEnable && d->AcceptButtonState);
    d->IgnoreEvent = false;
    }
  else if (obj == button && event->type() == QEvent::Destroy)
    {
    // The accept button is deleted probably because setAcceptMode() is being called.
    // observe the parent to check when the accept button is added back
    obj->parent()->installEventFilter(this);
    }
  else if (dialogButtonBox && event->type() == QEvent::ChildAdded)
    {
    dynamic_cast<QChildEvent*>(event)->child()->installEventFilter(this);
    }
  return QFileDialog::eventFilter(obj, event);
}

//------------------------------------------------------------------------------
void ctkFileDialog::onSelectionChanged()
{
  emit this->fileSelectionChanged(this->selectedFiles());
}

//------------------------------------------------------------------------------
void ctkFileDialog::accept()
{
  QLineEdit* fileNameEdit = qobject_cast<QLineEdit*>(this->sender());
  if (fileNameEdit)
    {
    QFileInfo info(fileNameEdit->text());
    if (info.isDir())
      {
      setDirectory(info.absoluteFilePath());
      return;
      }
    }
  // Don't accept read-only directories if we are in AcceptSave mode.
  if ((this->fileMode() == Directory || this->fileMode() == DirectoryOnly) &&
      this->acceptMode() == AcceptSave)
    {
    QStringList files = this->selectedFiles();
    QString fn = files.first();
    QFileInfo info(fn);
    if (info.isDir() && !info.isWritable())
      {
      this->setDirectory(info.absoluteFilePath());
      return;
      }
    }
  this->Superclass::accept();
}
<commit_msg>improved in-code description of previous ctkFileDialog crash fix<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=========================================================================*/

// QT includes
#include <QChildEvent>
#include <QDebug>
#include <QDialogButtonBox>
#include <QEvent>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QListView>
#include <QPushButton>

// CTK includes
#include "ctkFileDialog.h"

//------------------------------------------------------------------------------
class ctkFileDialogPrivate
{
  Q_DECLARE_PUBLIC(ctkFileDialog);
protected:
  ctkFileDialog* const q_ptr;
public:
  ctkFileDialogPrivate(ctkFileDialog& object);
  void init();
  void observeAcceptButton();

  QPushButton* acceptButton()const;
  QListView* listView()const;

  bool AcceptButtonEnable;
  bool AcceptButtonState;
  bool IgnoreEvent;
};

//------------------------------------------------------------------------------
ctkFileDialogPrivate::ctkFileDialogPrivate(ctkFileDialog& object)
  :q_ptr(&object)
{
  this->IgnoreEvent = false;
  this->AcceptButtonEnable = true;
  this->AcceptButtonState = true;
}

//------------------------------------------------------------------------------
void ctkFileDialogPrivate::init()
{
  Q_Q(ctkFileDialog);

  this->observeAcceptButton();

  QObject::connect(this->listView()->selectionModel(),
                   SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
                   q, SLOT(onSelectionChanged()));
}

//------------------------------------------------------------------------------
QPushButton* ctkFileDialogPrivate::acceptButton()const
{
  Q_Q(const ctkFileDialog);
  QDialogButtonBox* buttonBox = q->findChild<QDialogButtonBox*>();
  Q_ASSERT(buttonBox);
  QDialogButtonBox::StandardButton button =
    (q->acceptMode() == QFileDialog::AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);
  return buttonBox->button(button);
}

//------------------------------------------------------------------------------
QListView* ctkFileDialogPrivate::listView()const
{
  Q_Q(const ctkFileDialog);
  QListView* listView= q->findChild<QListView*>("listView");
  Q_ASSERT(listView);
  return listView;
}

//------------------------------------------------------------------------------
void ctkFileDialogPrivate::observeAcceptButton()
{
  Q_Q(ctkFileDialog);
  QPushButton* button = this->acceptButton();
  Q_ASSERT(button);
  this->AcceptButtonState =
    button->isEnabledTo(qobject_cast<QWidget*>(button->parent()));
  // TODO: catching the event of the enable state is not enough, if the user
  // double click on the file, the dialog will be accepted, that event should
  // be intercepted as well
  button->installEventFilter(q);
}

//------------------------------------------------------------------------------
ctkFileDialog::ctkFileDialog(QWidget *parentWidget,
              const QString &caption,
              const QString &directory,
              const QString &filter)
  :QFileDialog(parentWidget, caption, directory, filter)
  , d_ptr(new ctkFileDialogPrivate(*this))
{
  Q_D(ctkFileDialog);

// The findChild<QDialogButtonBox*>() call fails on Mac/Qt5 because native
// dialogs don't publish any internals. No problems on other OS.
// Can be applied to Qt4 as well, if problems arise there.
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
  this->setOptions(DontUseNativeDialog);
#endif

  d->init();
}

//------------------------------------------------------------------------------
ctkFileDialog::~ctkFileDialog()
{
}

//------------------------------------------------------------------------------
void ctkFileDialog::setBottomWidget(QWidget* widget, const QString& label)
{
  QGridLayout* gridLayout = qobject_cast<QGridLayout*>(this->layout());
  QWidget* oldBottomWidget = this->bottomWidget();
  // remove the old widget from the layout if any
  if (oldBottomWidget)
    {
    if (oldBottomWidget == widget)
      {
      return;
      }
    gridLayout->removeWidget(oldBottomWidget);
    delete oldBottomWidget;
    }
  if (widget == 0)
    {
    return;
    }
  if (!label.isEmpty())
    {
    gridLayout->addWidget(new QLabel(label), 4, 0);
    gridLayout->addWidget(widget,4, 1,1, 1);
    }
  else
    {
    gridLayout->addWidget(widget,4, 0,1, 2);
    }
  // The dialog button box is no longer spanned on 2 rows but on 3 rows if
  // there is a "bottom widget"
  QDialogButtonBox* buttonBox = this->findChild<QDialogButtonBox*>();
  Q_ASSERT(buttonBox);
  gridLayout->removeWidget(buttonBox);
  gridLayout->addWidget(buttonBox, 2, 2, widget ? 3 : 2, 1);
}

//------------------------------------------------------------------------------
QWidget* ctkFileDialog::bottomWidget()const
{
  QGridLayout* gridLayout = qobject_cast<QGridLayout*>(this->layout());
  QLayoutItem* item = gridLayout->itemAtPosition(4,1);
  return item ? item->widget() : 0;
}

//------------------------------------------------------------------------------
void ctkFileDialog::setAcceptButtonEnable(bool enable)
{
  Q_D(ctkFileDialog);
  d->AcceptButtonEnable = enable;
  d->IgnoreEvent = true;
  d->acceptButton()->setEnabled(d->AcceptButtonEnable && d->AcceptButtonState);
  d->IgnoreEvent = false;
}

//------------------------------------------------------------------------------
bool ctkFileDialog::eventFilter(QObject *obj, QEvent *event)
{
  Q_D(ctkFileDialog);
  QPushButton* button = d->acceptButton();
  QDialogButtonBox* dialogButtonBox = qobject_cast<QDialogButtonBox*>(obj);
  if (obj == button && event->type() == QEvent::EnabledChange &&
      !d->IgnoreEvent)
    {
    d->IgnoreEvent = true;
    d->AcceptButtonState = button->isEnabledTo(qobject_cast<QWidget*>(button->parent()));
    button->setEnabled(d->AcceptButtonEnable && d->AcceptButtonState);
    d->IgnoreEvent = false;
    }
  else if (obj == button && event->type() == QEvent::Destroy)
    {
    // The accept button is deleted probably because setAcceptMode() is being called.
    // observe the parent to check when the accept button is added back
    obj->parent()->installEventFilter(this);
    }
  else if (dialogButtonBox && event->type() == QEvent::ChildAdded)
    {
    dynamic_cast<QChildEvent*>(event)->child()->installEventFilter(this);
    }
  return QFileDialog::eventFilter(obj, event);
}

//------------------------------------------------------------------------------
void ctkFileDialog::onSelectionChanged()
{
  emit this->fileSelectionChanged(this->selectedFiles());
}

//------------------------------------------------------------------------------
void ctkFileDialog::accept()
{
  QLineEdit* fileNameEdit = qobject_cast<QLineEdit*>(this->sender());
  if (fileNameEdit)
    {
    QFileInfo info(fileNameEdit->text());
    if (info.isDir())
      {
      setDirectory(info.absoluteFilePath());
      return;
      }
    }
  // Don't accept read-only directories if we are in AcceptSave mode.
  if ((this->fileMode() == Directory || this->fileMode() == DirectoryOnly) &&
      this->acceptMode() == AcceptSave)
    {
    QStringList files = this->selectedFiles();
    QString fn = files.first();
    QFileInfo info(fn);
    if (info.isDir() && !info.isWritable())
      {
      this->setDirectory(info.absoluteFilePath());
      return;
      }
    }
  this->Superclass::accept();
}
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/mlir/tensorflow/transforms/bridge.h"

#include "mlir/Pass/PassManager.h"  // TF:local_config_mlir
#include "mlir/Transforms/Passes.h"  // TF:local_config_mlir
#include "tensorflow/compiler/mlir/tensorflow/transforms/passes.h"
#include "tensorflow/compiler/mlir/tensorflow/utils/error_util.h"

namespace mlir {
namespace TFTPU {

void createTPUBridge(OpPassManager &pm) {
  OpPassManager &func_pm = pm.nest<FuncOp>();
  func_pm.addPass(tf_executor::CreateTFExecutorIslandCoarseningPass());
  func_pm.addPass(createCanonicalizerPass());
  func_pm.addPass(CreateTPUClusterFormationPass());
  func_pm.addPass(tf_executor::CreateTFExecutorConstantSinkingPass());
  func_pm.addPass(TFDevice::CreateResourceOpLiftingPass());

  pm.addPass(TFDevice::CreateClusterOutliningPass());
  pm.addPass(CreateTPURewritePass());
  pm.addNestedPass<FuncOp>(TFDevice::CreateReplicateInvariantOpHoistingPass());
  pm.addNestedPass<FuncOp>(CreateFunctionalToExecutorDialectConversionPass());
  pm.addNestedPass<FuncOp>(CreateBreakUpIslandsPass());
  pm.addNestedPass<FuncOp>(TFDevice::CreateReplicateToIslandPass());
  pm.addNestedPass<FuncOp>(CreateBreakUpIslandsPass());
  pm.addNestedPass<FuncOp>(createCanonicalizerPass());
}

tensorflow::Status TPUBridge(ModuleOp module) {
  // Populate a passmanager with the list of passes that implement the bridge.
  PassManager bridge(module.getContext());
  createTPUBridge(bridge);

  // Run the bridge on the module, in case of failure, the `diag_handler`
  // converts MLIR errors emitted to the MLIRContext into a tensorflow::Status.
  mlir::StatusScopedDiagnosticHandler diag_handler(module.getContext());
  if (failed(bridge.run(module))) return diag_handler.ConsumeStatus();
  return diag_handler.ConsumeStatus();
}

}  // namespace TFTPU
}  // namespace mlir
<commit_msg>Move canonicalizer pass to after TPU cluster formation to prevent canonicalization from losing _tpu_replicate attributes<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/mlir/tensorflow/transforms/bridge.h"

#include "mlir/Pass/PassManager.h"  // TF:local_config_mlir
#include "mlir/Transforms/Passes.h"  // TF:local_config_mlir
#include "tensorflow/compiler/mlir/tensorflow/transforms/passes.h"
#include "tensorflow/compiler/mlir/tensorflow/utils/error_util.h"

namespace mlir {
namespace TFTPU {

void createTPUBridge(OpPassManager &pm) {
  OpPassManager &func_pm = pm.nest<FuncOp>();
  func_pm.addPass(tf_executor::CreateTFExecutorIslandCoarseningPass());
  func_pm.addPass(CreateTPUClusterFormationPass());
  func_pm.addPass(createCanonicalizerPass());
  func_pm.addPass(tf_executor::CreateTFExecutorConstantSinkingPass());
  func_pm.addPass(TFDevice::CreateResourceOpLiftingPass());

  pm.addPass(TFDevice::CreateClusterOutliningPass());
  pm.addPass(CreateTPURewritePass());
  pm.addNestedPass<FuncOp>(TFDevice::CreateReplicateInvariantOpHoistingPass());
  pm.addNestedPass<FuncOp>(CreateFunctionalToExecutorDialectConversionPass());
  pm.addNestedPass<FuncOp>(CreateBreakUpIslandsPass());
  pm.addNestedPass<FuncOp>(TFDevice::CreateReplicateToIslandPass());
  pm.addNestedPass<FuncOp>(CreateBreakUpIslandsPass());
  pm.addNestedPass<FuncOp>(createCanonicalizerPass());
}

tensorflow::Status TPUBridge(ModuleOp module) {
  // Populate a passmanager with the list of passes that implement the bridge.
  PassManager bridge(module.getContext());
  createTPUBridge(bridge);

  // Run the bridge on the module, in case of failure, the `diag_handler`
  // converts MLIR errors emitted to the MLIRContext into a tensorflow::Status.
  mlir::StatusScopedDiagnosticHandler diag_handler(module.getContext());
  if (failed(bridge.run(module))) return diag_handler.ConsumeStatus();
  return diag_handler.ConsumeStatus();
}

}  // namespace TFTPU
}  // namespace mlir
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <boost/shared_ptr.hpp>
#include <unicode/regex.h>

#include <comphelper/configuration.hxx>
#include <officecfg/Office/Common.hxx>
#include <opencl/openclconfig.hxx>
#include <opencl/platforminfo.hxx>
#include <rtl/ustring.hxx>
#include <sal/types.h>

OpenCLConfig::OpenCLConfig() :
    mbUseOpenCL(true)
{
    // This entry we have had for some time (when blacklisting was
    // done elsewhere in the code), so presumably there is a known
    // good reason for it.
    maBlackList.insert(ImplMatcher("Windows", "", "Intel\\(R\\) Corporation", "", "9\\.17\\.10\\.2884"));

    // This is what I have tested on Linux and it works for our unit tests.
    maWhiteList.insert(ImplMatcher("Linux", "", "Advanced Micro Devices, Inc\\.", "", "1445\\.5 \\(sse2,avx\\)"));

    // For now, assume that AMD, Intel and NVIDIA drivers are good
    maWhiteList.insert(ImplMatcher("", "", "Advanced Micro Devices, Inc\\.", "", ""));
    maWhiteList.insert(ImplMatcher("", "", "Intel\\(R\\) Corporation", "", ""));
    maWhiteList.insert(ImplMatcher("", "", "NVIDIA Corporation", "", ""));
}

bool OpenCLConfig::operator== (const OpenCLConfig& r) const
{
    return (mbUseOpenCL == r.mbUseOpenCL &&
            maBlackList == r.maBlackList &&
            maWhiteList == r.maWhiteList &&
            true);
}

bool OpenCLConfig::operator!= (const OpenCLConfig& r) const
{
    return !operator== (r);
}

namespace {

css::uno::Sequence<OUString> SetOfImplMatcherToStringSequence(const OpenCLConfig::ImplMatcherSet& rSet)
{
    css::uno::Sequence<OUString> result(rSet.size());

    size_t n(0);
    for (auto i = rSet.cbegin(); i != rSet.cend(); ++i)
    {
        result[n++] =
            (*i).maOS.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
            (*i).maOSVersion.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
            (*i).maPlatformVendor.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
            (*i).maDevice.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
            (*i).maDriverVersion.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B");
    }

    return result;
}

OUString getToken(const OUString& string, sal_Int32& index)
{
    OUString token(string.getToken(0, '/', index));
    OUString result;
    sal_Int32 i(0);
    sal_Int32 p;
    while ((p = token.indexOf('%', i)) >= 0)
    {
        if (p > i)
            result += token.copy(i, p - i);
        if (p < token.getLength() - 2)
        {
            result += OUString(static_cast<sal_Unicode>(token.copy(p+1, 2).toInt32(16)));
            i = p + 3;
        }
        else
        {
            i = token.getLength();
        }
    }
    result += token.copy(i);

    return result;
}

OpenCLConfig::ImplMatcherSet StringSequenceToSetOfImplMatcher(const css::uno::Sequence<OUString>& rSequence)
{
    OpenCLConfig::ImplMatcherSet result;

    for (auto i = rSequence.begin(); i != rSequence.end(); ++i)
    {
        OpenCLConfig::ImplMatcher m;
        sal_Int32 index(0);
        m.maOS = getToken(*i, index);
        m.maOSVersion = getToken(*i, index);
        m.maPlatformVendor = getToken(*i, index);
        m.maDevice = getToken(*i, index);
        m.maDriverVersion = getToken(*i, index);

        result.insert(m);
    }

    return result;
}

bool match(const OUString& rPattern, const OUString& rInput)
{
    if (rPattern == "")
        return true;

    UErrorCode nIcuError(U_ZERO_ERROR);
    icu::UnicodeString sIcuPattern(reinterpret_cast<const UChar*>(rPattern.getStr()), rPattern.getLength());
    icu::UnicodeString sIcuInput(reinterpret_cast<const UChar*>(rInput.getStr()), rInput.getLength());
    RegexMatcher aMatcher(sIcuPattern, sIcuInput, 0, nIcuError);

    if (U_SUCCESS(nIcuError) && aMatcher.matches(nIcuError) && U_SUCCESS(nIcuError))
        return true;

    return false;
}

bool match(const OpenCLConfig::ImplMatcher& rListEntry, const OpenCLPlatformInfo& rPlatform, const OpenCLDeviceInfo& rDevice)
{
#if defined WNT
    if (rListEntry.maOS != "" && rListEntry.maOS != "Windows")
        return false;
#elif defined LINUX
    if (rListEntry.maOS != "" && rListEntry.maOS != "Linux")
        return false;
#elif defined MACOSX
    if (rListEntry.maOS != "" && rListEntry.maOS != "OS X")
        return false;
#endif

    // OS version check not yet implemented

    if (!match(rListEntry.maPlatformVendor, rPlatform.maVendor))
        return false;

    if (!match(rListEntry.maDevice, rDevice.maName))
        return false;

    if (!match(rListEntry.maDriverVersion, rDevice.maDriver))
        return false;

    return true;
}

bool match(const OpenCLConfig::ImplMatcherSet& rList, const OpenCLPlatformInfo& rPlatform, const OpenCLDeviceInfo& rDevice, const char* sKindOfList)
{
    for (auto i = rList.cbegin(); i != rList.end(); ++i)
    {
        SAL_INFO("opencl", "Looking for match for platform=" << rPlatform << ", device=" << rDevice <<
                 " in " << sKindOfList << " entry=" << *i);

        if (match(*i, rPlatform, rDevice))
        {
            SAL_INFO("opencl", "Match!");
            return true;
        }
    }
    return false;
}

} // anonymous namespace

OpenCLConfig OpenCLConfig::get()
{
    OpenCLConfig result;

    result.mbUseOpenCL = officecfg::Office::Common::Misc::UseOpenCL::get();

    result.maBlackList = StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLBlackList::get());
    result.maWhiteList = StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLWhiteList::get());

    return result;
}

void OpenCLConfig::set()
{
    boost::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());

    officecfg::Office::Common::Misc::UseOpenCL::set(mbUseOpenCL, batch);
    officecfg::Office::Common::Misc::OpenCLBlackList::set(SetOfImplMatcherToStringSequence(maBlackList), batch);
    officecfg::Office::Common::Misc::OpenCLWhiteList::set(SetOfImplMatcherToStringSequence(maWhiteList), batch);

    batch->commit();
}

bool OpenCLConfig::checkImplementation(const OpenCLPlatformInfo& rPlatform, const OpenCLDeviceInfo& rDevice) const
{
    // Check blacklist of known bad OpenCL implementations
    if (match(maBlackList, rPlatform, rDevice, "blacklist"))
    {
        SAL_INFO("opencl", "Rejecting");
        return true;
    }

    // Check for whitelist of known good OpenCL implementations
    if (match(maWhiteList, rPlatform, rDevice, "whitelist"))
    {
        SAL_INFO("opencl", "Approving");
        return false;
    }

    // Fallback: reject
    SAL_INFO("opencl", "Fallback: rejecting platform=" << rPlatform << ", device=" << rDevice);
    return true;
}

std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig& rConfig)
{
    rStream << "{"
        "UseOpenCL=" << (rConfig.mbUseOpenCL ? "YES" : "NO") << ","
        "BlackList=" << rConfig.maBlackList << ","
        "WhiteList=" << rConfig.maWhiteList <<
        "}";
    return rStream;
}

std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig::ImplMatcher& rImpl)
{
    rStream << "{"
        "OS=" << rImpl.maOS << ","
        "OSVersion=" << rImpl.maOSVersion << ","
        "PlatformVendor=" << rImpl.maPlatformVendor << ","
        "Device=" << rImpl.maDevice << ","
        "DriverVersion=" << rImpl.maDriverVersion <<
        "}";

    return rStream;
}

std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig::ImplMatcherSet& rSet)
{
    rStream << "{";
    for (auto i = rSet.cbegin(); i != rSet.cend(); ++i)
    {
        if (i != rSet.cbegin())
            rStream << ",";
        rStream << *i;
    }
    rStream << "}";
    return rStream;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>opencl: Use appropriate OUString functions on string constants<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <boost/shared_ptr.hpp>
#include <unicode/regex.h>

#include <comphelper/configuration.hxx>
#include <officecfg/Office/Common.hxx>
#include <opencl/openclconfig.hxx>
#include <opencl/platforminfo.hxx>
#include <rtl/ustring.hxx>
#include <sal/types.h>

OpenCLConfig::OpenCLConfig() :
    mbUseOpenCL(true)
{
    // This entry we have had for some time (when blacklisting was
    // done elsewhere in the code), so presumably there is a known
    // good reason for it.
    maBlackList.insert(ImplMatcher("Windows", "", "Intel\\(R\\) Corporation", "", "9\\.17\\.10\\.2884"));

    // This is what I have tested on Linux and it works for our unit tests.
    maWhiteList.insert(ImplMatcher("Linux", "", "Advanced Micro Devices, Inc\\.", "", "1445\\.5 \\(sse2,avx\\)"));

    // For now, assume that AMD, Intel and NVIDIA drivers are good
    maWhiteList.insert(ImplMatcher("", "", "Advanced Micro Devices, Inc\\.", "", ""));
    maWhiteList.insert(ImplMatcher("", "", "Intel\\(R\\) Corporation", "", ""));
    maWhiteList.insert(ImplMatcher("", "", "NVIDIA Corporation", "", ""));
}

bool OpenCLConfig::operator== (const OpenCLConfig& r) const
{
    return (mbUseOpenCL == r.mbUseOpenCL &&
            maBlackList == r.maBlackList &&
            maWhiteList == r.maWhiteList &&
            true);
}

bool OpenCLConfig::operator!= (const OpenCLConfig& r) const
{
    return !operator== (r);
}

namespace {

css::uno::Sequence<OUString> SetOfImplMatcherToStringSequence(const OpenCLConfig::ImplMatcherSet& rSet)
{
    css::uno::Sequence<OUString> result(rSet.size());

    size_t n(0);
    for (auto i = rSet.cbegin(); i != rSet.cend(); ++i)
    {
        result[n++] =
            (*i).maOS.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
            (*i).maOSVersion.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
            (*i).maPlatformVendor.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
            (*i).maDevice.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
            (*i).maDriverVersion.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B");
    }

    return result;
}

OUString getToken(const OUString& string, sal_Int32& index)
{
    OUString token(string.getToken(0, '/', index));
    OUString result;
    sal_Int32 i(0);
    sal_Int32 p;
    while ((p = token.indexOf('%', i)) >= 0)
    {
        if (p > i)
            result += token.copy(i, p - i);
        if (p < token.getLength() - 2)
        {
            result += OUString(static_cast<sal_Unicode>(token.copy(p+1, 2).toInt32(16)));
            i = p + 3;
        }
        else
        {
            i = token.getLength();
        }
    }
    result += token.copy(i);

    return result;
}

OpenCLConfig::ImplMatcherSet StringSequenceToSetOfImplMatcher(const css::uno::Sequence<OUString>& rSequence)
{
    OpenCLConfig::ImplMatcherSet result;

    for (auto i = rSequence.begin(); i != rSequence.end(); ++i)
    {
        OpenCLConfig::ImplMatcher m;
        sal_Int32 index(0);
        m.maOS = getToken(*i, index);
        m.maOSVersion = getToken(*i, index);
        m.maPlatformVendor = getToken(*i, index);
        m.maDevice = getToken(*i, index);
        m.maDriverVersion = getToken(*i, index);

        result.insert(m);
    }

    return result;
}

bool match(const OUString& rPattern, const OUString& rInput)
{
    if (rPattern.isEmpty())
        return true;

    UErrorCode nIcuError(U_ZERO_ERROR);
    icu::UnicodeString sIcuPattern(reinterpret_cast<const UChar*>(rPattern.getStr()), rPattern.getLength());
    icu::UnicodeString sIcuInput(reinterpret_cast<const UChar*>(rInput.getStr()), rInput.getLength());
    RegexMatcher aMatcher(sIcuPattern, sIcuInput, 0, nIcuError);

    if (U_SUCCESS(nIcuError) && aMatcher.matches(nIcuError) && U_SUCCESS(nIcuError))
        return true;

    return false;
}

bool match(const OpenCLConfig::ImplMatcher& rListEntry, const OpenCLPlatformInfo& rPlatform, const OpenCLDeviceInfo& rDevice)
{
#if defined WNT
    if (!rListEntry.maOS.isEmpty() && rListEntry.maOS != "Windows")
        return false;
#elif defined LINUX
    if (!rListEntry.maOS.isEmpty() && rListEntry.maOS != "Linux")
        return false;
#elif defined MACOSX
    if (!rListEntry.maOS.isEmpty() && rListEntry.maOS != "OS X")
        return false;
#endif

    // OS version check not yet implemented

    if (!match(rListEntry.maPlatformVendor, rPlatform.maVendor))
        return false;

    if (!match(rListEntry.maDevice, rDevice.maName))
        return false;

    if (!match(rListEntry.maDriverVersion, rDevice.maDriver))
        return false;

    return true;
}

bool match(const OpenCLConfig::ImplMatcherSet& rList, const OpenCLPlatformInfo& rPlatform, const OpenCLDeviceInfo& rDevice, const char* sKindOfList)
{
    for (auto i = rList.cbegin(); i != rList.end(); ++i)
    {
        SAL_INFO("opencl", "Looking for match for platform=" << rPlatform << ", device=" << rDevice <<
                 " in " << sKindOfList << " entry=" << *i);

        if (match(*i, rPlatform, rDevice))
        {
            SAL_INFO("opencl", "Match!");
            return true;
        }
    }
    return false;
}

} // anonymous namespace

OpenCLConfig OpenCLConfig::get()
{
    OpenCLConfig result;

    result.mbUseOpenCL = officecfg::Office::Common::Misc::UseOpenCL::get();

    result.maBlackList = StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLBlackList::get());
    result.maWhiteList = StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLWhiteList::get());

    return result;
}

void OpenCLConfig::set()
{
    boost::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());

    officecfg::Office::Common::Misc::UseOpenCL::set(mbUseOpenCL, batch);
    officecfg::Office::Common::Misc::OpenCLBlackList::set(SetOfImplMatcherToStringSequence(maBlackList), batch);
    officecfg::Office::Common::Misc::OpenCLWhiteList::set(SetOfImplMatcherToStringSequence(maWhiteList), batch);

    batch->commit();
}

bool OpenCLConfig::checkImplementation(const OpenCLPlatformInfo& rPlatform, const OpenCLDeviceInfo& rDevice) const
{
    // Check blacklist of known bad OpenCL implementations
    if (match(maBlackList, rPlatform, rDevice, "blacklist"))
    {
        SAL_INFO("opencl", "Rejecting");
        return true;
    }

    // Check for whitelist of known good OpenCL implementations
    if (match(maWhiteList, rPlatform, rDevice, "whitelist"))
    {
        SAL_INFO("opencl", "Approving");
        return false;
    }

    // Fallback: reject
    SAL_INFO("opencl", "Fallback: rejecting platform=" << rPlatform << ", device=" << rDevice);
    return true;
}

std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig& rConfig)
{
    rStream << "{"
        "UseOpenCL=" << (rConfig.mbUseOpenCL ? "YES" : "NO") << ","
        "BlackList=" << rConfig.maBlackList << ","
        "WhiteList=" << rConfig.maWhiteList <<
        "}";
    return rStream;
}

std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig::ImplMatcher& rImpl)
{
    rStream << "{"
        "OS=" << rImpl.maOS << ","
        "OSVersion=" << rImpl.maOSVersion << ","
        "PlatformVendor=" << rImpl.maPlatformVendor << ","
        "Device=" << rImpl.maDevice << ","
        "DriverVersion=" << rImpl.maDriverVersion <<
        "}";

    return rStream;
}

std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig::ImplMatcherSet& rSet)
{
    rStream << "{";
    for (auto i = rSet.cbegin(); i != rSet.cend(); ++i)
    {
        if (i != rSet.cbegin())
            rStream << ",";
        rStream << *i;
    }
    rStream << "}";
    return rStream;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/**
 * C S O U N D   V S T
 *
 * A VST plugin version of Csound, with Python scripting.
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "CppSound.hpp"

#include <cstdio>
#include <cstring>

CppSound::CppSound() : Csound(),
                       go(false),
                       isCompiled(false),
                       isPerforming(false),
                       spoutSize(0)
{
  SetHostData((CSOUND *)0);
}

CppSound::~CppSound()
{
}

int CppSound::compile(int argc, char **argv_)
{
  Message("BEGAN CppSound::compile(%d, %p)...\n", argc, argv_);
  go = false;
  int returnValue = Compile(argc, argv_);
  spoutSize = GetKsmps() * GetNchnls() * sizeof(MYFLT);
  if(returnValue)
    {
      isCompiled = false;
    }
  else
    {
      const char *outfilename = GetOutputFileName();
      if (outfilename) {
        renderedSoundfile = outfilename;
      }
      isCompiled = true;
      go = true;
    }
  Message("ENDED CppSound::compile.\n");
  return returnValue;
}

int CppSound::compile()
{
  Message("BEGAN CppSound::compile()...\n");
  if(getCommand().length() <= 0)
    {
      Message("No Csound command.\n");
      return 0;
    }
  scatterArgs(getCommand(), const_cast< std::vector<std::string> & >(args), const_cast< std::vector<char *> &>(argv));
  int returnValue = compile(args.size(), &argv.front());
  Message("ENDED CppSound::compile.\n");
  return returnValue;
}

int CppSound::perform(int argc, char **argv_)
{
  double beganAt = double(clock()) / double(CLOCKS_PER_SEC);
  isCompiled = false;
  go = false;
  Message("BEGAN CppSound::perform(%d, %p)...\n", argc, argv_);
  if(argc <= 0)
    {
      Message("ENDED CppSound::perform without compiling or performing.\n");
      return 0;
    }
  int result = compile(argc, argv_);
  if(result == -1)
    {
      return result;
    }
  for(result = 0; (result == 0) && go; )
    {
      result = PerformKsmps();
    }
  cleanup();
  double endedAt = double(clock()) / double(CLOCKS_PER_SEC);
  double elapsed = endedAt - beganAt;
  Message("Elapsed time = %f seconds.\n", elapsed);
  Message("ENDED CppSound::perform.\n");
  isCompiled = false;
  isPerforming = false;
  return 1;
}

int CppSound::perform()
{
  int returnValue = 0;
  std::string command = getCommand();
  if(command.find("-") == 0)
    {
      const char *argv_[] = {"csound", getFilename().c_str(), 0};
      returnValue = perform(2, (char **)argv_);
    }
  else
    {
      scatterArgs(command, const_cast< std::vector<std::string> & >(args), const_cast< std::vector<char *> &>(argv));
      returnValue = perform(args.size(), &argv.front());
    }
  return returnValue;
}

void CppSound::stop()
{
  Message("RECEIVED CppSound::stop...\n");
  isCompiled = false;
  isPerforming = false;
  go = false;
}

CSOUND *CppSound::getCsound()
{
  return csound;
}

int CppSound::performKsmps(bool absolute)
{
  if(absolute){
    return PerformKsmpsAbsolute();
  }
  else {
    return PerformKsmps();
  }
}

void CppSound::cleanup()
{
  Cleanup();
  Reset();
}

size_t CppSound::getSpoutSize() const
{
  return spoutSize;
}

std::string CppSound::getOutputSoundfileName() const
{
  return renderedSoundfile;
}

void CppSound::inputMessage(const char *istatement)
{
  InputMessage(istatement);
}

void CppSound::write(const char *text)
{
  Message("%s", text);
}

long CppSound::getThis()
{
  return (long) this;
}

CsoundFile *CppSound::getCsoundFile()
{
  return dynamic_cast<CsoundFile *>(this);
}

bool CppSound::getIsCompiled() const
{
  return isCompiled;
}

void CppSound::setIsPerforming(bool isPerforming)
{
  this->isPerforming = isPerforming;
}

bool CppSound::getIsPerforming() const
{
  return isPerforming;
}

bool CppSound::getIsGo()
{
  if(csound) {
    if(GetSpin() && GetSpout()) {
      return go;
    }
  }
  return false;
}

extern "C"
{
  int PyRun_SimpleString(const char *string);
}

static void pythonMessageCallback(CSOUND *csound, int attr, const char *format, va_list valist)
{
  static char buffer[0x1000];
  static char buffer1[0x1000];
  vsprintf(buffer, format, valist);
  static std::string actualBuffer;
  static std::string lineBuffer;
  actualBuffer.append(buffer);
  size_t position = 0;
  while((position = actualBuffer.find("\n")) != std::string::npos)
    {
      lineBuffer = actualBuffer.substr(0, position);
      actualBuffer.erase(0, position + 1);
#ifndef MSVC
      actualBuffer.clear();
#endif
      sprintf(buffer1, "print '''%s'''", lineBuffer.c_str());
      PyRun_SimpleString(buffer1);
    }
}

void CppSound::setPythonMessageCallback()
{
  SetMessageCallback(pythonMessageCallback);
}

<commit_msg>Implement CppSound::stop with Csound::Stop.<commit_after>/**
 * C S O U N D   V S T
 *
 * A VST plugin version of Csound, with Python scripting.
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "CppSound.hpp"

#include <cstdio>
#include <cstring>

CppSound::CppSound() : Csound(),
                       go(false),
                       isCompiled(false),
                       isPerforming(false),
                       spoutSize(0)
{
  SetHostData((CSOUND *)0);
}

CppSound::~CppSound()
{
}

int CppSound::compile(int argc, char **argv_)
{
  Message("BEGAN CppSound::compile(%d, %p)...\n", argc, argv_);
  go = false;
  int returnValue = Compile(argc, argv_);
  spoutSize = GetKsmps() * GetNchnls() * sizeof(MYFLT);
  if(returnValue)
    {
      isCompiled = false;
    }
  else
    {
      const char *outfilename = GetOutputFileName();
      if (outfilename) {
        renderedSoundfile = outfilename;
      }
      isCompiled = true;
      go = true;
    }
  Message("ENDED CppSound::compile.\n");
  return returnValue;
}

int CppSound::compile()
{
  Message("BEGAN CppSound::compile()...\n");
  if(getCommand().length() <= 0)
    {
      Message("No Csound command.\n");
      return 0;
    }
  scatterArgs(getCommand(), const_cast< std::vector<std::string> & >(args), const_cast< std::vector<char *> &>(argv));
  int returnValue = compile(args.size(), &argv.front());
  Message("ENDED CppSound::compile.\n");
  return returnValue;
}

int CppSound::perform(int argc, char **argv_)
{
  double beganAt = double(clock()) / double(CLOCKS_PER_SEC);
  isCompiled = false;
  go = false;
  Message("BEGAN CppSound::perform(%d, %p)...\n", argc, argv_);
  if(argc <= 0)
    {
      Message("ENDED CppSound::perform without compiling or performing.\n");
      return 0;
    }
  int result = compile(argc, argv_);
  if(result == -1)
    {
      return result;
    }
  for(result = 0; (result == 0) && go; )
    {
      result = PerformKsmps();
    }
  cleanup();
  double endedAt = double(clock()) / double(CLOCKS_PER_SEC);
  double elapsed = endedAt - beganAt;
  Message("Elapsed time = %f seconds.\n", elapsed);
  Message("ENDED CppSound::perform.\n");
  isCompiled = false;
  isPerforming = false;
  return 1;
}

int CppSound::perform()
{
  int returnValue = 0;
  std::string command = getCommand();
  if(command.find("-") == 0)
    {
      const char *argv_[] = {"csound", getFilename().c_str(), 0};
      returnValue = perform(2, (char **)argv_);
    }
  else
    {
      scatterArgs(command, const_cast< std::vector<std::string> & >(args), const_cast< std::vector<char *> &>(argv));
      returnValue = perform(args.size(), &argv.front());
    }
  return returnValue;
}

void CppSound::stop()
{
  Message("RECEIVED CppSound::stop...\n");
  isCompiled = false;
  isPerforming = false;
  go = false;
  Stop();
}

CSOUND *CppSound::getCsound()
{
  return csound;
}

int CppSound::performKsmps(bool absolute)
{
  if(absolute){
    return PerformKsmpsAbsolute();
  }
  else {
    return PerformKsmps();
  }
}

void CppSound::cleanup()
{
  Cleanup();
  Reset();
}

size_t CppSound::getSpoutSize() const
{
  return spoutSize;
}

std::string CppSound::getOutputSoundfileName() const
{
  return renderedSoundfile;
}

void CppSound::inputMessage(const char *istatement)
{
  InputMessage(istatement);
}

void CppSound::write(const char *text)
{
  Message("%s", text);
}

long CppSound::getThis()
{
  return (long) this;
}

CsoundFile *CppSound::getCsoundFile()
{
  return dynamic_cast<CsoundFile *>(this);
}

bool CppSound::getIsCompiled() const
{
  return isCompiled;
}

void CppSound::setIsPerforming(bool isPerforming)
{
  this->isPerforming = isPerforming;
}

bool CppSound::getIsPerforming() const
{
  return isPerforming;
}

bool CppSound::getIsGo()
{
  if(csound) {
    if(GetSpin() && GetSpout()) {
      return go;
    }
  }
  return false;
}

extern "C"
{
  int PyRun_SimpleString(const char *string);
}

static void pythonMessageCallback(CSOUND *csound, int attr, const char *format, va_list valist)
{
  static char buffer[0x1000];
  static char buffer1[0x1000];
  vsprintf(buffer, format, valist);
  static std::string actualBuffer;
  static std::string lineBuffer;
  actualBuffer.append(buffer);
  size_t position = 0;
  while((position = actualBuffer.find("\n")) != std::string::npos)
    {
      lineBuffer = actualBuffer.substr(0, position);
      actualBuffer.erase(0, position + 1);
#ifndef MSVC
      actualBuffer.clear();
#endif
      sprintf(buffer1, "print '''%s'''", lineBuffer.c_str());
      PyRun_SimpleString(buffer1);
    }
}

void CppSound::setPythonMessageCallback()
{
  SetMessageCallback(pythonMessageCallback);
}

<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/mlir/tensorflow/transforms/bridge.h"

#include <memory>

#include "mlir/Pass/PassManager.h"  // TF:llvm-project
#include "mlir/Transforms/Passes.h"  // TF:llvm-project
#include "tensorflow/compiler/mlir/tensorflow/transforms/passes.h"
#include "tensorflow/compiler/mlir/tensorflow/utils/bridge_logger.h"
#include "tensorflow/compiler/mlir/tensorflow/utils/error_util.h"

namespace mlir {
namespace TFTPU {

void CreateTPUBridge(OpPassManager &pm) {
  // Run island coarsening before shape inference to allow more exact shape
  // inference using constant folding within islands.
  OpPassManager &func_pm = pm.nest<FuncOp>();
  func_pm.addPass(tf_executor::CreateTFExecutorIslandCoarseningPass());
  // Run shape inference so that tf_executor/tf_device ops created later will
  // likely to inherit more concrete types.
  pm.addPass(TF::CreateTFShapeInferencePass());
  func_pm.addPass(CreateTPUClusterFormationPass());
  func_pm.addPass(createCanonicalizerPass());
  // Place DecomposeResourceOpsPass before TFExecutorConstantSinking pass
  // because DecomposeResourceOpsPass uses pattern rewriter which hoists
  // changed constants out of tf_device.Launch.
  func_pm.addPass(TFDevice::CreateDecomposeResourceOpsPass());

  // Run another shape inference pass because resource ecomposition might have
  // created new partial types.
  pm.addPass(TF::CreateTFShapeInferencePass());
  OpPassManager &func_pm2 = pm.nest<FuncOp>();
  func_pm2.addPass(tf_executor::CreateTFExecutorConstantSinkingPass());
  func_pm2.addPass(TFDevice::CreateResourceOpLiftingPass());

  pm.addPass(TF::CreateResourceDeviceInferencePass());
  pm.addPass(TFDevice::CreateClusterOutliningPass());
  pm.addPass(CreateTPUDynamicPaddingMapperPass());
  pm.addPass(TFDevice::CreateAnnotateParameterReplicationPass());
  pm.addPass(CreateTPURewritePass());
  pm.addNestedPass<FuncOp>(TFDevice::CreateReplicateInvariantOpHoistingPass());
  pm.addNestedPass<FuncOp>(CreateTPUMergeVariablesWithExecutePass());
  // TODO(b/147020076): Enable this pass.
  // pm.addPass(CreateTPUVariableReformattingPass());
  pm.addNestedPass<FuncOp>(CreateFunctionalToExecutorDialectConversionPass());
  pm.addNestedPass<FuncOp>(CreateBreakUpIslandsPass());
  pm.addNestedPass<FuncOp>(TFDevice::CreateReplicateToIslandPass());
  pm.addNestedPass<FuncOp>(CreateBreakUpIslandsPass());
}

tensorflow::Status TPUBridge(ModuleOp module, bool enable_logging) {
  PassManager bridge(module.getContext());

  // Add logger to bridge passmanager.
  if (enable_logging)
    bridge.enableIRPrinting(std::make_unique<tensorflow::BridgeLoggerConfig>());

  // Populate a passmanager with the list of passes that implement the bridge.
  CreateTPUBridge(bridge);

  // Run the bridge on the module, in case of failure, the `diag_handler`
  // converts MLIR errors emitted to the MLIRContext into a tensorflow::Status.
  mlir::StatusScopedDiagnosticHandler diag_handler(module.getContext());
  LogicalResult result = bridge.run(module);
  (void)result;
  return diag_handler.ConsumeStatus();
}

}  // namespace TFTPU

namespace TF {

tensorflow::Status RunBridgeWithStandardPipeline(ModuleOp module,
                                                 bool enable_logging,
                                                 bool enable_inliner) {
  PassManager bridge(module.getContext());

  // Add logger to bridge passmanager.
  if (enable_logging)
    bridge.enableIRPrinting(std::make_unique<tensorflow::BridgeLoggerConfig>());

  StandardPipelineOptions pipeline_options;
  pipeline_options.enable_inliner.setValue(enable_inliner);
  CreateTFStandardPipeline(bridge, pipeline_options);
  mlir::StatusScopedDiagnosticHandler diag_handler(module.getContext());
  LogicalResult result = bridge.run(module);
  (void)result;
  return diag_handler.ConsumeStatus();
}

}  // namespace TF
}  // namespace mlir
<commit_msg>Fix pass pipeline<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/mlir/tensorflow/transforms/bridge.h"

#include <memory>

#include "mlir/Pass/PassManager.h"  // TF:llvm-project
#include "mlir/Transforms/Passes.h"  // TF:llvm-project
#include "tensorflow/compiler/mlir/tensorflow/transforms/passes.h"
#include "tensorflow/compiler/mlir/tensorflow/utils/bridge_logger.h"
#include "tensorflow/compiler/mlir/tensorflow/utils/error_util.h"

namespace mlir {
namespace TFTPU {

void CreateTPUBridge(OpPassManager &pm) {
  // Run island coarsening before shape inference to allow more exact shape
  // inference using constant folding within islands.
  pm.nest<FuncOp>().addPass(
      tf_executor::CreateTFExecutorIslandCoarseningPass());
  // Run shape inference so that tf_executor/tf_device ops created later will
  // likely to inherit more concrete types.
  pm.addPass(TF::CreateTFShapeInferencePass());
  OpPassManager &func_pm = pm.nest<FuncOp>();
  func_pm.addPass(CreateTPUClusterFormationPass());
  func_pm.addPass(createCanonicalizerPass());
  // Place DecomposeResourceOpsPass before TFExecutorConstantSinking pass
  // because DecomposeResourceOpsPass uses pattern rewriter which hoists
  // changed constants out of tf_device.Launch.
  func_pm.addPass(TFDevice::CreateDecomposeResourceOpsPass());

  // Run another shape inference pass because resource ecomposition might have
  // created new partial types.
  pm.addPass(TF::CreateTFShapeInferencePass());
  OpPassManager &func_pm2 = pm.nest<FuncOp>();
  func_pm2.addPass(tf_executor::CreateTFExecutorConstantSinkingPass());
  func_pm2.addPass(TFDevice::CreateResourceOpLiftingPass());

  pm.addPass(TF::CreateResourceDeviceInferencePass());
  pm.addPass(TFDevice::CreateClusterOutliningPass());
  pm.addPass(CreateTPUDynamicPaddingMapperPass());
  pm.addPass(TFDevice::CreateAnnotateParameterReplicationPass());
  pm.addPass(CreateTPURewritePass());
  pm.addNestedPass<FuncOp>(TFDevice::CreateReplicateInvariantOpHoistingPass());
  pm.addNestedPass<FuncOp>(CreateTPUMergeVariablesWithExecutePass());
  // TODO(b/147020076): Enable this pass.
  // pm.addPass(CreateTPUVariableReformattingPass());
  pm.addNestedPass<FuncOp>(CreateFunctionalToExecutorDialectConversionPass());
  pm.addNestedPass<FuncOp>(CreateBreakUpIslandsPass());
  pm.addNestedPass<FuncOp>(TFDevice::CreateReplicateToIslandPass());
  pm.addNestedPass<FuncOp>(CreateBreakUpIslandsPass());
}

tensorflow::Status TPUBridge(ModuleOp module, bool enable_logging) {
  PassManager bridge(module.getContext());

  // Add logger to bridge passmanager.
  if (enable_logging)
    bridge.enableIRPrinting(std::make_unique<tensorflow::BridgeLoggerConfig>());

  // Populate a passmanager with the list of passes that implement the bridge.
  CreateTPUBridge(bridge);

  // Run the bridge on the module, in case of failure, the `diag_handler`
  // converts MLIR errors emitted to the MLIRContext into a tensorflow::Status.
  mlir::StatusScopedDiagnosticHandler diag_handler(module.getContext());
  LogicalResult result = bridge.run(module);
  (void)result;
  return diag_handler.ConsumeStatus();
}

}  // namespace TFTPU

namespace TF {

tensorflow::Status RunBridgeWithStandardPipeline(ModuleOp module,
                                                 bool enable_logging,
                                                 bool enable_inliner) {
  PassManager bridge(module.getContext());

  // Add logger to bridge passmanager.
  if (enable_logging)
    bridge.enableIRPrinting(std::make_unique<tensorflow::BridgeLoggerConfig>());

  StandardPipelineOptions pipeline_options;
  pipeline_options.enable_inliner.setValue(enable_inliner);
  CreateTFStandardPipeline(bridge, pipeline_options);
  mlir::StatusScopedDiagnosticHandler diag_handler(module.getContext());
  LogicalResult result = bridge.run(module);
  (void)result;
  return diag_handler.ConsumeStatus();
}

}  // namespace TF
}  // namespace mlir
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>

#include "qgraphicsvideoitem.h"

#include "qmediaobject.h"
#include "qmediaservice.h"
#include "qpaintervideosurface_p.h"
#include "qvideooutputcontrol.h"
#include "qvideorenderercontrol.h"

#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qvideosurfaceformat.h>

#include <QtGui/qapplication.h>
#include <QtGui/qgraphicsscene.h>
#include <QtGui/qgraphicsview.h>

class tst_QGraphicsVideoItem : public QObject
{
    Q_OBJECT
private slots:
    void nullObject();
    void nullService();
    void nullOutputControl();
    void noOutputs();
    void serviceDestroyed();

    void show();

    void boundingRect_data();
    void boundingRect();

    void paint();
};

Q_DECLARE_METATYPE(const uchar *)

class QtTestOutputControl : public QVideoOutputControl
{
public:
    QtTestOutputControl() : m_output(NoOutput) {}

    QList<Output> availableOutputs() const { return m_outputs; }
    void setAvailableOutputs(const QList<Output> outputs) { m_outputs = outputs; }

    Output output() const { return m_output; }
    virtual void setOutput(Output output) { m_output = output; }

private:
    Output m_output;
    QList<Output> m_outputs;
};

class QtTestRendererControl : public QVideoRendererControl
{
public:
    QtTestRendererControl()
        : m_surface(0)
    {
    }

    QAbstractVideoSurface *surface() const { return m_surface; }
    void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; }

private:
    QAbstractVideoSurface *m_surface;
};

class QtTestVideoService : public QMediaService
{
    Q_OBJECT
public:
    QtTestVideoService(
            QtTestOutputControl *output,
            QtTestRendererControl *renderer)
        : QMediaService(0)
        , outputControl(output)
        , rendererControl(renderer)
    {
    }

    ~QtTestVideoService()
    {
        delete outputControl;
        delete rendererControl;
    }

    QMediaControl *control(const char *name) const
    {
        if (qstrcmp(name, QVideoOutputControl_iid) == 0)
            return outputControl;
        else if (qstrcmp(name, QVideoRendererControl_iid) == 0)
            return rendererControl;
        else
            return 0;
    }

    QtTestOutputControl *outputControl;
    QtTestRendererControl *rendererControl;
};

class QtTestVideoObject : public QMediaObject
{
    Q_OBJECT
public:
    QtTestVideoObject(QtTestRendererControl *renderer):
        QMediaObject(0, new QtTestVideoService(new QtTestOutputControl, renderer))
    {
        testService = qobject_cast<QtTestVideoService*>(service());
        QList<QVideoOutputControl::Output> outputs;

        if (renderer)
            outputs.append(QVideoOutputControl::RendererOutput);

        testService->outputControl->setAvailableOutputs(outputs);
    }

    QtTestVideoObject(QtTestVideoService *service):
        QMediaObject(0, service),
        testService(service)
    {
    }

    ~QtTestVideoObject()
    {
        delete testService;
    }

    QtTestVideoService *testService;
};

class QtTestGraphicsVideoItem : public QGraphicsVideoItem
{
public:
    QtTestGraphicsVideoItem(QMediaObject *object, QGraphicsItem *parent = 0)
        : QGraphicsVideoItem(object, parent)
        , m_paintCount(0)
    {
    }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        ++m_paintCount;

        QTestEventLoop::instance().exitLoop();

        QGraphicsVideoItem::paint(painter, option, widget);
    }

    bool waitForPaint(int secs)
    {
        const int paintCount = m_paintCount;

        QTestEventLoop::instance().enterLoop(secs);

        return m_paintCount != paintCount;
    }

    int paintCount() const
    {
        return m_paintCount;
    }

private:
    int m_paintCount;
};

void tst_QGraphicsVideoItem::nullObject()
{
    QGraphicsVideoItem item(0);

    QVERIFY(item.boundingRect().isEmpty());
}

void tst_QGraphicsVideoItem::nullService()
{
    QtTestVideoService *service = 0;

    QtTestVideoObject object(service);

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    item->show();

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();
}

void tst_QGraphicsVideoItem::nullOutputControl()
{
    QtTestVideoObject object(new QtTestVideoService(0, 0));

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    item->show();

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();
}

void tst_QGraphicsVideoItem::noOutputs()
{
    QtTestRendererControl *control = 0;
    QtTestVideoObject object(control);

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);
    item->show();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();
}

void tst_QGraphicsVideoItem::serviceDestroyed()
{
    QtTestVideoObject *object = new QtTestVideoObject(new QtTestRendererControl);

    QGraphicsVideoItem item(object);

    delete object;

    QVERIFY(item.boundingRect().isEmpty());
}

void tst_QGraphicsVideoItem::show()
{
    QtTestVideoObject object(new QtTestRendererControl);
    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    // Graphics items are visible by default
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput);
    QVERIFY(object.testService->rendererControl->surface() != 0);

    item->hide();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);

    item->show();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput);
    QVERIFY(object.testService->rendererControl->surface() != 0);

    QVERIFY(item->boundingRect().isEmpty());

    QVideoSurfaceFormat format(QSize(320,240),QVideoFrame::Format_RGB32);
    QVERIFY(object.testService->rendererControl->surface()->start(format));

    QVERIFY(!item->boundingRect().isEmpty());

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    QVERIFY(item->paintCount() || item->waitForPaint(1));
}

void tst_QGraphicsVideoItem::boundingRect_data()
{
    QTest::addColumn<QSize>("frameSize");
    QTest::addColumn<QRect>("viewport");
    QTest::addColumn<QSize>("pixelAspectRatio");
    QTest::addColumn<QRectF>("expectedRect");

    QTest::newRow("640x480")
            << QSize(640, 480)
            << QRect(0, 0, 640, 480)
            << QSize(1, 1)
            << QRectF(-319, -239, 640, 480);

    QTest::newRow("800x600, (80,60, 640x480) viewport")
            << QSize(800, 600)
            << QRect(80, 60, 640, 480)
            << QSize(1, 1)
            << QRectF(-319,-239, 640, 480);

    QTest::newRow("800x600, (80,60, 640x480) viewport, 4:3")
            << QSize(800, 600)
            << QRect(80, 60, 640, 480)
            << QSize(4, 3)
            << QRectF(-426, -239, 853, 480);

}

void tst_QGraphicsVideoItem::boundingRect()
{
    QFETCH(QSize, frameSize);
    QFETCH(QRect, viewport);
    QFETCH(QSize, pixelAspectRatio);
    QFETCH(QRectF, expectedRect);

    QtTestVideoObject object(new QtTestRendererControl);
    QGraphicsVideoItem item(&object);

    QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32);
    format.setViewport(viewport);
    format.setPixelAspectRatio(pixelAspectRatio);

    QVERIFY(object.testService->rendererControl->surface()->start(format));

    QCOMPARE(item.boundingRect(), expectedRect);
}

static const uchar rgb32ImageData[] =
{
    0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
    0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00
};

void tst_QGraphicsVideoItem::paint()
{
    QtTestVideoObject object(new QtTestRendererControl);
    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    QPainterVideoSurface *surface = qobject_cast<QPainterVideoSurface *>(
            object.testService->rendererControl->surface());

    QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32);

    QVERIFY(surface->start(format));
    QCOMPARE(surface->isActive(), true);
    QCOMPARE(surface->isReady(), true);

    QVERIFY(item->waitForPaint(1));

    QCOMPARE(surface->isActive(), true);
    QCOMPARE(surface->isReady(), true);

    QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32);

    frame.map(QAbstractVideoBuffer::WriteOnly);
    memcpy(frame.bits(), rgb32ImageData, frame.mappedBytes());
    frame.unmap();

    QVERIFY(surface->present(frame));
    QCOMPARE(surface->isActive(), true);
    QCOMPARE(surface->isReady(), false);

    QVERIFY(item->waitForPaint(1));

    QCOMPARE(surface->isActive(), true);
    QCOMPARE(surface->isReady(), true);
}

QTEST_MAIN(tst_QGraphicsVideoItem)

#include "tst_qgraphicsvideoitem.moc"
<commit_msg>more missing export symbols when building unit tests<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qmultimediaglobal.h>
#include <QtTest/QtTest>

#include "qgraphicsvideoitem.h"

#include "qmediaobject.h"
#include "qmediaservice.h"
#include "qpaintervideosurface_p.h"
#include "qvideooutputcontrol.h"
#include "qvideorenderercontrol.h"

#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qvideosurfaceformat.h>

#include <QtGui/qapplication.h>
#include <QtGui/qgraphicsscene.h>
#include <QtGui/qgraphicsview.h>

class tst_QGraphicsVideoItem : public QObject
{
    Q_OBJECT
private slots:
    void nullObject();
    void nullService();
    void nullOutputControl();
    void noOutputs();
    void serviceDestroyed();

    void show();

    void boundingRect_data();
    void boundingRect();

    void paint();
};

Q_DECLARE_METATYPE(const uchar *)

class QtTestOutputControl : public QVideoOutputControl
{
public:
    QtTestOutputControl() : m_output(NoOutput) {}

    QList<Output> availableOutputs() const { return m_outputs; }
    void setAvailableOutputs(const QList<Output> outputs) { m_outputs = outputs; }

    Output output() const { return m_output; }
    virtual void setOutput(Output output) { m_output = output; }

private:
    Output m_output;
    QList<Output> m_outputs;
};

class QtTestRendererControl : public QVideoRendererControl
{
public:
    QtTestRendererControl()
        : m_surface(0)
    {
    }

    QAbstractVideoSurface *surface() const { return m_surface; }
    void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; }

private:
    QAbstractVideoSurface *m_surface;
};

class QtTestVideoService : public QMediaService
{
    Q_OBJECT
public:
    QtTestVideoService(
            QtTestOutputControl *output,
            QtTestRendererControl *renderer)
        : QMediaService(0)
        , outputControl(output)
        , rendererControl(renderer)
    {
    }

    ~QtTestVideoService()
    {
        delete outputControl;
        delete rendererControl;
    }

    QMediaControl *control(const char *name) const
    {
        if (qstrcmp(name, QVideoOutputControl_iid) == 0)
            return outputControl;
        else if (qstrcmp(name, QVideoRendererControl_iid) == 0)
            return rendererControl;
        else
            return 0;
    }

    QtTestOutputControl *outputControl;
    QtTestRendererControl *rendererControl;
};

class QtTestVideoObject : public QMediaObject
{
    Q_OBJECT
public:
    QtTestVideoObject(QtTestRendererControl *renderer):
        QMediaObject(0, new QtTestVideoService(new QtTestOutputControl, renderer))
    {
        testService = qobject_cast<QtTestVideoService*>(service());
        QList<QVideoOutputControl::Output> outputs;

        if (renderer)
            outputs.append(QVideoOutputControl::RendererOutput);

        testService->outputControl->setAvailableOutputs(outputs);
    }

    QtTestVideoObject(QtTestVideoService *service):
        QMediaObject(0, service),
        testService(service)
    {
    }

    ~QtTestVideoObject()
    {
        delete testService;
    }

    QtTestVideoService *testService;
};

class QtTestGraphicsVideoItem : public QGraphicsVideoItem
{
public:
    QtTestGraphicsVideoItem(QMediaObject *object, QGraphicsItem *parent = 0)
        : QGraphicsVideoItem(object, parent)
        , m_paintCount(0)
    {
    }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        ++m_paintCount;

        QTestEventLoop::instance().exitLoop();

        QGraphicsVideoItem::paint(painter, option, widget);
    }

    bool waitForPaint(int secs)
    {
        const int paintCount = m_paintCount;

        QTestEventLoop::instance().enterLoop(secs);

        return m_paintCount != paintCount;
    }

    int paintCount() const
    {
        return m_paintCount;
    }

private:
    int m_paintCount;
};

void tst_QGraphicsVideoItem::nullObject()
{
    QGraphicsVideoItem item(0);

    QVERIFY(item.boundingRect().isEmpty());
}

void tst_QGraphicsVideoItem::nullService()
{
    QtTestVideoService *service = 0;

    QtTestVideoObject object(service);

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    item->show();

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();
}

void tst_QGraphicsVideoItem::nullOutputControl()
{
    QtTestVideoObject object(new QtTestVideoService(0, 0));

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    item->show();

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();
}

void tst_QGraphicsVideoItem::noOutputs()
{
    QtTestRendererControl *control = 0;
    QtTestVideoObject object(control);

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);
    item->show();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();
}

void tst_QGraphicsVideoItem::serviceDestroyed()
{
    QtTestVideoObject *object = new QtTestVideoObject(new QtTestRendererControl);

    QGraphicsVideoItem item(object);

    delete object;

    QVERIFY(item.boundingRect().isEmpty());
}

void tst_QGraphicsVideoItem::show()
{
    QtTestVideoObject object(new QtTestRendererControl);
    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    // Graphics items are visible by default
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput);
    QVERIFY(object.testService->rendererControl->surface() != 0);

    item->hide();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);

    item->show();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput);
    QVERIFY(object.testService->rendererControl->surface() != 0);

    QVERIFY(item->boundingRect().isEmpty());

    QVideoSurfaceFormat format(QSize(320,240),QVideoFrame::Format_RGB32);
    QVERIFY(object.testService->rendererControl->surface()->start(format));

    QVERIFY(!item->boundingRect().isEmpty());

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    QVERIFY(item->paintCount() || item->waitForPaint(1));
}

void tst_QGraphicsVideoItem::boundingRect_data()
{
    QTest::addColumn<QSize>("frameSize");
    QTest::addColumn<QRect>("viewport");
    QTest::addColumn<QSize>("pixelAspectRatio");
    QTest::addColumn<QRectF>("expectedRect");

    QTest::newRow("640x480")
            << QSize(640, 480)
            << QRect(0, 0, 640, 480)
            << QSize(1, 1)
            << QRectF(-319, -239, 640, 480);

    QTest::newRow("800x600, (80,60, 640x480) viewport")
            << QSize(800, 600)
            << QRect(80, 60, 640, 480)
            << QSize(1, 1)
            << QRectF(-319,-239, 640, 480);

    QTest::newRow("800x600, (80,60, 640x480) viewport, 4:3")
            << QSize(800, 600)
            << QRect(80, 60, 640, 480)
            << QSize(4, 3)
            << QRectF(-426, -239, 853, 480);

}

void tst_QGraphicsVideoItem::boundingRect()
{
    QFETCH(QSize, frameSize);
    QFETCH(QRect, viewport);
    QFETCH(QSize, pixelAspectRatio);
    QFETCH(QRectF, expectedRect);

    QtTestVideoObject object(new QtTestRendererControl);
    QGraphicsVideoItem item(&object);

    QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32);
    format.setViewport(viewport);
    format.setPixelAspectRatio(pixelAspectRatio);

    QVERIFY(object.testService->rendererControl->surface()->start(format));

    QCOMPARE(item.boundingRect(), expectedRect);
}

static const uchar rgb32ImageData[] =
{
    0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
    0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00
};

void tst_QGraphicsVideoItem::paint()
{
    QtTestVideoObject object(new QtTestRendererControl);
    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    QPainterVideoSurface *surface = qobject_cast<QPainterVideoSurface *>(
            object.testService->rendererControl->surface());

    QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32);

    QVERIFY(surface->start(format));
    QCOMPARE(surface->isActive(), true);
    QCOMPARE(surface->isReady(), true);

    QVERIFY(item->waitForPaint(1));

    QCOMPARE(surface->isActive(), true);
    QCOMPARE(surface->isReady(), true);

    QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32);

    frame.map(QAbstractVideoBuffer::WriteOnly);
    memcpy(frame.bits(), rgb32ImageData, frame.mappedBytes());
    frame.unmap();

    QVERIFY(surface->present(frame));
    QCOMPARE(surface->isActive(), true);
    QCOMPARE(surface->isReady(), false);

    QVERIFY(item->waitForPaint(1));

    QCOMPARE(surface->isActive(), true);
    QCOMPARE(surface->isReady(), true);
}

QTEST_MAIN(tst_QGraphicsVideoItem)

#include "tst_qgraphicsvideoitem.moc"
<|endoftext|>