<commit_before>#include "symboltable.hpp"
#include "exception.hpp"
#include "configuration.hpp"
#include "version.h"

#include "builtin/array.hpp"
#include "builtin/encoding.hpp"
#include "builtin/exception.hpp"
#include "builtin/string.hpp"
#include "builtin/symbol.hpp"

#include <iostream>
#include <iomanip>

namespace rubinius {

  SymbolTable::Kind SymbolTable::detect_kind(const char* str, size_t size) {
    const char one = str[0];

    // A constant begins with an uppercase letter.
    if(one >= 'A' && one <= 'Z') {
      // Make sure that the rest of it is only alphanumerics
      for(size_t i = 1; i < size; i++) {
        if((isalnum(str[i]) || str[i] == '_') == false)
          return SymbolTable::Normal;
      }
      return SymbolTable::Constant;
    }

    if(one == '@') {
      // A class variable begins with @@
      if(size > 1 && str[1] == '@') {
        return SymbolTable::CVar;
      }

      // An instance variable can't start with a digit
      if(size > 1 && ISDIGIT(str[1])) {
        return SymbolTable::Normal;
      }

      // An instance variable begins with @
      return SymbolTable::IVar;
    }

    // A system variable begins with __
    if(size > 2 && one == '_' && str[1] == '_') {
      return SymbolTable::System;
    }

    // Everything else is normal
    return SymbolTable::Normal;
  }

  SymbolTable::Kind SymbolTable::kind(STATE, const Symbol* sym) const {
    return kinds[sym->index()];
  }

  size_t SymbolTable::add(std::string str, int enc) {
    bytes_used_ += (str.size() + sizeof(str));

    strings.push_back(str);
    encodings.push_back(enc);
    kinds.push_back(detect_kind(str.data(), str.size()));
    return strings.size() - 1;
  }

  Symbol* SymbolTable::lookup(STATE, const char* str, size_t length) {
    if(length == 0 && LANGUAGE_18_ENABLED) {
      Exception::argument_error(state, "Cannot create a symbol from an empty string");
      return NULL;
    }

    return lookup(str, length, Encoding::eAscii, state->hash_seed());
  }

  Symbol* SymbolTable::lookup(STATE, const char* str, size_t length, int enc) {
    if(length == 0 && LANGUAGE_18_ENABLED) {
      Exception::argument_error(state, "Cannot create a symbol from an empty string");
      return NULL;
    }

    return lookup(str, length, enc, state->hash_seed());
  }

  struct SpecialOperator {
    const char* name;
    const char* symbol;
  };

  // These are a set of special operators that MRI
  // changes the symbol value of.
  static SpecialOperator SpecialOperators[] = {
    {"+(binary)", "+"},
    {"-(binary)", "-"},
    {"+(unary)", "+@"},
    {"-(unary)", "-@"},
    {"!(unary)", "!"},
    {"~(unary)", "~"},
    {"!@", "!"},
    {"~@", "~"}
  };

  const static int cNumSpecialOperators = 8;

  static const char* find_special(const char* check, size_t length) {
    for(int i = 0; i < cNumSpecialOperators; i++) {
      SpecialOperator* op = &SpecialOperators[i];
      if(*op->name == *check && strncmp(op->name, check, length) == 0) {
        return op->symbol;
      }
    }

    return 0;
  }

  Symbol* SymbolTable::lookup(SharedState* shared, const std::string& str) {
    return lookup(str.data(), str.size(), Encoding::eAscii, shared->hash_seed);
  }

  Symbol* SymbolTable::lookup(STATE, const std::string& str) {
    return lookup(str.data(), str.size(), Encoding::eAscii, state->hash_seed());
  }

  Symbol* SymbolTable::lookup(const char* str, size_t length, int enc, uint32_t seed) {
    size_t sym;

    if(const char* op = find_special(str, length)) {
      str = op;
      length = strlen(str);
    }

    hashval hash = String::hash_str((unsigned char*)str, length, seed);

    // Symbols can be looked up by multiple threads at the same time.
    // This is fast operation, so we protect this with a spinlock.
    {
      utilities::thread::SpinLock::LockGuard guard(lock_);
      SymbolMap::iterator entry = symbols.find(hash);
      if(entry == symbols.end()) {
        sym = add(std::string(str, length), enc);
        SymbolIds v(1, sym);
        symbols[hash] = v;
      } else {
        SymbolIds& v = entry->second;
        for(SymbolIds::const_iterator i = v.begin(); i != v.end(); ++i) {
          std::string& s = strings[*i];
          int e = encodings[*i];

          if(!strncmp(s.data(), str, length) && enc == e) return Symbol::from_index(*i);
        }
        sym = add(std::string(str, length), enc);
        v.push_back(sym);
      }
    }

    return Symbol::from_index(sym);
  }

  Symbol* SymbolTable::lookup(STATE, String* str) {
    if(str->nil_p()) {
      Exception::argument_error(state, "Cannot look up Symbol from nil");
      return NULL;
    }

    // Since we also explicitly use the size, we can safely
    // use byte_address() here.
    const char* bytes = (const char*) str->byte_address();
    size_t size = str->byte_size();

    int enc = str->encoding(state)->index();

    if(LANGUAGE_18_ENABLED) {
      for(size_t i = 0; i < size; i++) {
        if(bytes[i] == 0) {
          Exception::argument_error(state,
              "cannot create a symbol from a string containing `\\0'");
          return NULL;
        }
      }
      enc = Encoding::eAscii;
    } else {
      if(CBOOL(str->ascii_only_p(state))) {
        enc = Encoding::eAscii;
      }
    }

    return lookup(bytes, size, enc, state->hash_seed());
  }

  String* SymbolTable::lookup_string(STATE, const Symbol* sym) {
    if(sym->nil_p()) {
      Exception::argument_error(state, "Cannot look up Symbol from nil");
      return NULL;
    }

    size_t sym_index = sym->index();
    if(sym_index >= strings.size()) {
      return NULL;
    }
    std::string& str = strings[sym_index];
    int enc = encodings[sym_index];
    String* s = String::create(state, str.data(), str.size());
    s->encoding(state, Encoding::from_index(state, enc));
    return s;
  }

  std::string& SymbolTable::lookup_cppstring(const Symbol* sym) {
    return strings[sym->index()];
  }

  int SymbolTable::lookup_encoding(const Symbol* sym) {
    return encodings[sym->index()];
  }

  std::string SymbolTable::lookup_debug_string(const Symbol* sym) {
    std::string str = lookup_cppstring(sym);
    std::ostringstream os;
    unsigned char* cstr = (unsigned char*) str.data();
    size_t size = str.size();
    for(size_t i = 0; i < size; ++i) {
      if(isprint(cstr[i]) && isascii(cstr[i])) {
        os << cstr[i];
      } else {
        os << "\\x" << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)cstr[i];
      }
    }
    return os.str();
  }

  size_t SymbolTable::size() const {
    return strings.size();
  }

  size_t SymbolTable::byte_size() const {
    size_t total = 0;

    for(SymbolStrings::const_iterator i = strings.begin();
        i != strings.end();
        ++i) {
      total += i->size();
      total += sizeof(std::string);
    }

    return total;
  }

  Array* SymbolTable::all_as_array(STATE) {
    size_t idx = 0;
    Array* ary = Array::create(state, this->size());

    for(SymbolMap::iterator s = symbols.begin(); s != symbols.end(); ++s) {
      for(SymbolIds::iterator i = s->second.begin(); i != s->second.end(); ++i) {
        ary->set(state, idx++, Symbol::from_index(state, *i));
      }
    }

    return ary;
  }
}
<commit_msg>Throw exception in 1.8 mode for empty string<commit_after>#include "symboltable.hpp"
#include "exception.hpp"
#include "configuration.hpp"
#include "version.h"

#include "builtin/array.hpp"
#include "builtin/encoding.hpp"
#include "builtin/exception.hpp"
#include "builtin/string.hpp"
#include "builtin/symbol.hpp"

#include <iostream>
#include <iomanip>

namespace rubinius {

  SymbolTable::Kind SymbolTable::detect_kind(const char* str, size_t size) {
    const char one = str[0];

    // A constant begins with an uppercase letter.
    if(one >= 'A' && one <= 'Z') {
      // Make sure that the rest of it is only alphanumerics
      for(size_t i = 1; i < size; i++) {
        if((isalnum(str[i]) || str[i] == '_') == false)
          return SymbolTable::Normal;
      }
      return SymbolTable::Constant;
    }

    if(one == '@') {
      // A class variable begins with @@
      if(size > 1 && str[1] == '@') {
        return SymbolTable::CVar;
      }

      // An instance variable can't start with a digit
      if(size > 1 && ISDIGIT(str[1])) {
        return SymbolTable::Normal;
      }

      // An instance variable begins with @
      return SymbolTable::IVar;
    }

    // A system variable begins with __
    if(size > 2 && one == '_' && str[1] == '_') {
      return SymbolTable::System;
    }

    // Everything else is normal
    return SymbolTable::Normal;
  }

  SymbolTable::Kind SymbolTable::kind(STATE, const Symbol* sym) const {
    return kinds[sym->index()];
  }

  size_t SymbolTable::add(std::string str, int enc) {
    bytes_used_ += (str.size() + sizeof(str));

    strings.push_back(str);
    encodings.push_back(enc);
    kinds.push_back(detect_kind(str.data(), str.size()));
    return strings.size() - 1;
  }

  Symbol* SymbolTable::lookup(STATE, const char* str, size_t length) {
    if(length == 0 && LANGUAGE_18_ENABLED) {
      Exception::argument_error(state, "Cannot create a symbol from an empty string");
      return NULL;
    }

    return lookup(str, length, Encoding::eAscii, state->hash_seed());
  }

  Symbol* SymbolTable::lookup(STATE, const char* str, size_t length, int enc) {
    if(length == 0 && LANGUAGE_18_ENABLED) {
      Exception::argument_error(state, "Cannot create a symbol from an empty string");
      return NULL;
    }

    return lookup(str, length, enc, state->hash_seed());
  }

  struct SpecialOperator {
    const char* name;
    const char* symbol;
  };

  // These are a set of special operators that MRI
  // changes the symbol value of.
  static SpecialOperator SpecialOperators[] = {
    {"+(binary)", "+"},
    {"-(binary)", "-"},
    {"+(unary)", "+@"},
    {"-(unary)", "-@"},
    {"!(unary)", "!"},
    {"~(unary)", "~"},
    {"!@", "!"},
    {"~@", "~"}
  };

  const static int cNumSpecialOperators = 8;

  static const char* find_special(const char* check, size_t length) {
    for(int i = 0; i < cNumSpecialOperators; i++) {
      SpecialOperator* op = &SpecialOperators[i];
      if(*op->name == *check && strncmp(op->name, check, length) == 0) {
        return op->symbol;
      }
    }

    return 0;
  }

  Symbol* SymbolTable::lookup(SharedState* shared, const std::string& str) {
    return lookup(str.data(), str.size(), Encoding::eAscii, shared->hash_seed);
  }

  Symbol* SymbolTable::lookup(STATE, const std::string& str) {
    return lookup(str.data(), str.size(), Encoding::eAscii, state->hash_seed());
  }

  Symbol* SymbolTable::lookup(const char* str, size_t length, int enc, uint32_t seed) {
    size_t sym;

    if(const char* op = find_special(str, length)) {
      str = op;
      length = strlen(str);
    }

    hashval hash = String::hash_str((unsigned char*)str, length, seed);

    // Symbols can be looked up by multiple threads at the same time.
    // This is fast operation, so we protect this with a spinlock.
    {
      utilities::thread::SpinLock::LockGuard guard(lock_);
      SymbolMap::iterator entry = symbols.find(hash);
      if(entry == symbols.end()) {
        sym = add(std::string(str, length), enc);
        SymbolIds v(1, sym);
        symbols[hash] = v;
      } else {
        SymbolIds& v = entry->second;
        for(SymbolIds::const_iterator i = v.begin(); i != v.end(); ++i) {
          std::string& s = strings[*i];
          int e = encodings[*i];

          if(!strncmp(s.data(), str, length) && enc == e) return Symbol::from_index(*i);
        }
        sym = add(std::string(str, length), enc);
        v.push_back(sym);
      }
    }

    return Symbol::from_index(sym);
  }

  Symbol* SymbolTable::lookup(STATE, String* str) {
    if(str->nil_p()) {
      Exception::argument_error(state, "Cannot look up Symbol from nil");
      return NULL;
    }

    // Since we also explicitly use the size, we can safely
    // use byte_address() here.
    const char* bytes = (const char*) str->byte_address();
    size_t size = str->byte_size();

    int enc = str->encoding(state)->index();

    if(LANGUAGE_18_ENABLED) {
      if(size == 0) {
        Exception::argument_error(state, "Cannot create a symbol from an empty string");
        return NULL;
      }

      if(strnlen(bytes, size) < size) {
        Exception::argument_error(state,
            "cannot create a symbol from a string containing `\\0'");
        return NULL;
      }
      enc = Encoding::eAscii;
    } else {
      if(CBOOL(str->ascii_only_p(state))) {
        enc = Encoding::eAscii;
      }
    }

    return lookup(bytes, size, enc, state->hash_seed());
  }

  String* SymbolTable::lookup_string(STATE, const Symbol* sym) {
    if(sym->nil_p()) {
      Exception::argument_error(state, "Cannot look up Symbol from nil");
      return NULL;
    }

    size_t sym_index = sym->index();
    if(sym_index >= strings.size()) {
      return NULL;
    }
    std::string& str = strings[sym_index];
    int enc = encodings[sym_index];
    String* s = String::create(state, str.data(), str.size());
    s->encoding(state, Encoding::from_index(state, enc));
    return s;
  }

  std::string& SymbolTable::lookup_cppstring(const Symbol* sym) {
    return strings[sym->index()];
  }

  int SymbolTable::lookup_encoding(const Symbol* sym) {
    return encodings[sym->index()];
  }

  std::string SymbolTable::lookup_debug_string(const Symbol* sym) {
    std::string str = lookup_cppstring(sym);
    std::ostringstream os;
    unsigned char* cstr = (unsigned char*) str.data();
    size_t size = str.size();
    for(size_t i = 0; i < size; ++i) {
      if(isprint(cstr[i]) && isascii(cstr[i])) {
        os << cstr[i];
      } else {
        os << "\\x" << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)cstr[i];
      }
    }
    return os.str();
  }

  size_t SymbolTable::size() const {
    return strings.size();
  }

  size_t SymbolTable::byte_size() const {
    size_t total = 0;

    for(SymbolStrings::const_iterator i = strings.begin();
        i != strings.end();
        ++i) {
      total += i->size();
      total += sizeof(std::string);
    }

    return total;
  }

  Array* SymbolTable::all_as_array(STATE) {
    size_t idx = 0;
    Array* ary = Array::create(state, this->size());

    for(SymbolMap::iterator s = symbols.begin(); s != symbols.end(); ++s) {
      for(SymbolIds::iterator i = s->second.begin(); i != s->second.end(); ++i) {
        ary->set(state, idx++, Symbol::from_index(state, *i));
      }
    }

    return ary;
  }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $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 "qdeclarativerepeater_p.h"
#include "qdeclarativerepeater_p_p.h"

#include "qdeclarativevisualitemmodel_p.h"

#include <qdeclarativelistaccessor_p.h>

#include <qlistmodelinterface_p.h>

QT_BEGIN_NAMESPACE
QDeclarativeRepeaterPrivate::QDeclarativeRepeaterPrivate()
: model(0), ownModel(false)
{
}

QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate()
{
    if (ownModel)
        delete model;
}

/*!
    \qmlclass Repeater QDeclarativeRepeater
  \since 4.7
    \inherits Item

    \brief The Repeater item allows you to repeat a component based on a model.

    The Repeater item is used when you want to create a large number of
    similar items.  For each entry in the model, an item is instantiated
    in a context seeded with data from the model.  If the repeater will
    be instantiating a large number of instances, it may be more efficient to
    use one of Qt Declarative's \l {xmlViews}{view items}.

    The model may be either an object list, a string list, a number or a Qt model.
    In each case, the data element and the index is exposed to each instantiated
    component.

    The index is always exposed as an accessible \c index property.
    In the case of an object or string list, the data element (of type string
    or object) is available as the \c modelData property.  In the case of a Qt model,
    all roles are available as named properties just like in the view classes. The
    following example shows how to use the index property inside the instantiated
    items.

    \snippet doc/src/snippets/declarative/repeater-index.qml 0

    \image repeater-index.png

    Items instantiated by the Repeater are inserted, in order, as
    children of the Repeater's parent.  The insertion starts immediately after
    the repeater's position in its parent stacking list.  This is to allow
    you to use a Repeater inside a layout.  The following QML example shows how
    the instantiated items would visually appear stacked between the red and
    blue rectangles.

    \snippet doc/src/snippets/declarative/repeater.qml 0

    \image repeater.png

    The repeater instance continues to own all items it instantiates, even
    if they are otherwise manipulated.  It is illegal to manually remove an item
    created by the Repeater.
 */

/*!
    \internal
    \class QDeclarativeRepeater
    \qmlclass Repeater

    XXX Repeater is very conservative in how it instatiates/deletes items.  Also
    new model entries will not be created and old ones will not be removed.
 */

/*!
    Create a new QDeclarativeRepeater instance.
 */
QDeclarativeRepeater::QDeclarativeRepeater(QDeclarativeItem *parent)
  : QDeclarativeItem(*(new QDeclarativeRepeaterPrivate), parent)
{
}

/*!
    Destroy the repeater instance.  All items it instantiated are also
    destroyed.
 */
QDeclarativeRepeater::~QDeclarativeRepeater()
{
}

/*!
    \qmlproperty any Repeater::model

    The model providing data for the repeater.

    The model may be either an object list, a string list, a number or a Qt model.
    In each case, the data element and the index is exposed to each instantiated
    component.  The index is always exposed as an accessible \c index property.
    In the case of an object or string list, the data element (of type string
    or object) is available as the \c modelData property.  In the case of a Qt model,
    all roles are available as named properties just like in the view classes.

    As a special case the model can also be merely a number. In this case it will
    create that many instances of the component. They will also be assigned an index
    based on the order they are created.

    Models can also be created directly in QML, using a \l{ListModel} or \l{XmlListModel}.

    \sa {qmlmodels}{Data Models}
*/
QVariant QDeclarativeRepeater::model() const
{
    Q_D(const QDeclarativeRepeater);
    return d->dataSource;
}

void QDeclarativeRepeater::setModel(const QVariant &model)
{
    Q_D(QDeclarativeRepeater);
    if (d->dataSource == model)
        return;

    clear();
    if (d->model) {
        disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
        disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
        disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
        disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
        /*
        disconnect(d->model, SIGNAL(createdItem(int, QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
        disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
    */
    }
    d->dataSource = model;
    emit modelChanged();
    QObject *object = qvariant_cast<QObject*>(model);
    QDeclarativeVisualModel *vim = 0;
    if (object && (vim = qobject_cast<QDeclarativeVisualModel *>(object))) {
        if (d->ownModel) {
            delete d->model;
            d->ownModel = false;
        }
        d->model = vim;
    } else {
        if (!d->ownModel) {
            d->model = new QDeclarativeVisualDataModel(qmlContext(this));
            d->ownModel = true;
        }
        if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model))
            dataModel->setModel(model);
    }
    if (d->model) {
        connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
        connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
        connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
        connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
        /*
        connect(d->model, SIGNAL(createdItem(int, QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
        connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
        */
        regenerate();
        emit countChanged();
    }
}

/*!
    \qmlproperty Component Repeater::delegate
    \default

    The delegate provides a template defining each item instantiated by the repeater.
    The index is exposed as an accessible \c index property.  Properties of the
    model are also available depending upon the type of \l {qmlmodels}{Data Model}.
 */
QDeclarativeComponent *QDeclarativeRepeater::delegate() const
{
    Q_D(const QDeclarativeRepeater);
    if (d->model) {
        if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model))
            return dataModel->delegate();
    }

    return 0;
}

void QDeclarativeRepeater::setDelegate(QDeclarativeComponent *delegate)
{
    Q_D(QDeclarativeRepeater);
    if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model))
       if (delegate == dataModel->delegate())
           return;

    if (!d->ownModel) {
        d->model = new QDeclarativeVisualDataModel(qmlContext(this));
        d->ownModel = true;
    }
    if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model)) {
        dataModel->setDelegate(delegate);
        regenerate();
        emit delegateChanged();
    }
}

/*!
    \qmlproperty int Repeater::count

    This property holds the number of items in the repeater.
*/
int QDeclarativeRepeater::count() const
{
    Q_D(const QDeclarativeRepeater);
    if (d->model)
        return d->model->count();
    return 0;
}

/*!
    \internal
 */
void QDeclarativeRepeater::componentComplete()
{
    QDeclarativeItem::componentComplete();
    regenerate();
}

/*!
    \internal
 */
QVariant QDeclarativeRepeater::itemChange(GraphicsItemChange change,
                                       const QVariant &value)
{
    QVariant rv = QDeclarativeItem::itemChange(change, value);
    if (change == ItemParentHasChanged) {
        regenerate();
    }

    return rv;
}

void QDeclarativeRepeater::clear()
{
    Q_D(QDeclarativeRepeater);
    if (d->model) {
        foreach (QDeclarativeItem *item, d->deletables) {
            item->setParentItem(this);
            d->model->release(item);
        }
    }
    d->deletables.clear();
}

/*!
    \internal
 */
void QDeclarativeRepeater::regenerate()
{
    Q_D(QDeclarativeRepeater);
    if (!isComponentComplete())
        return;

    clear();

    if (!d->model || !d->model->count() || !d->model->isValid() || !parentItem() || !isComponentComplete())
        return;

    for (int ii = 0; ii < count(); ++ii) {
        QDeclarativeItem *item = d->model->item(ii);
        if (item) {
            item->setParent(parentItem());
            item->stackBefore(this);
            d->deletables << item;
        }
    }
}

void QDeclarativeRepeater::itemsInserted(int index, int count)
{
    Q_D(QDeclarativeRepeater);
    if (!isComponentComplete())
        return;
    for (int i = 0; i < count; ++i) {
        int modelIndex = index + i;
        QDeclarativeItem *item = d->model->item(modelIndex);
        if (item) {
            item->setParent(parentItem());
            if (modelIndex < d->deletables.count())
                item->stackBefore(d->deletables.at(modelIndex));
            else
                item->stackBefore(this);
            d->deletables.insert(modelIndex, item);
        }
    }
}

void QDeclarativeRepeater::itemsRemoved(int index, int count)
{
    Q_D(QDeclarativeRepeater);
    if (!isComponentComplete())
        return;
    while (count--) {
        QDeclarativeItem *item = d->deletables.takeAt(index);
        if (item) {
            item->setParentItem(this);
            d->model->release(item);
        }
    }
}

void QDeclarativeRepeater::itemsMoved(int from, int to, int count)
{
    Q_D(QDeclarativeRepeater);
    if (!isComponentComplete())
        return;
    QList<QDeclarativeItem*> removed;
    int removedCount = count;
    while (removedCount--)
        removed << d->deletables.takeAt(from);
    for (int i = 0; i < count; ++i)
        d->deletables.insert(to + i, removed.at(i));
    for (int i = 0; i < d->model->count(); ++i) {
        if (i < from && i < to)
            continue;
        QDeclarativeItem *item = d->deletables.at(i);
        if (i < d->deletables.count()-1)
            item->stackBefore(d->deletables.at(i+1));
        else
            item->stackBefore(this);
    }
}

void QDeclarativeRepeater::modelReset()
{
    if (!isComponentComplete())
        return;
    regenerate();
}

QT_END_NAMESPACE
<commit_msg>Setting stacking order from top to bottom seems to work better.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $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 "qdeclarativerepeater_p.h"
#include "qdeclarativerepeater_p_p.h"

#include "qdeclarativevisualitemmodel_p.h"

#include <qdeclarativelistaccessor_p.h>

#include <qlistmodelinterface_p.h>

QT_BEGIN_NAMESPACE
QDeclarativeRepeaterPrivate::QDeclarativeRepeaterPrivate()
: model(0), ownModel(false)
{
}

QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate()
{
    if (ownModel)
        delete model;
}

/*!
    \qmlclass Repeater QDeclarativeRepeater
  \since 4.7
    \inherits Item

    \brief The Repeater item allows you to repeat a component based on a model.

    The Repeater item is used when you want to create a large number of
    similar items.  For each entry in the model, an item is instantiated
    in a context seeded with data from the model.  If the repeater will
    be instantiating a large number of instances, it may be more efficient to
    use one of Qt Declarative's \l {xmlViews}{view items}.

    The model may be either an object list, a string list, a number or a Qt model.
    In each case, the data element and the index is exposed to each instantiated
    component.

    The index is always exposed as an accessible \c index property.
    In the case of an object or string list, the data element (of type string
    or object) is available as the \c modelData property.  In the case of a Qt model,
    all roles are available as named properties just like in the view classes. The
    following example shows how to use the index property inside the instantiated
    items.

    \snippet doc/src/snippets/declarative/repeater-index.qml 0

    \image repeater-index.png

    Items instantiated by the Repeater are inserted, in order, as
    children of the Repeater's parent.  The insertion starts immediately after
    the repeater's position in its parent stacking list.  This is to allow
    you to use a Repeater inside a layout.  The following QML example shows how
    the instantiated items would visually appear stacked between the red and
    blue rectangles.

    \snippet doc/src/snippets/declarative/repeater.qml 0

    \image repeater.png

    The repeater instance continues to own all items it instantiates, even
    if they are otherwise manipulated.  It is illegal to manually remove an item
    created by the Repeater.
 */

/*!
    \internal
    \class QDeclarativeRepeater
    \qmlclass Repeater

    XXX Repeater is very conservative in how it instatiates/deletes items.  Also
    new model entries will not be created and old ones will not be removed.
 */

/*!
    Create a new QDeclarativeRepeater instance.
 */
QDeclarativeRepeater::QDeclarativeRepeater(QDeclarativeItem *parent)
  : QDeclarativeItem(*(new QDeclarativeRepeaterPrivate), parent)
{
}

/*!
    Destroy the repeater instance.  All items it instantiated are also
    destroyed.
 */
QDeclarativeRepeater::~QDeclarativeRepeater()
{
}

/*!
    \qmlproperty any Repeater::model

    The model providing data for the repeater.

    The model may be either an object list, a string list, a number or a Qt model.
    In each case, the data element and the index is exposed to each instantiated
    component.  The index is always exposed as an accessible \c index property.
    In the case of an object or string list, the data element (of type string
    or object) is available as the \c modelData property.  In the case of a Qt model,
    all roles are available as named properties just like in the view classes.

    As a special case the model can also be merely a number. In this case it will
    create that many instances of the component. They will also be assigned an index
    based on the order they are created.

    Models can also be created directly in QML, using a \l{ListModel} or \l{XmlListModel}.

    \sa {qmlmodels}{Data Models}
*/
QVariant QDeclarativeRepeater::model() const
{
    Q_D(const QDeclarativeRepeater);
    return d->dataSource;
}

void QDeclarativeRepeater::setModel(const QVariant &model)
{
    Q_D(QDeclarativeRepeater);
    if (d->dataSource == model)
        return;

    clear();
    if (d->model) {
        disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
        disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
        disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
        disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
        /*
        disconnect(d->model, SIGNAL(createdItem(int, QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
        disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
    */
    }
    d->dataSource = model;
    emit modelChanged();
    QObject *object = qvariant_cast<QObject*>(model);
    QDeclarativeVisualModel *vim = 0;
    if (object && (vim = qobject_cast<QDeclarativeVisualModel *>(object))) {
        if (d->ownModel) {
            delete d->model;
            d->ownModel = false;
        }
        d->model = vim;
    } else {
        if (!d->ownModel) {
            d->model = new QDeclarativeVisualDataModel(qmlContext(this));
            d->ownModel = true;
        }
        if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model))
            dataModel->setModel(model);
    }
    if (d->model) {
        connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
        connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
        connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
        connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
        /*
        connect(d->model, SIGNAL(createdItem(int, QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
        connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
        */
        regenerate();
        emit countChanged();
    }
}

/*!
    \qmlproperty Component Repeater::delegate
    \default

    The delegate provides a template defining each item instantiated by the repeater.
    The index is exposed as an accessible \c index property.  Properties of the
    model are also available depending upon the type of \l {qmlmodels}{Data Model}.
 */
QDeclarativeComponent *QDeclarativeRepeater::delegate() const
{
    Q_D(const QDeclarativeRepeater);
    if (d->model) {
        if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model))
            return dataModel->delegate();
    }

    return 0;
}

void QDeclarativeRepeater::setDelegate(QDeclarativeComponent *delegate)
{
    Q_D(QDeclarativeRepeater);
    if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model))
       if (delegate == dataModel->delegate())
           return;

    if (!d->ownModel) {
        d->model = new QDeclarativeVisualDataModel(qmlContext(this));
        d->ownModel = true;
    }
    if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model)) {
        dataModel->setDelegate(delegate);
        regenerate();
        emit delegateChanged();
    }
}

/*!
    \qmlproperty int Repeater::count

    This property holds the number of items in the repeater.
*/
int QDeclarativeRepeater::count() const
{
    Q_D(const QDeclarativeRepeater);
    if (d->model)
        return d->model->count();
    return 0;
}

/*!
    \internal
 */
void QDeclarativeRepeater::componentComplete()
{
    QDeclarativeItem::componentComplete();
    regenerate();
}

/*!
    \internal
 */
QVariant QDeclarativeRepeater::itemChange(GraphicsItemChange change,
                                       const QVariant &value)
{
    QVariant rv = QDeclarativeItem::itemChange(change, value);
    if (change == ItemParentHasChanged) {
        regenerate();
    }

    return rv;
}

void QDeclarativeRepeater::clear()
{
    Q_D(QDeclarativeRepeater);
    if (d->model) {
        foreach (QDeclarativeItem *item, d->deletables) {
            item->setParentItem(this);
            d->model->release(item);
        }
    }
    d->deletables.clear();
}

/*!
    \internal
 */
void QDeclarativeRepeater::regenerate()
{
    Q_D(QDeclarativeRepeater);
    if (!isComponentComplete())
        return;

    clear();

    if (!d->model || !d->model->count() || !d->model->isValid() || !parentItem() || !isComponentComplete())
        return;

    for (int ii = 0; ii < count(); ++ii) {
        QDeclarativeItem *item = d->model->item(ii);
        if (item) {
            item->setParent(parentItem());
            item->stackBefore(this);
            d->deletables << item;
        }
    }
}

void QDeclarativeRepeater::itemsInserted(int index, int count)
{
    Q_D(QDeclarativeRepeater);
    if (!isComponentComplete())
        return;
    for (int i = 0; i < count; ++i) {
        int modelIndex = index + i;
        QDeclarativeItem *item = d->model->item(modelIndex);
        if (item) {
            item->setParent(parentItem());
            if (modelIndex < d->deletables.count())
                item->stackBefore(d->deletables.at(modelIndex));
            else
                item->stackBefore(this);
            d->deletables.insert(modelIndex, item);
        }
    }
}

void QDeclarativeRepeater::itemsRemoved(int index, int count)
{
    Q_D(QDeclarativeRepeater);
    if (!isComponentComplete())
        return;
    while (count--) {
        QDeclarativeItem *item = d->deletables.takeAt(index);
        if (item) {
            item->setParentItem(this);
            d->model->release(item);
        }
    }
}

void QDeclarativeRepeater::itemsMoved(int from, int to, int count)
{
    Q_D(QDeclarativeRepeater);
    if (!isComponentComplete())
        return;
    QList<QDeclarativeItem*> removed;
    int removedCount = count;
    while (removedCount--)
        removed << d->deletables.takeAt(from);
    for (int i = 0; i < count; ++i)
        d->deletables.insert(to + i, removed.at(i));
    d->deletables.last()->stackBefore(this);
    for (int i = d->model->count()-1; i > 0; --i) {
        QDeclarativeItem *item = d->deletables.at(i-1);
        item->stackBefore(d->deletables.at(i));
    }
}

void QDeclarativeRepeater::modelReset()
{
    if (!isComponentComplete())
        return;
    regenerate();
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>#include <iostream>

const int GLOB = 0;

class T {
public:
  T(int t) : _t{t} { std::cout << "T()\n"; }
  T(T &t) : _t{t._t} { std::cout << "T(&)\n"; }
  T(T &&t) : _t{t._t} { std::cout << "T(&&)\n"; }
  ~T(void) { std::cout << "~T()\n"; }
private:
  int _t;
};

T getT(void)
{
  T t{1};
  return t;
}

// Note! RValue references must not be named! point of move( x ) is to remove
// name from scope to force a rvalue reference.
int main(void)
{
  // lvalue
  int a; // cell (s1) + capability to access it ('a').

  // rvalue
  (void) 1; // literal value 1, no capability to access it / identify it beyond
            // the semicolumn.

  // lvalue + rvalue
  a = 1; // store rvalue (1) into cell (s1) using capability 'a'.

  // Notes: values (rvalues) can be stored into a cell through a capability
  // (lvalue).

  // lvalue (pointers)
  int *b; // cell (s2 [for pointer val] + capability to access it ('b')
          // + 'derefernce' operation on capability
          // best to think of pointers as a type that stores a capability.
          // I.e., it reifies as a value a capability. So while 'a' is a
          // capabilty to access the cell s1, 'b' is a capability to access the
          // cell s2, which itself can store a capability.
          //
          // 'dereference' operation, invokes the capability stored in s2,
          // access the cell it identifies.

  // *b = 0 // error as we have yet to store a capability in cell s2.
  (void) &a; // reify capability 'a' into a rvalue.
  b = &a; // store capability 'a' into cell s2 using capability 'b'.

  // &9; // error as can't derive a new capability (lvalue) from an rvalue....
         // what cell would it be for?

  // lvalue references
  int &c = a; // creates a new capability 'a' to access the cell s1
              // identified by capability 'a'.
  // int &c; // error as need to refer to an existing capability when creating
             // new one.
  int &c1 = c; // create another capability 'c1' to access cell s1

  c = 0; // update cell (s1) to store the rvalue 0 using capability 'c'.
  a = 0; // equivalent to above, but using capability 'a'.

  // Note: the cell that a capability identifies can't be changed after
  // declaration. Pointers provide an ability to achieve operations that
  // utilize this feature, but they do so through a layer of indirection where
  // a capability has been reified into a rvalue stored in the cell that the
  // pointer type capability identifies.

  int d = a; // creates cell (s3) with capability 'd' to access it + stores a
             // copy of the rvalue in cell s1 referenced by capability 'a'.

  // lvalue references (more)
  // int &e = 0; // error as 0 is an rvalue, and we need an lvalue to create a
                 // new capability, since what cell would 'e' be a capability
                 // for in this situation?

  const int &e = 0; // OK as since 'e' is a capability to only access (but not
                    // modify) a cell, we can create it from an rvalue.
                    // Why want? If the type was expensive to copy, this gives
                    // us a constant reference to a literal.

  // (int&) e = 1; // may work or fail depending on how the compiler allocated '0'.
  // const int &e = GLOB;
  // (int&) e = 1; // extremely likely to segfault as GLOB allocated in
                   // read-only text section.

  // rvalue references
  int &&f = 0; // create cell (s4) and capability to access it 'f' + store 0;
  f = 1;

  // rvalue references (move)
  int &&g = 1;
  int &h = g;
  int &&i = std::move(g);
  int &&j = 2;

  std::cout << "&g: " << &g << std::endl;
  std::cout << "&h: " << &h << std::endl;
  std::cout << "&i: " << &i << std::endl;

  std::cout << "j: " << j << std::endl;
  std::cout << "&j: " << &j << std::endl;

  j = std::move(g);

  std::cout << "j: " << j << std::endl;
  std::cout << "&j: " << &j << std::endl;

  // why rvalue references?
  T&& t = getT();

  return 0;
}

<commit_msg>More play with rvalue references<commit_after>#include <iostream>

const int GLOB = 0;

class T {
public:
  T(int t) : _t{t} { std::cout << "T()\n"; }
  ~T(void) { std::cout << "~T()\n"; }

  T(const T &t) : _t{t._t} { std::cout << "T(&)\n"; }
  T & operator=(const T &t) { std::cout << "=(T&)\n"; return *this; }
  // T(const T &t) = delete;
  // T & operator=(const T &t) = delete;

  T(T &&t) : _t{t._t} { std::cout << "T(&&)\n"; }
  T & operator=(T &&t) { std::cout << "=(T&&)\n"; return *this; }
  // T(T &&) = delete;
  // T & operator=(T &&) = delete;

private:
  int _t;
};

T getT(void)
{
  T t{1};
  return t;
}

void fun(T && t)
{
  // You want to use an rvalue reference argument when moving the value inside
  // the function, you can get away with a normal reference, but the type is
  // less descriptive (i.e., doesn't communicate the move to the caller).
  // T t2 = std::move(t);
  std::cout << "fun(T&&)\n";
  return;
}

// Note! RValue references must not be named! point of move( x ) is to remove
// name from scope to force a rvalue reference.
int main(void)
{
  // lvalue
  int a; // cell (s1) + capability to access it ('a').

  // rvalue
  (void) 1; // literal value 1, no capability to access it / identify it beyond
            // the semicolumn.

  // lvalue + rvalue
  a = 1; // store rvalue (1) into cell (s1) using capability 'a'.

  // Notes: values (rvalues) can be stored into a cell through a capability
  // (lvalue).

  // lvalue (pointers)
  int *b; // cell (s2 [for pointer val] + capability to access it ('b')
          // + 'derefernce' operation on capability
          // best to think of pointers as a type that stores a capability.
          // I.e., it reifies as a value a capability. So while 'a' is a
          // capabilty to access the cell s1, 'b' is a capability to access the
          // cell s2, which itself can store a capability.
          //
          // 'dereference' operation, invokes the capability stored in s2,
          // access the cell it identifies.

  // *b = 0 // error as we have yet to store a capability in cell s2.
  (void) &a; // reify capability 'a' into a rvalue.
  b = &a; // store capability 'a' into cell s2 using capability 'b'.

  // &9; // error as can't derive a new capability (lvalue) from an rvalue....
         // what cell would it be for?

  // lvalue references
  int &c = a; // creates a new capability 'a' to access the cell s1
              // identified by capability 'a'.
  // int &c; // error as need to refer to an existing capability when creating
             // new one.
  int &c1 = c; // create another capability 'c1' to access cell s1

  c = 0; // update cell (s1) to store the rvalue 0 using capability 'c'.
  a = 0; // equivalent to above, but using capability 'a'.

  // Note: the cell that a capability identifies can't be changed after
  // declaration. Pointers provide an ability to achieve operations that
  // utilize this feature, but they do so through a layer of indirection where
  // a capability has been reified into a rvalue stored in the cell that the
  // pointer type capability identifies.

  int d = a; // creates cell (s3) with capability 'd' to access it + stores a
             // copy of the rvalue in cell s1 referenced by capability 'a'.

  // lvalue references (more)
  // int &e = 0; // error as 0 is an rvalue, and we need an lvalue to create a
                 // new capability, since what cell would 'e' be a capability
                 // for in this situation?

  const int &e = 0; // OK as since 'e' is a capability to only access (but not
                    // modify) a cell, we can create it from an rvalue.
                    // Why want? If the type was expensive to copy, this gives
                    // us a constant reference to a literal.

  // (int&) e = 1; // may work or fail depending on how the compiler allocated '0'.
  // const int &e = GLOB;
  // (int&) e = 1; // extremely likely to segfault as GLOB allocated in
                   // read-only text section.

  // rvalue references
  int &&f = 0; // create cell (s4) and capability to access it 'f' + store 0;
  f = 1;

  // rvalue references (move)
  int &&g = 1;
  int &h = g;
  int &&i = std::move(g);
  int &&j = 2;

  std::cout << "&g: " << &g << std::endl;
  std::cout << "&h: " << &h << std::endl;
  std::cout << "&i: " << &i << std::endl;

  std::cout << "j: " << j << std::endl;
  std::cout << "&j: " << &j << std::endl;

  j = std::move(g);

  std::cout << "j: " << j << std::endl;
  std::cout << "&j: " << &j << std::endl;

  // why rvalue references?
  T&& t = getT();

  std::cout << "end...\n";

  fun(std::move(t));

  return 0;
}

<|endoftext|>


<commit_before>#pragma once

#include <cstddef>		// std::size_t

#include <new>			// std::bad_array_new_length
#include <limits>		// std::numeric_limits

namespace cdp
{
	// Allocator requirements: 17.6.3.5

	/// A basic reference C++11 allocator mostly for testing and documenting requirements from the standard
	template <typename T>
	class ReferenceAllocator
	{
	public:
		using value_type = T;

		/// Default constructor
		ReferenceAllocator(...) noexcept {}
		/// Copy constructor
		ReferenceAllocator(const ReferenceAllocator& original) = default;
		/// Move constructor
		ReferenceAllocator(ReferenceAllocator&& original) = default;
		/// Destructor
		~ReferenceAllocator() = default;

		/// Copy assignment operator
		ReferenceAllocator& operator = (const ReferenceAllocator& rhs) = default;
		/// Move assignment operator
		ReferenceAllocator& operator = (ReferenceAllocator&& rhs) = default;

		/// Rebind constructor
		template <typename U>
		ReferenceAllocator(const ReferenceAllocator<U>& original) noexcept {}

		T* allocate(const std::size_t n) const
		{
			if (n > std::numeric_limits<std::size_t>::max()/sizeof(T))
				throw std::bad_array_new_length{};

			// 18.6.1.1/3 and 18.6.1.2: returns properly-aligned pointer, throws std::bad_alloc on error
			return static_cast<T*>(::operator new[](sizeof(T)*n));
		}
		void deallocate(T* const p, std::size_t) const noexcept
		{
			::operator delete[](p); // 18.6.1.2: doesn't throw
		}
	};

	template <typename T, typename U>
	inline bool operator == (const ReferenceAllocator<T>& lhs, const ReferenceAllocator<U>& rhs) noexcept
	{
		return true;
	}
	template <typename T, typename U>
	inline bool operator != (const ReferenceAllocator<T>& lhs, const ReferenceAllocator<U>& rhs) noexcept
	{
		return false;
	}
}<commit_msg>Added non-const check to T of ReferenceAllocator<T><commit_after>#pragma once

#include <cstddef>		// std::size_t

#include <new>			// std::bad_array_new_length
#include <limits>		// std::numeric_limits
#include <type_traits>	// std::is_const

namespace cdp
{
	// Allocator requirements: 17.6.3.5

	/// A basic reference C++11 allocator mostly for testing and documenting requirements from the standard
	template <typename T>
	class ReferenceAllocator
	{
		static_assert(!std::is_const<T>::value, "Allocated type must be non-const (17.6.3.5/2)");

	public:
		using value_type = T;

		/// Default constructor
		ReferenceAllocator(...) noexcept {}
		/// Copy constructor
		ReferenceAllocator(const ReferenceAllocator& original) = default;
		/// Move constructor
		ReferenceAllocator(ReferenceAllocator&& original) = default;
		/// Destructor
		~ReferenceAllocator() = default;

		/// Copy assignment operator
		ReferenceAllocator& operator = (const ReferenceAllocator& rhs) = default;
		/// Move assignment operator
		ReferenceAllocator& operator = (ReferenceAllocator&& rhs) = default;

		/// Rebind constructor
		template <typename U>
		ReferenceAllocator(const ReferenceAllocator<U>& original) noexcept {}

		T* allocate(const std::size_t n) const
		{
			if (n > std::numeric_limits<std::size_t>::max()/sizeof(T))
				throw std::bad_array_new_length{};

			// 18.6.1.1/3 and 18.6.1.2: returns properly-aligned pointer, throws std::bad_alloc on error
			return static_cast<T*>(::operator new[](sizeof(T)*n));
		}
		void deallocate(T* const p, std::size_t) const noexcept
		{
			::operator delete[](p); // 18.6.1.2: doesn't throw
		}
	};

	template <typename T, typename U>
	inline bool operator == (const ReferenceAllocator<T>& lhs, const ReferenceAllocator<U>& rhs) noexcept
	{
		return true;
	}
	template <typename T, typename U>
	inline bool operator != (const ReferenceAllocator<T>& lhs, const ReferenceAllocator<U>& rhs) noexcept
	{
		return false;
	}
}<|endoftext|>


<commit_before>/**
 *
 * HX711 library for Arduino
 * https://github.com/bogde/HX711
 *
 * MIT License
 * (c) 2018 Bogdan Necula
 *
**/
#include <Arduino.h>
#include <HX711.h>

#if defined(ARDUINO) && ARDUINO <= 106
	// "yield" is not implemented as noop in older Arduino Core releases, so let's define it.
	// See also: https://stackoverflow.com/questions/34497758/what-is-the-secret-of-the-arduino-yieldfunction/34498165#34498165
	void yield(void) {};
#endif

#if defined(ESP_H) || defined(CORE_TEENSY)
// Make shiftIn() be aware of clockspeed for ESP32, Teensy 3.x and friends
// https://github.com/bogde/HX711/issues/75
// https://github.com/arduino/Arduino/issues/6561
// https://community.hiveeyes.org/t/using-bogdans-canonical-hx711-library-on-the-esp32/539
uint8_t shiftInSlow(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
    uint8_t value = 0;
    uint8_t i;

    for(i = 0; i < 8; ++i) {
        digitalWrite(clockPin, HIGH);
        delayMicroseconds(1);
        if(bitOrder == LSBFIRST)
            value |= digitalRead(dataPin) << i;
        else
            value |= digitalRead(dataPin) << (7 - i);
        digitalWrite(clockPin, LOW);
        delayMicroseconds(1);
    }
    return value;
}
#define SHIFTIN_WITH_SPEED_SUPPORT(data,clock,order) shiftInSlow(data,clock,order)
#else
#define SHIFTIN_WITH_SPEED_SUPPORT(data,clock,order) shiftIn(data,clock,order)
#endif

HX711::HX711() {
}

HX711::~HX711() {
}

void HX711::begin(byte dout, byte pd_sck, byte gain) {
	PD_SCK = pd_sck;
	DOUT = dout;

	pinMode(PD_SCK, OUTPUT);
	pinMode(DOUT, INPUT);

	set_gain(gain);
}

bool HX711::is_ready() {
	return digitalRead(DOUT) == LOW;
}

void HX711::set_gain(byte gain) {
	switch (gain) {
		case 128:		// channel A, gain factor 128
			GAIN = 1;
			break;
		case 64:		// channel A, gain factor 64
			GAIN = 3;
			break;
		case 32:		// channel B, gain factor 32
			GAIN = 2;
			break;
	}

	digitalWrite(PD_SCK, LOW);
	read();
}

long HX711::read() {
	// wait for the chip to become ready
	while (!is_ready()) {
		// Will do nothing on Arduino but prevent resets of ESP8266 (Watchdog Issue)
		yield();
	}

	unsigned long value = 0;
	uint8_t data[3] = { 0 };
	uint8_t filler = 0x00;

	#ifdef ESP_H
	// Begin of critical section.
	// Critical sections are used as a valid protection method
	// against simultaneous access in vanilla FreeRTOS.
	// Disable the scheduler and call portDISABLE_INTERRUPTS. This prevents
	// context switches and servicing of ISRs during a critical section.
	portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
	portENTER_CRITICAL(&mux);
	#endif

	// pulse the clock pin 24 times to read the data
	data[2] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
	data[1] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
	data[0] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);

	// set the channel and the gain factor for the next reading using the clock pin
	for (unsigned int i = 0; i < GAIN; i++) {
		digitalWrite(PD_SCK, HIGH);
		#ifdef ESP_H
		delayMicroseconds(1);
		#endif
		digitalWrite(PD_SCK, LOW);
		#ifdef ESP_H
		delayMicroseconds(1);
		#endif
	}

	#ifdef ESP_H
	// End of critical section.
	portEXIT_CRITICAL(&mux);
	#endif

	// Replicate the most significant bit to pad out a 32-bit signed integer
	if (data[2] & 0x80) {
		filler = 0xFF;
	} else {
		filler = 0x00;
	}

	// Construct a 32-bit signed integer
	value = ( static_cast<unsigned long>(filler) << 24
			| static_cast<unsigned long>(data[2]) << 16
			| static_cast<unsigned long>(data[1]) << 8
			| static_cast<unsigned long>(data[0]) );

	return static_cast<long>(value);
}

long HX711::read_average(byte times) {
	long sum = 0;
	for (byte i = 0; i < times; i++) {
		sum += read();
		yield();
	}
	return sum / times;
}

double HX711::get_value(byte times) {
	return read_average(times) - OFFSET;
}

float HX711::get_units(byte times) {
	return get_value(times) / SCALE;
}

void HX711::tare(byte times) {
	double sum = read_average(times);
	set_offset(sum);
}

void HX711::set_scale(float scale) {
	SCALE = scale;
}

float HX711::get_scale() {
	return SCALE;
}

void HX711::set_offset(long offset) {
	OFFSET = offset;
}

long HX711::get_offset() {
	return OFFSET;
}

void HX711::power_down() {
	digitalWrite(PD_SCK, LOW);
	digitalWrite(PD_SCK, HIGH);
}

void HX711::power_up() {
	digitalWrite(PD_SCK, LOW);
}
<commit_msg>Prevent ints from corrupting the read sequence<commit_after>/**
 *
 * HX711 library for Arduino
 * https://github.com/bogde/HX711
 *
 * MIT License
 * (c) 2018 Bogdan Necula
 *
**/
#include <Arduino.h>
#include <HX711.h>
#ifdef AVR
// Acquire AVR-specific ATOMIC_BLOCK(ATOMIC_RESTORESTATE) macro
#include <util/atomic.h>
#endif

#if defined(ARDUINO) && ARDUINO <= 106
	// "yield" is not implemented as noop in older Arduino Core releases, so let's define it.
	// See also: https://stackoverflow.com/questions/34497758/what-is-the-secret-of-the-arduino-yieldfunction/34498165#34498165
	void yield(void) {};
#endif

#if defined(ESP_H) || defined(CORE_TEENSY)
// Make shiftIn() be aware of clockspeed for ESP32, Teensy 3.x and friends
// https://github.com/bogde/HX711/issues/75
// https://github.com/arduino/Arduino/issues/6561
// https://community.hiveeyes.org/t/using-bogdans-canonical-hx711-library-on-the-esp32/539
uint8_t shiftInSlow(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
    uint8_t value = 0;
    uint8_t i;

    for(i = 0; i < 8; ++i) {
        digitalWrite(clockPin, HIGH);
        delayMicroseconds(1);
        if(bitOrder == LSBFIRST)
            value |= digitalRead(dataPin) << i;
        else
            value |= digitalRead(dataPin) << (7 - i);
        digitalWrite(clockPin, LOW);
        delayMicroseconds(1);
    }
    return value;
}
#define SHIFTIN_WITH_SPEED_SUPPORT(data,clock,order) shiftInSlow(data,clock,order)
#else
#define SHIFTIN_WITH_SPEED_SUPPORT(data,clock,order) shiftIn(data,clock,order)
#endif

HX711::HX711() {
}

HX711::~HX711() {
}

void HX711::begin(byte dout, byte pd_sck, byte gain) {
	PD_SCK = pd_sck;
	DOUT = dout;

	pinMode(PD_SCK, OUTPUT);
	pinMode(DOUT, INPUT);

	set_gain(gain);
}

bool HX711::is_ready() {
	return digitalRead(DOUT) == LOW;
}

void HX711::set_gain(byte gain) {
	switch (gain) {
		case 128:		// channel A, gain factor 128
			GAIN = 1;
			break;
		case 64:		// channel A, gain factor 64
			GAIN = 3;
			break;
		case 32:		// channel B, gain factor 32
			GAIN = 2;
			break;
	}

	digitalWrite(PD_SCK, LOW);
	read();
}

long HX711::read() {
	// wait for the chip to become ready
	while (!is_ready()) {
		// Will do nothing on Arduino but prevent resets of ESP8266 (Watchdog Issue)
		yield();
	}

	unsigned long value = 0;
	uint8_t data[3] = { 0 };
	uint8_t filler = 0x00;

	// Protect the read sequence from system interrupts.  If an interrupt occurs during
	// the time the PD_SCK signal is high it will stretch the length of the clock pulse.
	// If the total pulse time exceeds 60 uSec this will cause the HX711 to enter
	// power down mode during the middle of the read sequence.  While the device will
	// wake up when PD_SCK goes low again, the reset starts a new conversion cycle which
	// forces DOUT high until that cycle is completed.
	//
	// The result is that all subsequent bits read by shiftIn() will read back as 1,
	// corrupting the value returned by read().  The ATOMIC_BLOCK macro disables
	// interrupts during the sequence and then restores the interrupt mask to its previous
	// state after the sequence completes, insuring that the entire read-and-gain-set
	// sequence is not interrupted.  The macro has a few minor advantages over bracketing
	// the sequence between NoInterrupts() and interrupts() calls.
	#ifdef AVR
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
	#endif

	#ifdef ESP_H
	// Begin of critical section.
	// Critical sections are used as a valid protection method
	// against simultaneous access in vanilla FreeRTOS.
	// Disable the scheduler and call portDISABLE_INTERRUPTS. This prevents
	// context switches and servicing of ISRs during a critical section.
	portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
	portENTER_CRITICAL(&mux);
	#endif

	// pulse the clock pin 24 times to read the data
	data[2] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
	data[1] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
	data[0] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);

	// set the channel and the gain factor for the next reading using the clock pin
	for (unsigned int i = 0; i < GAIN; i++) {
		digitalWrite(PD_SCK, HIGH);
		#ifdef ESP_H
		delayMicroseconds(1);
		#endif
		digitalWrite(PD_SCK, LOW);
		#ifdef ESP_H
		delayMicroseconds(1);
		#endif
	}

	#ifdef ESP_H
	// End of critical section.
	portEXIT_CRITICAL(&mux);
	#endif

	#ifdef AVR
	}
	#endif

	// Replicate the most significant bit to pad out a 32-bit signed integer
	if (data[2] & 0x80) {
		filler = 0xFF;
	} else {
		filler = 0x00;
	}

	// Construct a 32-bit signed integer
	value = ( static_cast<unsigned long>(filler) << 24
			| static_cast<unsigned long>(data[2]) << 16
			| static_cast<unsigned long>(data[1]) << 8
			| static_cast<unsigned long>(data[0]) );

	return static_cast<long>(value);
}

long HX711::read_average(byte times) {
	long sum = 0;
	for (byte i = 0; i < times; i++) {
		sum += read();
		yield();
	}
	return sum / times;
}

double HX711::get_value(byte times) {
	return read_average(times) - OFFSET;
}

float HX711::get_units(byte times) {
	return get_value(times) / SCALE;
}

void HX711::tare(byte times) {
	double sum = read_average(times);
	set_offset(sum);
}

void HX711::set_scale(float scale) {
	SCALE = scale;
}

float HX711::get_scale() {
	return SCALE;
}

void HX711::set_offset(long offset) {
	OFFSET = offset;
}

long HX711::get_offset() {
	return OFFSET;
}

void HX711::power_down() {
	digitalWrite(PD_SCK, LOW);
	digitalWrite(PD_SCK, HIGH);
}

void HX711::power_up() {
	digitalWrite(PD_SCK, LOW);
}
<|endoftext|>


<commit_before>//
// Copyright (C) 2005 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// Copyright (C) 2005 Pingtel Corp.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// $$
//////////////////////////////////////////////////////////////////////////////

// SYSTEM INCLUDES
// APPLICATION INCLUDES
#include "os/OsSysLog.h"
#include "resiprocateLib/sipXexternalLogger.h"

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STATICS

/* //////////////////////////// PUBLIC //////////////////////////////////// */

bool SipXExternalLogger::operator()(resip::Log::Level level,
                                    const resip::Subsystem& subsystem,
                                    const resip::Data& appName,
                                    const char* file,
                                    int line,
                                    const resip::Data& message,
                                    const resip::Data& messageWithHeaders)
{
   OsSysLog::add(FAC_CONFERENCE, toPriority(level), "%s", messageWithHeaders.c_str());
   return false;
}

OsSysLogPriority SipXExternalLogger::toPriority(resip::Log::Level level)
{
   switch (level)
   {
   case resip::Log::Crit:
      return PRI_CRIT;
   case resip::Log::Err:
      return PRI_ERR;
   case resip::Log::Warning:
      return PRI_WARNING;
   case resip::Log::Info:
      return PRI_INFO;
   case resip::Log::Debug:
   case resip::Log::Stack:
   default:
      return PRI_DEBUG;
   }
}
<commit_msg>- change for windows builds only<commit_after>//
// Copyright (C) 2005 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// Copyright (C) 2005 Pingtel Corp.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// $$
//////////////////////////////////////////////////////////////////////////////

// SYSTEM INCLUDES
// APPLICATION INCLUDES
#if defined(_WIN32)
#   include <winsock2.h>
#endif
#include "os/OsSysLog.h"
#include "resiprocateLib/sipXexternalLogger.h"

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STATICS

/* //////////////////////////// PUBLIC //////////////////////////////////// */

bool SipXExternalLogger::operator()(resip::Log::Level level,
                                    const resip::Subsystem& subsystem,
                                    const resip::Data& appName,
                                    const char* file,
                                    int line,
                                    const resip::Data& message,
                                    const resip::Data& messageWithHeaders)
{
   OsSysLog::add(FAC_CONFERENCE, toPriority(level), "%s", messageWithHeaders.c_str());
   return false;
}

OsSysLogPriority SipXExternalLogger::toPriority(resip::Log::Level level)
{
   switch (level)
   {
   case resip::Log::Crit:
      return PRI_CRIT;
   case resip::Log::Err:
      return PRI_ERR;
   case resip::Log::Warning:
      return PRI_WARNING;
   case resip::Log::Info:
      return PRI_INFO;
   case resip::Log::Debug:
   case resip::Log::Stack:
   default:
      return PRI_DEBUG;
   }
}
<|endoftext|>


<commit_before>/*
**	Author: Abhilash
**	Date:	18.04.2015
*/
// Bottom up computation
//
#include <bits/stdc++.h>
#define sf							scanf
#define pf 							printf
typedef long long ll;
using namespace std;
const ll N = 1e6+3;
const ll inf = 1e18;

ll DP[N][3];
ll cost[N][3];

ll n;

ll move[4][2] = {{1, -1}, {0, 1}, {1, 1}, {1, 0}};

ll dp() {
	DP[n][0] = cost[n][0]+cost[n][1];
	DP[n][1] = cost[n][1];
	DP[n][2] = inf;
	ll r, c, ans;
	for (int i = n-1; i >= 1; --i) {
		for (int j = 2; j >= 0; --j) {
			ans = inf;
			for (int k = 0; k < 4; ++k) {
				r = i + move[k][0];
				c = j + move[k][1];
				if (c >= 0 && c <= 2) {
					ans = min(ans, cost[i][j] + DP[r][c]);
				}
			}
			DP[i][j] = ans;
		}
	}
	return DP[1][1];
}

int main() {
	sf("%lld", &n);
	ll T = 1;
	while (n) {
		for (int i = 0; i < n; ++i)
			sf("%lld %lld %lld", &cost[i+1][0],
						&cost[i+1][1],
						&cost[i+1][2]);
		pf("%lld. %lld\n", T++, dp());
		sf("%lld", &n);
	}

	return 0;
}
<commit_msg>Update ACPC10D.cpp<commit_after>/*
**	Author: Abhilash
**	Date:	18.04.2015
*/
// Bottom up computation
//
#include <bits/stdc++.h>
#define sf							scanf
#define pf 							printf
typedef long long ll;
using namespace std;
const ll N = 1e6+3;
const ll inf = 1e18;

ll DP[N][3];
ll cost[N][3];

ll n;

ll move[4][2] = {{1, -1}, {0, 1}, {1, 1}, {1, 0}};

ll dp() {
	DP[n][0] = cost[n][0]+cost[n][1];
	DP[n][1] = cost[n][1];
	DP[n][2] = inf;
	ll r, c, ans;
	for (int i = n-1; i >= 1; --i) {
		for (int j = 2; j >= 0; --j) {
			ans = inf;
			for (int k = 0; k < 4; ++k) {
				r = i + move[k][0];
				c = j + move[k][1];
				if (c >= 0 && c <= 2) {
					ans = min(ans, cost[i][j] + DP[r][c]);
				}
			}
			DP[i][j] = ans;
		}
	}
	return DP[1][1];
}

int main() {
	sf("%lld", &n);
	ll T = 1;
	while (n) {
		for (int i = 0; i < n; ++i)
			sf("%lld %lld %lld", &cost[i+1][0],
						&cost[i+1][1],
						&cost[i+1][2]);
		pf("%lld. %lld\n", T++, dp());
		sf("%lld", &n);
	}
	return 0;
}
<|endoftext|>


<commit_before>//******************************************************************
//
// Copyright 2016 Samsung Electronics 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 <iostream>
#include <vector>
#include <algorithm>

#include "OCPlatform.h"
#include "RCSDiscoveryManager.h"
#include "RCSRemoteResourceObject.h"
#include "RCSAddress.h"
#include "RemoteSceneList.h"

using namespace OC;
using namespace OIC::Service;

typedef std::function< void() > Run;

enum Menu
{
    CREATE_REMOTE_SCENE_LIST = 1, CREATE_REMOTE_SCENE_COLLECTION,
    CREATE_REMOTE_SCENE, CREATE_REMOTE_SCENE_ACTION, EXECUTE_REMOTE_SCENE
};

constexpr int SCENE_RESULT_OK = 200;
constexpr int numMenu = 1;

const std::string scene_name = "Going Out";
const std::string relativetUri = OC_RSRVD_WELL_KNOWN_URI;
const std::vector<std::string> resourceTypes{ "oic.wk.scenelist", "core.light", "core.fan" };

std::mutex g_mtx;
std::mutex g_discoverymtx;
std::condition_variable g_cond;

std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> g_discoveryTask;

RCSRemoteResourceObject::Ptr g_foundListResource;
RCSRemoteResourceObject::Ptr g_foundLightResource;
RCSRemoteResourceObject::Ptr g_foundFanResource;

RemoteSceneList::Ptr g_sceneList;
RemoteSceneCollection::Ptr g_sceneCollection;
RemoteScene::Ptr g_scene;

void displaySceneList();
void displaySceneCollection();
void displayScene();
void displaySceneAction();

void runMenu(Menu);

// Scene Manager Remote API sample ---
void onRemoteSceneListCreated(RemoteSceneList::Ptr remoteSceneList, int eCode)
{
    std::cout << __func__ << " - error code : " << eCode << std::endl;

    if (eCode == SCENE_RESULT_OK)
    {
        g_sceneList = std::move(remoteSceneList);

        displaySceneList();
        runMenu(CREATE_REMOTE_SCENE_COLLECTION);
    }
    else
    {
        std::cout << "Create Remote scene list failed." << std::endl;
        runMenu(CREATE_REMOTE_SCENE_LIST);
    }
}

void onRemoteSceneCollectionCreated(RemoteSceneCollection::Ptr remoteSceneCol, int eCode)
{
    std::cout << __func__ << " - error code : " << eCode << std::endl;

    if (eCode == SCENE_RESULT_OK)
    {
        g_sceneCollection = remoteSceneCol;

        displaySceneList();
        displaySceneCollection();
        runMenu(CREATE_REMOTE_SCENE);
    }
    else
    {
        std::cout << "Create Remote scene collection failed." << std::endl;
        runMenu(CREATE_REMOTE_SCENE_COLLECTION);
    }
}

void onRemoteSceneCreated(RemoteScene::Ptr remoteScene, int eCode)
{
    std::cout << __func__ << " - error code : " << eCode << std::endl;

    if (eCode == SCENE_RESULT_OK)
    {
        g_scene = remoteScene;

        displaySceneList();
        displaySceneCollection();
        displayScene();
        runMenu(CREATE_REMOTE_SCENE_ACTION);
    }
    else
    {
        std::cout << "Create Remote scene failed." << std::endl;
        runMenu(CREATE_REMOTE_SCENE);
    }
}

void onRemoteSceneActionCreated(RemoteSceneAction::Ptr, int eCode)
{
    std::cout << __func__ << " - error code : " << eCode << std::endl;

    if (eCode == SCENE_RESULT_OK)
    {
        displaySceneList();
        displaySceneCollection();
        displaySceneAction();
        runMenu(EXECUTE_REMOTE_SCENE);
    }
    else
    {
        std::cout << "Create Remote scene action failed." << std::endl;
        runMenu(CREATE_REMOTE_SCENE_ACTION);
    }
}

void onRemoteSceneExecuted(const std::string &sceneName, int eCode)
{
    std::cout << __func__ << " - scene name : " << sceneName
              <<  ", error code : " << eCode << std::endl;

    if (eCode != SCENE_RESULT_OK)
    {
        std::cout << "Execute scene failed." << std::endl;
    }

    runMenu(EXECUTE_REMOTE_SCENE);
}

void createRemoteSceneList()
{
    if (g_foundListResource)
    {
        RemoteSceneList::createInstance(g_foundListResource, onRemoteSceneListCreated);
    }
    else
    {
        std::cout << "Scene List Resource is not discovered." << std::endl;
        runMenu(CREATE_REMOTE_SCENE_LIST);
    }
}

void createRemoteSceneCollection()
{
    if (!g_sceneList) return;

    g_sceneList->addNewSceneCollection(onRemoteSceneCollectionCreated);
}

void createRemoteScene()
{
    if (!g_sceneCollection) return;

    g_sceneCollection->addNewScene(scene_name, onRemoteSceneCreated);
}

void createRemoteSceneAction(
    RemoteScene::Ptr scene, RCSRemoteResourceObject::Ptr member,
    const std::string &key, const std::string &value)
{
    if (scene && member)
    {
        g_scene->addNewSceneAction(member, key, RCSResourceAttributes::Value(value),
            onRemoteSceneActionCreated);
    }
}

void createRemoteSceneActions()
{
    createRemoteSceneAction(g_scene, g_foundLightResource, "power", "off");
    createRemoteSceneAction(g_scene, g_foundFanResource, "speed", "0");
}

void executeScene()
{
    displaySceneList();
    displaySceneCollection();
    displaySceneAction();

    if (g_scene)
    {
        g_scene->execute(onRemoteSceneExecuted);
        std::cout << "\n\t'" << g_scene->getName() << "' is executed!\n" << std::endl;
    }
}
// --- Scene Manager Remote API sample

void configurePlatform()
{
    PlatformConfig config
    {
        OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos
    };
    OCPlatform::Configure(config);
}

void processUserInput(int min, int max)
{
    assert(min <= max);

    int input;

    std::cin >> input;

    if (!std::cin.fail())
    {
        if (input == max + 1)  exit(0);
        if (min <= input && input <= max) return;
    }

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    throw std::runtime_error("Invalid Input, please try again");
}

void excecuteCommand(std::string str, Run runFunc)
{
    std::cout << "\n========================================================\n";
    std::cout << "1. " << str << "\n";
    std::cout << "2. Quit         \n";
    std::cout << "========================================================  \n";

    try
    {
        processUserInput(1, numMenu);
        runFunc();
    }
    catch(std::exception & e)
    {
        std::cout << e.what() << std::endl;
    }
}

void runMenu(Menu menu)
{
    std::string strMenu;
    Run runFunc;

    switch (menu)
    {
    case CREATE_REMOTE_SCENE_LIST:
        strMenu = "Create a RemoteSceneList";
        runFunc = createRemoteSceneList;
        break;
    case CREATE_REMOTE_SCENE_COLLECTION:
        strMenu = "Create a RemoteSceneCollection";
        runFunc = createRemoteSceneCollection;
        break;
    case CREATE_REMOTE_SCENE:
        strMenu = "Create a RemoteScene";
        runFunc = createRemoteScene;
        break;
    case CREATE_REMOTE_SCENE_ACTION:
        strMenu = "Create RemoteSceneActions";
        runFunc = createRemoteSceneActions;
        break;
    case EXECUTE_REMOTE_SCENE:
        strMenu = "Execute RemoteScene";
        runFunc = executeScene;
        break;
    default:
        return;
    }

    excecuteCommand(strMenu, runFunc);
}

void displaySceneList()
{
    if (g_sceneList)
    {
        std::cout << "\tSceneList" << "\n\t   |_ _ _ ";
        std::cout << g_sceneList->getName() << std::endl;
    }
}

void displaySceneCollection()
{
    if (g_sceneCollection)
    {
        std::cout << "\t\t   |_ _ _ " << g_sceneCollection->getId()
            << " (SceneCollection)" << std::endl;
    }
}

void displayScene()
{
    if (g_scene)
    {
        std::cout << "\t\t\t   |_ _ _ " << g_scene->getName() << " (Scene)" << std::endl;
    }
}

void displaySceneAction()
{
    if (!g_scene) return;

    displayScene();

    auto sceneActionList = g_scene->getRemoteSceneActions();
    for (const auto &it : sceneActionList)
    {
        auto attr = it->getExecutionParameter();
        for (const auto &att : attr)
        {
            std::cout << "\t\t\t      \t\t|_ _ _ ";
            std::cout << it->getRemoteResourceObject()->getUri() << " : ";
            std::cout << att.key() << " - " << att.value().toString() << std::endl;
        }
    }
}

void onResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> foundResource)
{
    std::lock_guard< std::mutex > lock(g_discoverymtx);
    std::cout << "onResourceDiscovered callback" << std::endl;

    std::string resourceURI = foundResource->getUri();
    std::string hostAddress = foundResource->getAddress();
    std::vector< std::string > vecRTs = foundResource->getTypes();

    std::cout << "\t\tResource URI : " << resourceURI << std::endl;
    std::cout << "\t\tResource Host : " << hostAddress << std::endl;

    // if the found resource is a scene list resource
    if (std::find(vecRTs.begin(), vecRTs.end(), "oic.wk.scenelist") != vecRTs.end())
        g_foundListResource = foundResource;

    // if the found resource is a light resource
    else if (std::find(vecRTs.begin(), vecRTs.end(), "core.light") != vecRTs.end())
    {
        g_foundLightResource = foundResource;
    }

    // if the found resource is a fan resource
    else if (std::find(vecRTs.begin(), vecRTs.end(), "core.fan") != vecRTs.end())
    {
        g_foundFanResource = foundResource;
    }

    if (g_foundListResource && g_foundLightResource && g_foundFanResource)
    {
        g_discoveryTask->cancel();
        return;
    }

    g_cond.notify_all();
}

void discoverResource()
{
    std::cout << "Wait 2 seconds until discovered." << std::endl;

    try
    {
        g_discoveryTask
            = RCSDiscoveryManager::getInstance()->discoverResourceByTypes(RCSAddress::multicast(),
                    relativetUri, resourceTypes, &onResourceDiscovered);
    }
    catch (const RCSPlatformException &e)
    {
        std::cout << e.what() << std::endl;
    }
    std::unique_lock<std::mutex> lck(g_mtx);

    g_cond.wait_for(lck, std::chrono::seconds(4));
    return;
}

int main()
{
    configurePlatform();

    try
    {
        discoverResource();
    }
    catch(std::exception &e)
    {
        std::cout << e.what() << std::endl;
        return 0;
    }

    try
    {
        runMenu(CREATE_REMOTE_SCENE_LIST);
    }
    catch(std::exception &e)
    {
        std::cout << e.what() << std::endl;
        return 0;
    }

    while (true) { }

    std::cout << "Stopping the scene client" << std::endl;

    return 0;
}
<commit_msg>Enrich a sceneclient sample application for executing an existing scene at remote device<commit_after>//******************************************************************
//
// Copyright 2016 Samsung Electronics 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 <iostream>
#include <vector>
#include <algorithm>

#include "OCPlatform.h"
#include "RCSDiscoveryManager.h"
#include "RCSRemoteResourceObject.h"
#include "RCSAddress.h"
#include "RemoteSceneList.h"

using namespace OC;
using namespace OIC::Service;

constexpr int CREATE_REMOTE_SCENE_LIST = 1;

constexpr int CREATE_REMOTE_SCENE_COLLECTION = 1;
constexpr int SHOW_REMOTE_SCENE_COLLECTION = 2;

constexpr int CREATE_REMOTE_SCENE = 1;
constexpr int CREATE_REMOTE_SCENE_ACTION = 1;

constexpr int EXECUTE_REMOTE_SCENE = 1;

constexpr int SCENE_RESULT_OK = 200;

constexpr int numCreatedSceneAction = 2;
static int numRecvSceneActionCreationResp = 0;

typedef std::function< void() > Run;
Run g_currentRun;

const std::string scene_name = "Night mode";
const std::string relativetUri = OC_RSRVD_WELL_KNOWN_URI;
const std::vector<std::string> resourceTypes{ "oic.wk.scenelist", "core.light", "core.fan" };

std::mutex g_mtx;
std::mutex g_discoverymtx;
std::condition_variable g_cond;

std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> g_discoveryTask;

RCSRemoteResourceObject::Ptr g_foundListResource;
RCSRemoteResourceObject::Ptr g_foundLightResource;
RCSRemoteResourceObject::Ptr g_foundFanResource;

RemoteSceneList::Ptr g_sceneList;
RemoteSceneCollection::Ptr g_sceneCollection;
RemoteScene::Ptr g_scene;

void displaySceneList();
void runCreateRemoteSceneList();
void runRemoteSceneCollection();
void runCreateRemoteScene();
void runCreateRemoteSceneAction();
void runExecuteCreatedRemoteScene();
void runExecuteExistingRemoteScene();

// Scene Manager Remote API sample ---
void onRemoteSceneListCreated(RemoteSceneList::Ptr remoteSceneList, int eCode)
{
    std::cout << __func__ << " - error code : " << eCode << std::endl;

    if (eCode == SCENE_RESULT_OK)
    {
        g_sceneList = std::move(remoteSceneList);
        g_currentRun = runRemoteSceneCollection;
    }
    else
    {
        std::cout << "Create Remote scene list failed." << std::endl;
        g_currentRun = runCreateRemoteSceneList;
    }
    g_currentRun();
}

void onRemoteSceneCollectionCreated(RemoteSceneCollection::Ptr remoteSceneCol, int eCode)
{
    std::cout << __func__ << " - error code : " << eCode << std::endl;

    if (eCode == SCENE_RESULT_OK)
    {
        g_sceneCollection = remoteSceneCol;
        g_currentRun = runCreateRemoteScene;
    }
    else
    {
        std::cout << "Create Remote scene collection failed." << std::endl;
        g_currentRun = runRemoteSceneCollection;
    }

    g_currentRun();
}

void onRemoteSceneCreated(RemoteScene::Ptr remoteScene, int eCode)
{
    std::cout << __func__ << " - error code : " << eCode << std::endl;

    if (eCode == SCENE_RESULT_OK)
    {
        g_scene = remoteScene;

        g_currentRun = runCreateRemoteSceneAction;
    }
    else
    {
        std::cout << "Create Remote scene failed." << std::endl;
        g_currentRun = runCreateRemoteScene;
    }

    g_currentRun();
}

void onRemoteSceneActionCreated(RemoteSceneAction::Ptr, int eCode)
{
    std::cout << __func__ << " - error code : " << eCode << std::endl;

    if (eCode == SCENE_RESULT_OK)
    {
        g_currentRun = runExecuteCreatedRemoteScene;
    }
    else
    {
        std::cout << "Create Remote scene action failed." << std::endl;
        g_currentRun = runCreateRemoteSceneAction;
    }

    numRecvSceneActionCreationResp++;

    if(numCreatedSceneAction == numRecvSceneActionCreationResp)
        g_currentRun();
}

void onRemoteSceneExecuted(const std::string &sceneName, int eCode)
{
    std::cout << __func__ << " - scene name : " << sceneName
              <<  ", error code : " << eCode << std::endl;

    if (eCode != SCENE_RESULT_OK)
    {
        std::cout << "Execute scene failed." << std::endl;
    }

    g_currentRun();
}

// --- Scene Manager Remote API sample

void createRemoteSceneList()
{
    if (g_foundListResource)
    {
        RemoteSceneList::createInstance(g_foundListResource, onRemoteSceneListCreated);
    }
    else
    {
        std::cout << "Scene List Resource is not discovered." << std::endl;
        g_currentRun();
    }
}

void createRemoteSceneCollection()
{
    if (!g_sceneList) return;

    g_sceneList->addNewSceneCollection(onRemoteSceneCollectionCreated);
}

void showRemoteSceneCollection()
{
    if (!g_sceneList) return;

    if (g_sceneList->getRemoteSceneCollections().size() == 0) return;

    g_sceneCollection = g_sceneList->getRemoteSceneCollections().at(0);

    if( g_sceneCollection->getRemoteScenes().size() == 0) return;

    g_scene = g_sceneCollection->getRemoteScenes().begin()->second;
}

void createRemoteScene()
{
    if (!g_sceneCollection) return;

    g_sceneCollection->addNewScene(scene_name, onRemoteSceneCreated);
}

void createRemoteSceneAction(
    RemoteScene::Ptr scene, RCSRemoteResourceObject::Ptr member,
    const std::string &key, const std::string &value)
{
    if (scene && member)
    {
        g_scene->addNewSceneAction(member, key, RCSResourceAttributes::Value(value),
            onRemoteSceneActionCreated);
    }
}

void createRemoteSceneActions()
{
    createRemoteSceneAction(g_scene, g_foundLightResource, "power", "on");
    createRemoteSceneAction(g_scene, g_foundFanResource, "speed", "50");
}

void executeScene()
{
    displaySceneList();

    if (g_scene)
    {
        g_scene->execute(onRemoteSceneExecuted);
        std::cout << "\n\t'" << g_scene->getName() << "' is executed!\n" << std::endl;
    }
}

// --- Scene Manager Remote API sample

void configurePlatform()
{
    PlatformConfig config
    {
        OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos
    };
    OCPlatform::Configure(config);
}

int processUserInput(int min, int max)
{
    assert(min <= max);

    int input;

    std::cin >> input;

    if (!std::cin.fail())
    {
        if (input == max + 1)  exit(0);
        if (min <= input && input <= max) return input;
    }

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    throw std::runtime_error("Invalid Input, please try again");
}

void displaySceneList()
{
    if (!g_sceneList) return;

    std::cout << "\t" << g_sceneList->getName() << "(SceneList)" << std::endl;

    if (!g_sceneCollection) return;

    std::cout << "\t\t   |_ _ _ " << g_sceneCollection->getId() << " (SceneCollection)" << std::endl;

    for( const auto &it_scene : g_sceneCollection->getRemoteScenes() )
    {
        std::cout << "\t\t\t   |_ _ _ " << it_scene.first << " (Scene)" << std::endl;

        auto sceneActionList = it_scene.second->getRemoteSceneActions();
        for (const auto &it : sceneActionList)
        {
            auto attr = it->getExecutionParameter();
            for (const auto &att : attr)
            {
                std::cout << "\t\t\t      \t\t|_ _ _ ";
                std::cout << it->getRemoteResourceObject()->getUri() << " : ";
                std::cout << att.key() << " - " << att.value().toString() << std::endl;
            }
        }
    }
}

void displayClear(Run runFunc)
{
    auto ret = std::system("/usr/bin/clear");
    if(ret == -1)
    {
        std::cout << "clear error!" << std::endl;
    }
    g_currentRun = runFunc;
}

void displayCreateRemoteSceneListMenu()
{
    std::cout << "========================================================\n";
    std::cout << CREATE_REMOTE_SCENE_LIST  << ". Create a RemoteSceneList \n";
    std::cout << CREATE_REMOTE_SCENE_LIST + 1  << ". Quit                 \n";
    std::cout << "========================================================\n";
}

void displayRemoteSceneCollectionMenu()
{
    std::cout << "========================================================               \n";
    std::cout << CREATE_REMOTE_SCENE_COLLECTION  << ". Create a RemoteSceneCollection    \n";
    std::cout << SHOW_REMOTE_SCENE_COLLECTION  << ". Show existing RemoteSceneCollection \n";
    std::cout << SHOW_REMOTE_SCENE_COLLECTION + 1  << ". Quit                            \n";
    std::cout << "========================================================               \n";
}

void displayRemoteSceneCreationMenu()
{
    std::cout << "========================================================\n";
    std::cout << CREATE_REMOTE_SCENE  << ". Create a RemoteScene          \n";
    std::cout << CREATE_REMOTE_SCENE + 1  << ". Quit                      \n";
    std::cout << "========================================================\n";
}

void displayRemoteSceneActionCreationMenu()
{
    std::cout << "========================================================   \n";
    std::cout << CREATE_REMOTE_SCENE_ACTION  << ". Create RemoteSceneActions \n";
    std::cout << CREATE_REMOTE_SCENE_ACTION + 1  << ". Quit                  \n";
    std::cout << "========================================================   \n";
}

void displayExecuteCreatedRemoteSceneCreationMenu()
{
    std::cout << "========================================================\n";
    std::cout << EXECUTE_REMOTE_SCENE  << ". Execute RemoteScene          \n";
    std::cout << EXECUTE_REMOTE_SCENE + 1  << ". Quit                     \n";
    std::cout << "========================================================\n";
}

void displayExecuteExistingRemoteSceneCreationMenu()
{
    std::cout << "========================================================\n";
    std::cout << EXECUTE_REMOTE_SCENE  << ". Execute a first RemoteScene  \n";
    std::cout << EXECUTE_REMOTE_SCENE + 1  << ". Quit                     \n";
    std::cout << "========================================================\n";
}

void runExecuteExistingRemoteScene()
{
    displaySceneList();

    displayExecuteExistingRemoteSceneCreationMenu();

    try
    {
        int command = processUserInput(EXECUTE_REMOTE_SCENE, EXECUTE_REMOTE_SCENE);
        switch(command)
        {
            case EXECUTE_REMOTE_SCENE:
                executeScene();
                displayClear(runExecuteExistingRemoteScene);
                break;
        }
    } catch (std::exception &e)
    {
        std::cout << e.what() << std::endl;
        g_currentRun();
    }
}

void runExecuteCreatedRemoteScene()
{
    displaySceneList();

    displayExecuteCreatedRemoteSceneCreationMenu();

    try
    {
        int command = processUserInput(EXECUTE_REMOTE_SCENE, EXECUTE_REMOTE_SCENE);
        switch(command)
        {
            case EXECUTE_REMOTE_SCENE:
                executeScene();
                displayClear(runExecuteCreatedRemoteScene);
                break;
        }
    } catch (std::exception &e)
    {
        std::cout << e.what() << std::endl;
        g_currentRun();
    }
}

void runCreateRemoteSceneAction()
{
    displaySceneList();

    displayRemoteSceneActionCreationMenu();

    try
    {
        int command = processUserInput(CREATE_REMOTE_SCENE_ACTION, CREATE_REMOTE_SCENE_ACTION);
        switch(command)
        {
            case CREATE_REMOTE_SCENE_ACTION:
                createRemoteSceneActions();
                displayClear(runExecuteCreatedRemoteScene);
                break;
        }
    } catch (std::exception &e)
    {
        std::cout << e.what() << std::endl;
        g_currentRun();
    }
}

void runCreateRemoteScene()
{
    displaySceneList();

    displayRemoteSceneCreationMenu();

    try
    {
        int command = processUserInput(CREATE_REMOTE_SCENE, CREATE_REMOTE_SCENE);
        switch(command)
        {
            case CREATE_REMOTE_SCENE:
                createRemoteScene();
                displayClear(runCreateRemoteSceneAction);
                break;
        }
    } catch (std::exception &e)
    {
        std::cout << e.what() << std::endl;
        g_currentRun();
    }
}

void runRemoteSceneCollection()
{
    displaySceneList();

    displayRemoteSceneCollectionMenu();

    try
    {
        int command = processUserInput(CREATE_REMOTE_SCENE_COLLECTION, SHOW_REMOTE_SCENE_COLLECTION);
        switch(command)
        {
            case CREATE_REMOTE_SCENE_COLLECTION:
                createRemoteSceneCollection();
                displayClear(runCreateRemoteScene);
                break;
            case SHOW_REMOTE_SCENE_COLLECTION:
                showRemoteSceneCollection();
                displayClear(runExecuteExistingRemoteScene);
                g_currentRun();
                break;
        }
    } catch (std::exception &e)
    {
        std::cout << e.what() << std::endl;
        g_currentRun();
    }
}

void runCreateRemoteSceneList()
{
    displayCreateRemoteSceneListMenu();

    try
    {
        int command = processUserInput(CREATE_REMOTE_SCENE_LIST, CREATE_REMOTE_SCENE_LIST);
        switch(command)
        {
            case CREATE_REMOTE_SCENE_LIST:
                createRemoteSceneList();
                displayClear(runRemoteSceneCollection);
                break;
        }
    } catch (std::exception &e)
    {
        std::cout << e.what() << std::endl;
        g_currentRun();
    }
}

void onResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> foundResource)
{
    std::lock_guard< std::mutex > lock(g_discoverymtx);
    std::cout << "onResourceDiscovered callback" << std::endl;

    std::string resourceURI = foundResource->getUri();
    std::string hostAddress = foundResource->getAddress();
    std::vector< std::string > vecRTs = foundResource->getTypes();

    std::cout << "\t\tResource URI : " << resourceURI << std::endl;
    std::cout << "\t\tResource Host : " << hostAddress << std::endl;

    // if the found resource is a scene list resource
    if (std::find(vecRTs.begin(), vecRTs.end(), "oic.wk.scenelist") != vecRTs.end())
        g_foundListResource = foundResource;

    // if the found resource is a light resource
    else if (std::find(vecRTs.begin(), vecRTs.end(), "core.light") != vecRTs.end())
    {
        g_foundLightResource = foundResource;
    }

    // if the found resource is a fan resource
    else if (std::find(vecRTs.begin(), vecRTs.end(), "core.fan") != vecRTs.end())
    {
        g_foundFanResource = foundResource;
    }

    if (g_foundListResource && g_foundLightResource && g_foundFanResource)
    {
        g_discoveryTask->cancel();
        return;
    }

    g_cond.notify_all();
}

void discoverResource()
{
    std::cout << "Wait 2 seconds until discovered." << std::endl;

    try
    {
        g_discoveryTask
            = RCSDiscoveryManager::getInstance()->discoverResourceByTypes(RCSAddress::multicast(),
                    relativetUri, resourceTypes, &onResourceDiscovered);
    }
    catch (const RCSPlatformException &e)
    {
        std::cout << e.what() << std::endl;
    }
    std::unique_lock<std::mutex> lck(g_mtx);

    g_cond.wait_for(lck, std::chrono::seconds(4));
    return;
}

int main()
{
    configurePlatform();

    try
    {
        discoverResource();
    }
    catch(std::exception &e)
    {
        std::cout << e.what() << std::endl;
        return 0;
    }

    try
    {
        g_currentRun = runCreateRemoteSceneList;
        g_currentRun();
    }
    catch(std::exception &e)
    {
        std::cout << e.what() << std::endl;
        return 0;
    }

    while (true) { }

    std::cout << "Stopping the scene client" << std::endl;

    return 0;
}
<|endoftext|>