<commit_before>/*
 * D-Bus AT-SPI, Qt Adaptor
 *
 * Copyright 2008-2011 Nokia Corporation and/or its subsidiary(-ies).
 * Copyright 2008, 2009      Codethink Ltd.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "bridge.h"

#include "adaptor.h"
#include "accessible.h"
#include "application.h"
#include "cache.h"
#include "constant_mappings.h"
#include "dbusconnection.h"
#include "struct_marshallers.h"

#include "generated/dec_proxy.h"
#include "generated/event_adaptor.h"

#include <QEvent>
#include <QKeyEvent>

#define QSPI_DEC_NAME        "/org/a11y/atspi/Registry"
#define QSPI_DEC_OBJECT_PATH "/org/a11y/atspi/registry/deviceeventcontroller"

QSpiAccessibleBridge* QSpiAccessibleBridge::self = 0;

QSpiAccessibleBridge::QSpiAccessibleBridge()
    : cache(0), initialized(false)
{
    Q_ASSERT(self == 0);
    self = this;

    dbusConnection = new DBusConnection();
    if (!dBusConnection().isConnected()) {
        qWarning() << "Could not connect to dbus.";
    }

    qSpiInitializeStructTypes();
    qSpiInitializeConstantMappings();

    /* Create the cache of accessible objects */
    cache = new QSpiDBusCache(dBusConnection(), this);
    dec = new DeviceEventControllerProxy(this);

    bool reg = dBusConnection().registerObject(QSPI_DEC_OBJECT_PATH, this, QDBusConnection::ExportAdaptors);
    qDebug() << "Registered DEC: " << reg;

    QAccessibleInterface* i = QAccessible::queryAccessibleInterface(qApp);
    QSpiAdaptor* applicationAccessible = new QSpiApplication(dbusConnection->connection(), i);
    adaptors.insert(QString(QSPI_OBJECT_PATH_ROOT), applicationAccessible);
    connect(applicationAccessible, SIGNAL(windowActivated(QObject*)), this, SLOT(windowActivated(QObject*)));
}

void QSpiAccessibleBridge::windowActivated(QObject* window)
{
    QSpiAdaptor* a = spiBridge->objectToAccessible(window);
    QSpiAccessible* acc = static_cast<QSpiAccessible*>(a);
    acc->windowActivated();
}

QSpiAccessibleBridge::~QSpiAccessibleBridge()
{
    delete dbusConnection;
} // Qt currently doesn't delete plugins.

QDBusConnection QSpiAccessibleBridge::dBusConnection() const
{
    return dbusConnection->connection();
}

void QSpiAccessibleBridge::setRootObject(QAccessibleInterface *interface)
{
    initialized = true;

    // the interface we get will be for the QApplication object.
    // we already cache it in the constructor.
    Q_ASSERT(interface->object() == qApp);
}

QSpiObjectReference QSpiAccessibleBridge::getRootReference() const
{
    return QSpiObjectReference(dBusConnection(), QDBusObjectPath(QSPI_OBJECT_PATH_ROOT));
}

void QSpiAccessibleBridge::notifyAccessibilityUpdate(int reason, QAccessibleInterface *interface, int index)
{
    Q_ASSERT(interface && interface->isValid());

    if (!initialized)
        return;

    // this gets deleted, so create one if we don't have it yet
    QSpiAdaptor* accessible = interfaceToAccessible(interface, index, false);
    Q_ASSERT(accessible->associatedInterface()->object() == interface->object());

    switch (reason) {
    case QAccessible::Focus: {
        static QSpiAccessible *lastFocused = 0;
        if (lastFocused) {
            QDBusVariant data;
            data.setVariant(QVariant::fromValue(lastFocused->getReference()));
            emit lastFocused->StateChanged("focused", 0, 0, data, getRootReference());
        }
        lastFocused = qobject_cast<QSpiAccessible*>(accessible);
    }
    }
//    qDebug() << "QSpiAccessibleBridge::notifyAccessibilityUpdate" << QString::number(reason, 16)
//             << " obj: " << interface->object()
//             << (interface->isValid() ? interface->object()->objectName() : " invalid interface!")
//             << accessible->interface;
    accessible->accessibleEvent((QAccessible::Event)reason);
}

QSpiAdaptor* QSpiAccessibleBridge::objectToAccessible(QObject *object)
{
    Q_ASSERT(object);

    QString path = QSpiAccessible::pathForObject(object);
    if (adaptors.contains(path))
        return adaptors.value(path);

    QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(object);
    if (!interface) {
        qWarning() << "Create accessible for object which cannot create an accessible interface." << object;
        return 0;
    }

    return interfaceToAccessible(interface, 0, true);
}

QSpiAdaptor* QSpiAccessibleBridge::interfaceToAccessible(QAccessibleInterface* interface, int index, bool takeOwnershipOfInterface)
{
    Q_ASSERT(interface && interface->isValid());

    QString path = QSpiAccessible::pathForInterface(interface, index);
    // optimize?
    if (adaptors.contains(path))
        return adaptors.value(path);

// FIXME if this works, we can save code below...
//    QAccessibleInterface* copy(QAccessibleInterface(*interface));

    // if we cannot keep the interface around (notifyAccessibility will delete interfaces)
    // we need to ask for one that we can keep
    if (!takeOwnershipOfInterface) {
        QAccessibleInterface* ownedInterface = QAccessible::queryAccessibleInterface(interface->object());
        if (!ownedInterface) {
            QAccessibleInterface* parentInterface;
            interface->navigate(QAccessible::Ancestor, 1, &parentInterface);
            Q_ASSERT(parentInterface);
            int index = parentInterface->indexOfChild(interface);
            parentInterface->navigate(QAccessible::Child, index, &ownedInterface);
            delete parentInterface;
        }
        Q_ASSERT(ownedInterface);
        interface = ownedInterface;
    }
    QSpiAdaptor *accessible = new QSpiAccessible(interface, index);

    // put ourself in the list of accessibles
    adaptors.insert(path, accessible);

    // say hello to d-bus
    cache->emitAddAccessible(accessible->getCacheItem());

    // notify about the new child of our parent
    int childCount = 0;
    QSpiAdaptor* parentAdaptor = 0;
    if (index == 0) {
        QAccessibleInterface *parent = 0;
        interface->navigate(QAccessible::Ancestor, 1, &parent);
        if (parent) {
            parentAdaptor = interfaceToAccessible(parent, 0, true);
            childCount = parent->childCount();
        }
    } else {
        parentAdaptor = interfaceToAccessible(interface, 0, true);
        childCount = interface->childCount();
    }

    if (parentAdaptor) {
        QSpiObjectReference r = accessible->getReference();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(r));
        parentAdaptor->signalChildrenChanged("add", childCount, 0, data);
    }

    return accessible;
}

void QSpiAccessibleBridge::objectDestroyed(QObject* o)
{
    QString path = QSpiAccessible::pathForObject(o);
    adaptors.remove(path);
}

void QSpiAccessibleBridge::removeAdaptor(QSpiAdaptor *adaptor)
{
    adaptors.remove(adaptor->getReference().path.path());
}
<commit_msg>Don't assert on creation of some accessibles.<commit_after>/*
 * D-Bus AT-SPI, Qt Adaptor
 *
 * Copyright 2008-2011 Nokia Corporation and/or its subsidiary(-ies).
 * Copyright 2008, 2009      Codethink Ltd.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "bridge.h"

#include "adaptor.h"
#include "accessible.h"
#include "application.h"
#include "cache.h"
#include "constant_mappings.h"
#include "dbusconnection.h"
#include "struct_marshallers.h"

#include "generated/dec_proxy.h"
#include "generated/event_adaptor.h"

#include <QEvent>
#include <QKeyEvent>

#define QSPI_DEC_NAME        "/org/a11y/atspi/Registry"
#define QSPI_DEC_OBJECT_PATH "/org/a11y/atspi/registry/deviceeventcontroller"

QSpiAccessibleBridge* QSpiAccessibleBridge::self = 0;

QSpiAccessibleBridge::QSpiAccessibleBridge()
    : cache(0), initialized(false)
{
    Q_ASSERT(self == 0);
    self = this;

    dbusConnection = new DBusConnection();
    if (!dBusConnection().isConnected()) {
        qWarning() << "Could not connect to dbus.";
    }

    qSpiInitializeStructTypes();
    qSpiInitializeConstantMappings();

    /* Create the cache of accessible objects */
    cache = new QSpiDBusCache(dBusConnection(), this);
    dec = new DeviceEventControllerProxy(this);

    bool reg = dBusConnection().registerObject(QSPI_DEC_OBJECT_PATH, this, QDBusConnection::ExportAdaptors);
    qDebug() << "Registered DEC: " << reg;

    QAccessibleInterface* i = QAccessible::queryAccessibleInterface(qApp);
    QSpiAdaptor* applicationAccessible = new QSpiApplication(dbusConnection->connection(), i);
    adaptors.insert(QString(QSPI_OBJECT_PATH_ROOT), applicationAccessible);
    connect(applicationAccessible, SIGNAL(windowActivated(QObject*)), this, SLOT(windowActivated(QObject*)));
}

void QSpiAccessibleBridge::windowActivated(QObject* window)
{
    QSpiAdaptor* a = spiBridge->objectToAccessible(window);
    QSpiAccessible* acc = static_cast<QSpiAccessible*>(a);
    acc->windowActivated();
}

QSpiAccessibleBridge::~QSpiAccessibleBridge()
{
    delete dbusConnection;
} // Qt currently doesn't delete plugins.

QDBusConnection QSpiAccessibleBridge::dBusConnection() const
{
    return dbusConnection->connection();
}

void QSpiAccessibleBridge::setRootObject(QAccessibleInterface *interface)
{
    initialized = true;

    // the interface we get will be for the QApplication object.
    // we already cache it in the constructor.
    Q_ASSERT(interface->object() == qApp);
}

QSpiObjectReference QSpiAccessibleBridge::getRootReference() const
{
    return QSpiObjectReference(dBusConnection(), QDBusObjectPath(QSPI_OBJECT_PATH_ROOT));
}

void QSpiAccessibleBridge::notifyAccessibilityUpdate(int reason, QAccessibleInterface *interface, int index)
{
    Q_ASSERT(interface && interface->isValid());

    if (!initialized)
        return;

    // this gets deleted, so create one if we don't have it yet
    QSpiAdaptor* accessible = interfaceToAccessible(interface, index, false);
    //Q_ASSERT(accessible->associatedInterface()->object() == interface->object());
    if (accessible->associatedInterface()->object() == interface->object()) {
        qWarning() << "Creating accessible with different object than the original interface!";
    }

    switch (reason) {
    case QAccessible::Focus: {
        static QSpiAccessible *lastFocused = 0;
        if (lastFocused) {
            QDBusVariant data;
            data.setVariant(QVariant::fromValue(lastFocused->getReference()));
            emit lastFocused->StateChanged("focused", 0, 0, data, getRootReference());
        }
        lastFocused = qobject_cast<QSpiAccessible*>(accessible);
    }
    }
//    qDebug() << "QSpiAccessibleBridge::notifyAccessibilityUpdate" << QString::number(reason, 16)
//             << " obj: " << interface->object()
//             << (interface->isValid() ? interface->object()->objectName() : " invalid interface!")
//             << accessible->interface;
    accessible->accessibleEvent((QAccessible::Event)reason);
}

QSpiAdaptor* QSpiAccessibleBridge::objectToAccessible(QObject *object)
{
    Q_ASSERT(object);

    QString path = QSpiAccessible::pathForObject(object);
    if (adaptors.contains(path))
        return adaptors.value(path);

    QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(object);
    if (!interface) {
        qWarning() << "Create accessible for object which cannot create an accessible interface." << object;
        return 0;
    }

    return interfaceToAccessible(interface, 0, true);
}

QSpiAdaptor* QSpiAccessibleBridge::interfaceToAccessible(QAccessibleInterface* interface, int index, bool takeOwnershipOfInterface)
{
    Q_ASSERT(interface && interface->isValid());

    QString path = QSpiAccessible::pathForInterface(interface, index);
    // optimize?
    if (adaptors.contains(path))
        return adaptors.value(path);

// FIXME if this works, we can save code below...
//    QAccessibleInterface* copy(QAccessibleInterface(*interface));

    // if we cannot keep the interface around (notifyAccessibility will delete interfaces)
    // we need to ask for one that we can keep
    if (!takeOwnershipOfInterface) {
        QAccessibleInterface* ownedInterface = QAccessible::queryAccessibleInterface(interface->object());
        if (!ownedInterface) {
            QAccessibleInterface* parentInterface;
            interface->navigate(QAccessible::Ancestor, 1, &parentInterface);
            Q_ASSERT(parentInterface);
            int index = parentInterface->indexOfChild(interface);
            parentInterface->navigate(QAccessible::Child, index, &ownedInterface);
            delete parentInterface;
        }
        Q_ASSERT(ownedInterface);
        interface = ownedInterface;
    }
    QSpiAdaptor *accessible = new QSpiAccessible(interface, index);

    // put ourself in the list of accessibles
    adaptors.insert(path, accessible);

    // say hello to d-bus
    cache->emitAddAccessible(accessible->getCacheItem());

    // notify about the new child of our parent
    int childCount = 0;
    QSpiAdaptor* parentAdaptor = 0;
    if (index == 0) {
        QAccessibleInterface *parent = 0;
        interface->navigate(QAccessible::Ancestor, 1, &parent);
        if (parent) {
            parentAdaptor = interfaceToAccessible(parent, 0, true);
            childCount = parent->childCount();
        }
    } else {
        parentAdaptor = interfaceToAccessible(interface, 0, true);
        childCount = interface->childCount();
    }

    if (parentAdaptor) {
        QSpiObjectReference r = accessible->getReference();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(r));
        parentAdaptor->signalChildrenChanged("add", childCount, 0, data);
    }

    return accessible;
}

void QSpiAccessibleBridge::objectDestroyed(QObject* o)
{
    QString path = QSpiAccessible::pathForObject(o);
    adaptors.remove(path);
}

void QSpiAccessibleBridge::removeAdaptor(QSpiAdaptor *adaptor)
{
    adaptors.remove(adaptor->getReference().path.path());
}
<|endoftext|>


<commit_before>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#include <qi/assert.hpp>
#include <qi/buffer.hpp>
#include <qi/log.hpp>

#include <cstdio>
#include <cstring>
#include <stdexcept>
#include <iomanip>
#include <ctype.h>

#include <boost/pool/singleton_pool.hpp>
#include <boost/make_shared.hpp>

#include "buffer_p.hpp"

qiLogCategory("qi.Buffer");

namespace qi
{
  BufferPrivate::BufferPrivate() // cppcheck-suppress uninitMemberVar
    : _bigdata(0)
    , _cachedSubBufferTotalSize(0)
    , used(0)
    , available(sizeof(_data))
  {
  }

  BufferPrivate::~BufferPrivate()
  {
    if (_bigdata)
    {
      free(_bigdata);
      _bigdata = NULL;
    }
  }

  struct MyPoolTag { };
  using buffer_pool = boost::singleton_pool<MyPoolTag, sizeof(BufferPrivate)>;

  void* BufferPrivate::operator new(size_t sz)
  {
    QI_ASSERT(sz <= sizeof(BufferPrivate));
    return buffer_pool::malloc();
  }

  void BufferPrivate::operator delete(void* ptr)
  {
    buffer_pool::free(ptr);
  }

  int BufferPrivate::indexOfSubBuffer(size_t offset) const
  {
    for(unsigned i = 0; i < _subBuffers.size(); ++i) {
      if (_subBuffers[i].first == offset) {
        return i;
      }
    }

    return -1;
  }

  Buffer::Buffer()
    : _p(boost::make_shared<BufferPrivate>())
  {
  }

  Buffer::Buffer(const Buffer& b)
  {
    (*this) = b;
  }

  Buffer& Buffer::operator=(const Buffer& b)
  {
    _p = b._p;
    return *this;
  }

  Buffer::Buffer(Buffer&& b)
    : _p(std::move(b._p))
  {
    // The default state of a qi::Buffer contains a valid BufferPrivate pointer.
    b._p = boost::make_shared<BufferPrivate>();
  }

  Buffer& Buffer::operator=(Buffer&& b)
  {
    _p = std::move(b._p);
    b._p = boost::make_shared<BufferPrivate>();
    return *this;
  }

  unsigned char* BufferPrivate::data()
  {
    if (_bigdata)
      return (_bigdata);

    return (_data);
  }

  bool BufferPrivate::resize(size_t neededSize)
  {
    neededSize += BLOCK; // Should be enough in most cases;

    qiLogDebug() << "Resizing buffer from " << available << " to " << neededSize;
    unsigned char *newBigdata;

    newBigdata = static_cast<unsigned char *>(realloc(_bigdata, neededSize));
    if (newBigdata == NULL)
      return false;
    if (!_bigdata && used > 0)
      ::memcpy(newBigdata, _data, used);
    available = neededSize;
    _bigdata = newBigdata; // Don't worry, realloc free previous buffer if needed
    return true;
  }

  bool Buffer::write(const void *data, size_t size)
  {
    if (_p->used + size > _p->available)
    {
      bool ret = _p->resize(_p->used + size);
      if (!ret) {
        qiLogVerbose() << "write(" << size << ") failed, buffer size is " << _p->available;
        return false;
      }
    }

    memcpy(_p->data() + _p->used, data, size);
    _p->used += size;

    return true;
  }

  size_t Buffer::addSubBuffer(const Buffer& buffer)
  {
    size_t subBufferSize = buffer.size();
    size_t actualUsed = _p->used;

    write((uint32_t*)&subBufferSize, sizeof(uint32_t));

    _p->_subBuffers.push_back(std::make_pair(actualUsed, buffer));
    _p->_cachedSubBufferTotalSize += buffer.totalSize();
    return actualUsed;
  }

  bool Buffer::hasSubBuffer(size_t offset) const
  {
    return (_p->indexOfSubBuffer(offset) != -1);
  }

  const Buffer& Buffer::subBuffer(size_t offset) const
  {
    int index = _p->indexOfSubBuffer(offset);

    if (index == -1)
      throw std::runtime_error("No sub-buffer at the specified offset.");

    return _p->_subBuffers[index].second;
  }

  size_t Buffer::size() const
  {
    return _p->used;
  }

  size_t Buffer::totalSize() const
  {
    return size() + _p->_cachedSubBufferTotalSize;
  }

  const std::vector<std::pair<size_t, Buffer> > & Buffer::subBuffers() const
  {
    return _p->_subBuffers;
  }

  /*
  ** We need to allocate memory as soon as this function is called
  ** Returned memory MUST be coherent with the buffer used (either on stack/heap)
  ** As we can't know if the buffer will be used on heap later, we've to resize on heap
  */
  void *Buffer::reserve(size_t size)
  {
    if (_p->used + size > _p->available)
      _p->resize(_p->used + size);

    void *p = _p->data() + _p->used;
    _p->used += size;

    return p;
  }

  void Buffer::clear()
  {
    _p->used = 0;
    _p->_subBuffers.clear();
    _p->_cachedSubBufferTotalSize = 0;
  }

  void* Buffer::data()
  {
    return _p ? _p->data() : 0;
  }

  const void* Buffer::data() const
  {
    return _p ? _p->data() : 0;
  }

  const void *Buffer::read(size_t offset, size_t length) const
  {
    if (offset + length > _p->used)
    {
      qiLogDebug() << "Attempt to read " << offset+length
       <<" on buffer of size " << _p->used;
      return  nullptr;
    }
    return (char*)_p->data() + offset;
  }

  size_t Buffer::read(void* buffer, size_t offset, size_t length) const
  {
    if (offset > _p->used)
    {
      qiLogDebug() << "Attempt to read " << offset+length
      <<" on buffer of size " << _p->used;
      return -1;
    }
    size_t copy = std::min(length, _p->used - offset);
    memcpy(buffer, (char*)_p->data()+offset, copy);
    return copy;
  }

  namespace detail {
    void printBuffer(std::ostream& stream, const Buffer& buffer)
    {
      if (buffer.size() == 0) {
        qiLogDebug() << "dump on empty buffer";
        return;
      }

      std::ios_base::fmtflags flags = stream.flags();
      unsigned int i = 0;
      const unsigned char* data = (const unsigned char*)buffer.data();

      while (i < buffer.size()) {
        if (i % 16 == 0) stream << std::hex << std::setfill('0') << std::setw(8) << i << ": ";
        stream << std::setw(2) << (const unsigned int) data[i];
        i++;
        if (i % 2 == 0) stream << ' ';
        if (i % 16 == 0)
        {
          for (unsigned int j = i - 16; j < i ; j++)
          {
            char c = data[j];
            stream << (isgraph(c) ? c : '.');
          }
          stream << '\n';
        }
      }

      while (i % 16 != 0) {
        stream << "  ";
        if (i % 2 == 0) stream << ' ';
        i++;
      }
      stream << ' ';

      for (unsigned int j = i - 16; j < buffer.size(); j++) {
        char c = data[j];
        stream << (isgraph(c) ? c : '.');
      }

      stream.flags(flags);
    }
  }
} // !qi
<commit_msg>Fixed buffer content logging calling isgraph() with invalid values.<commit_after>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#include <qi/assert.hpp>
#include <qi/buffer.hpp>
#include <qi/log.hpp>

#include <cstdio>
#include <cstring>
#include <stdexcept>
#include <iomanip>
#include <ctype.h>

#include <boost/pool/singleton_pool.hpp>
#include <boost/make_shared.hpp>

#include "buffer_p.hpp"

qiLogCategory("qi.Buffer");

namespace qi
{
  BufferPrivate::BufferPrivate() // cppcheck-suppress uninitMemberVar
    : _bigdata(0)
    , _cachedSubBufferTotalSize(0)
    , used(0)
    , available(sizeof(_data))
  {
  }

  BufferPrivate::~BufferPrivate()
  {
    if (_bigdata)
    {
      free(_bigdata);
      _bigdata = NULL;
    }
  }

  struct MyPoolTag { };
  using buffer_pool = boost::singleton_pool<MyPoolTag, sizeof(BufferPrivate)>;

  void* BufferPrivate::operator new(size_t sz)
  {
    QI_ASSERT(sz <= sizeof(BufferPrivate));
    return buffer_pool::malloc();
  }

  void BufferPrivate::operator delete(void* ptr)
  {
    buffer_pool::free(ptr);
  }

  int BufferPrivate::indexOfSubBuffer(size_t offset) const
  {
    for(unsigned i = 0; i < _subBuffers.size(); ++i) {
      if (_subBuffers[i].first == offset) {
        return i;
      }
    }

    return -1;
  }

  Buffer::Buffer()
    : _p(boost::make_shared<BufferPrivate>())
  {
  }

  Buffer::Buffer(const Buffer& b)
  {
    (*this) = b;
  }

  Buffer& Buffer::operator=(const Buffer& b)
  {
    _p = b._p;
    return *this;
  }

  Buffer::Buffer(Buffer&& b)
    : _p(std::move(b._p))
  {
    // The default state of a qi::Buffer contains a valid BufferPrivate pointer.
    b._p = boost::make_shared<BufferPrivate>();
  }

  Buffer& Buffer::operator=(Buffer&& b)
  {
    _p = std::move(b._p);
    b._p = boost::make_shared<BufferPrivate>();
    return *this;
  }

  unsigned char* BufferPrivate::data()
  {
    if (_bigdata)
      return (_bigdata);

    return (_data);
  }

  bool BufferPrivate::resize(size_t neededSize)
  {
    neededSize += BLOCK; // Should be enough in most cases;

    qiLogDebug() << "Resizing buffer from " << available << " to " << neededSize;
    unsigned char *newBigdata;

    newBigdata = static_cast<unsigned char *>(realloc(_bigdata, neededSize));
    if (newBigdata == NULL)
      return false;
    if (!_bigdata && used > 0)
      ::memcpy(newBigdata, _data, used);
    available = neededSize;
    _bigdata = newBigdata; // Don't worry, realloc free previous buffer if needed
    return true;
  }

  bool Buffer::write(const void *data, size_t size)
  {
    if (_p->used + size > _p->available)
    {
      bool ret = _p->resize(_p->used + size);
      if (!ret) {
        qiLogVerbose() << "write(" << size << ") failed, buffer size is " << _p->available;
        return false;
      }
    }

    memcpy(_p->data() + _p->used, data, size);
    _p->used += size;

    return true;
  }

  size_t Buffer::addSubBuffer(const Buffer& buffer)
  {
    size_t subBufferSize = buffer.size();
    size_t actualUsed = _p->used;

    write((uint32_t*)&subBufferSize, sizeof(uint32_t));

    _p->_subBuffers.push_back(std::make_pair(actualUsed, buffer));
    _p->_cachedSubBufferTotalSize += buffer.totalSize();
    return actualUsed;
  }

  bool Buffer::hasSubBuffer(size_t offset) const
  {
    return (_p->indexOfSubBuffer(offset) != -1);
  }

  const Buffer& Buffer::subBuffer(size_t offset) const
  {
    int index = _p->indexOfSubBuffer(offset);

    if (index == -1)
      throw std::runtime_error("No sub-buffer at the specified offset.");

    return _p->_subBuffers[index].second;
  }

  size_t Buffer::size() const
  {
    return _p->used;
  }

  size_t Buffer::totalSize() const
  {
    return size() + _p->_cachedSubBufferTotalSize;
  }

  const std::vector<std::pair<size_t, Buffer> > & Buffer::subBuffers() const
  {
    return _p->_subBuffers;
  }

  /*
  ** We need to allocate memory as soon as this function is called
  ** Returned memory MUST be coherent with the buffer used (either on stack/heap)
  ** As we can't know if the buffer will be used on heap later, we've to resize on heap
  */
  void *Buffer::reserve(size_t size)
  {
    if (_p->used + size > _p->available)
      _p->resize(_p->used + size);

    void *p = _p->data() + _p->used;
    _p->used += size;

    return p;
  }

  void Buffer::clear()
  {
    _p->used = 0;
    _p->_subBuffers.clear();
    _p->_cachedSubBufferTotalSize = 0;
  }

  void* Buffer::data()
  {
    return _p ? _p->data() : 0;
  }

  const void* Buffer::data() const
  {
    return _p ? _p->data() : 0;
  }

  const void *Buffer::read(size_t offset, size_t length) const
  {
    if (offset + length > _p->used)
    {
      qiLogDebug() << "Attempt to read " << offset+length
       <<" on buffer of size " << _p->used;
      return  nullptr;
    }
    return (char*)_p->data() + offset;
  }

  size_t Buffer::read(void* buffer, size_t offset, size_t length) const
  {
    if (offset > _p->used)
    {
      qiLogDebug() << "Attempt to read " << offset+length
      <<" on buffer of size " << _p->used;
      return -1;
    }
    size_t copy = std::min(length, _p->used - offset);
    memcpy(buffer, (char*)_p->data()+offset, copy);
    return copy;
  }

  namespace detail {
    void printBuffer(std::ostream& stream, const Buffer& buffer)
    {
      if (buffer.size() == 0) {
        qiLogDebug() << "dump on empty buffer";
        return;
      }

      std::ios_base::fmtflags flags = stream.flags();
      unsigned int i = 0;
      const unsigned char* data = (const unsigned char*)buffer.data();

      while (i < buffer.size()) {
        if (i % 16 == 0) stream << std::hex << std::setfill('0') << std::setw(8) << i << ": ";
        stream << std::setw(2) << (const unsigned int) data[i];
        i++;
        if (i % 2 == 0) stream << ' ';
        if (i % 16 == 0)
        {
          for (unsigned int j = i - 16; j < i ; j++)
          {
            char c = data[j];
            stream << (isgraph(c) ? c : '.');
          }
          stream << '\n';
        }
      }

      while (i % 16 != 0) {
        stream << "  ";
        if (i % 2 == 0) stream << ' ';
        i++;
      }
      stream << ' ';

      for (unsigned int j = i - 16; j < buffer.size(); j++) {
        char c = data[j];
        stream << (c >= 0 && isgraph(c) ? c : '.'); // isgraph() required a value which can be represented by an unsigned char
      }

      stream.flags(flags);
    }
  }
} // !qi
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Copyright (c) 2017 Denise Härnström
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <modules/crystalvisualization/intvectorpropertywidgetqt.h>
#include <QLineEdit>

namespace inviwo {

IntVectorPropertyWidgetQt::IntVectorPropertyWidgetQt(IntVectorProperty* property)
    : PropertyWidgetQt(property)
    , property_(property){

    generateWidget();
    updateFromProperty();
}

void IntVectorPropertyWidgetQt::generateWidget() {
    label_ = new EditableLabelQt(this, property_, false);

    //widget layout
    QHBoxLayout* hLayout = new QHBoxLayout();
    setSpacingAndMargins(hLayout);
    hLayout->addWidget(label_);

    lineEdit_ = new QLineEdit();

    QSizePolicy sizePolicy(lineEdit_->sizePolicy());
    sizePolicy.setHorizontalStretch(3);
    sizePolicy.setVerticalPolicy(QSizePolicy::Fixed);
    lineEdit_->setSizePolicy(sizePolicy);

    lineEdit_->setReadOnly(true);
    hLayout->addWidget(lineEdit_);

    setLayout(hLayout);

}

void IntVectorPropertyWidgetQt::updateFromProperty() {
    if(lineEdit_) {
        lineEdit_->clear();
        QString text;
        for (const auto &ind : property_->get()) {
            text.append(QString::number(ind));
            text.append(", ");
        }
        text.chop(2);
        lineEdit_->insert(text);
    }

}

} // namespace
<commit_msg>Add missing include in crystalvisualization<commit_after>/*********************************************************************************
 *
 * Copyright (c) 2017 Denise Härnström
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <modules/crystalvisualization/intvectorpropertywidgetqt.h>
#include <QLineEdit>
#include <QHBoxLayout>

namespace inviwo {

IntVectorPropertyWidgetQt::IntVectorPropertyWidgetQt(IntVectorProperty* property)
    : PropertyWidgetQt(property)
    , property_(property){

    generateWidget();
    updateFromProperty();
}

void IntVectorPropertyWidgetQt::generateWidget() {
    label_ = new EditableLabelQt(this, property_, false);

    //widget layout
    QHBoxLayout* hLayout = new QHBoxLayout();
    setSpacingAndMargins(hLayout);
    hLayout->addWidget(label_);

    lineEdit_ = new QLineEdit();

    QSizePolicy sizePolicy(lineEdit_->sizePolicy());
    sizePolicy.setHorizontalStretch(3);
    sizePolicy.setVerticalPolicy(QSizePolicy::Fixed);
    lineEdit_->setSizePolicy(sizePolicy);

    lineEdit_->setReadOnly(true);
    hLayout->addWidget(lineEdit_);

    setLayout(hLayout);

}

void IntVectorPropertyWidgetQt::updateFromProperty() {
    if(lineEdit_) {
        lineEdit_->clear();
        QString text;
        for (const auto &ind : property_->get()) {
            text.append(QString::number(ind));
            text.append(", ");
        }
        text.chop(2);
        lineEdit_->insert(text);
    }

}

} // namespace
<|endoftext|>


<commit_before>/*
The OpenTRV project licenses this file to you
under the Apache Licence, Version 2.0 (the "Licence");
you may not use this file except in compliance
with the Licence. You may obtain a copy of the Licence at

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

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

Author(s) / Copyright (s): Damon Hart-Davis 2016
*/

/*
 * OTRadValve TempControl tests.
 */

#include <gtest/gtest.h>

#include "OTSIM900Link.h"

// Test for general sanity of OTSIM900Link.
// Make sure that an instance can be created and does not die horribly.
TEST(OTSIM900Link,basics)
{
    class NULLSerialStream final : public Stream
      {
      public:
        void begin(unsigned long) { }
        void begin(unsigned long, uint8_t);
        void end();

        virtual size_t write(uint8_t) override { return(0); }
        virtual int available() override { return(-1); }
        virtual int read() override { return(-1); }
        virtual int peek() override { return(-1); }
        virtual void flush() override { }
      };
    OTSIM900Link::OTSIM900Link<0, 0, 0, NULLSerialStream> l0;
    EXPECT_TRUE(l0.begin());
    EXPECT_EQ(OTSIM900Link::GET_STATE, l0._getState());
    // Try to hang just by calling poll() repeatedly.
    for(int i = 0; i < 1000; ++i) { l0.poll(); }
    EXPECT_GE(OTSIM900Link::START_UP, l0._getState()) << "should keep trying to start with GET_STATE, RETRY_GET_STATE and START_UP";
    // ...
    l0.end();
}

<commit_msg>TODO-1028: tests<commit_after>/*
The OpenTRV project licenses this file to you
under the Apache Licence, Version 2.0 (the "Licence");
you may not use this file except in compliance
with the Licence. You may obtain a copy of the Licence at

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

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

Author(s) / Copyright (s): Damon Hart-Davis 2016
*/

/*
 * OTRadValve TempControl tests.
 */

#include <gtest/gtest.h>
#include <stdio.h>

#include "OTSIM900Link.h"

// Test for general sanity of OTSIM900Link.
// Make sure that an instance can be created and does not die horribly.
// Underlying simulated serial/SIM900 never accepts data or responds, eg like a dead card.
TEST(OTSIM900Link,basicsDeadCard)
{
    const bool verbose = false;

    class NULLSerialStream final : public Stream
      {
      public:
        void begin(unsigned long) { }
        void begin(unsigned long, uint8_t);
        void end();

        virtual size_t write(uint8_t c) override { if(verbose) { fprintf(stderr, "%c\n", (char) c); } return(0); }
        virtual int available() override { return(-1); }
        virtual int read() override { return(-1); }
        virtual int peek() override { return(-1); }
        virtual void flush() override { }
      };
    OTSIM900Link::OTSIM900Link<0, 0, 0, NULLSerialStream> l0;
    EXPECT_TRUE(l0.begin());
    EXPECT_EQ(OTSIM900Link::GET_STATE, l0._getState());
    // Try to hang just by calling poll() repeatedly.
    for(int i = 0; i < 10000; ++i) { l0.poll(); }
    EXPECT_GE(OTSIM900Link::START_UP, l0._getState()) << "should keep trying to start with GET_STATE, RETRY_GET_STATE and START_UP";
    // ...
    l0.end();
}

// Test for general sanity of OTSIM900Link.
// Make sure that an instance can be created and does not die horribly.
// Underlying simulated serial/SIM900 accepts output, does not respond.
TEST(OTSIM900Link,basics)
{
    const bool verbose = true;

    class SerialStream final : public Stream
      {
      public:
        void begin(unsigned long) { }
        void begin(unsigned long, uint8_t);
        void end();

        virtual size_t write(uint8_t c) override { if(verbose) { fprintf(stderr, "%c\n", (char) c); } return(1); }
        virtual int available() override { return(-1); }
        virtual int read() override { return(-1); }
        virtual int peek() override { return(-1); }
        virtual void flush() override { }
      };
    OTSIM900Link::OTSIM900Link<0, 0, 0, SerialStream> l0;
    EXPECT_TRUE(l0.begin());
    EXPECT_EQ(OTSIM900Link::GET_STATE, l0._getState());
    // Try to hang just by calling poll() repeatedly.
    for(int i = 0; i < 10000; ++i) { l0.poll(); }
    EXPECT_GE(OTSIM900Link::START_UP, l0._getState()) << "should keep trying to start with GET_STATE, RETRY_GET_STATE and START_UP";
    // ...
    l0.end();
}

<|endoftext|>


<commit_before>//===- DWARFVerifier.cpp --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <set>
#include <vector>

using namespace llvm;
using namespace dwarf;
using namespace object;

void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
                                             DWARFAttribute &AttrValue) {
  const auto Attr = AttrValue.Attr;
  switch (Attr) {
  case DW_AT_ranges:
    // Make sure the offset in the DW_AT_ranges attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DCtx.getRangeSection().Data.size()) {
        ++NumDebugInfoErrors;
        OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
              "bounds:\n";
        Die.dump(OS, 0);
        OS << "\n";
      }
    } else {
      ++NumDebugInfoErrors;
      OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
      Die.dump(OS, 0);
      OS << "\n";
    }
    break;
  case DW_AT_stmt_list:
    // Make sure the offset in the DW_AT_stmt_list attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DCtx.getLineSection().Data.size()) {
        ++NumDebugInfoErrors;
        OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
              "bounds: "
           << format("0x%08" PRIx32, *SectionOffset) << "\n";
        Die.dump(OS, 0);
        OS << "\n";
      }
    } else {
      ++NumDebugInfoErrors;
      OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
      Die.dump(OS, 0);
      OS << "\n";
    }
    break;

  default:
    break;
  }
}

void DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
                                        DWARFAttribute &AttrValue) {
  const auto Form = AttrValue.Value.getForm();
  switch (Form) {
  case DW_FORM_ref1:
  case DW_FORM_ref2:
  case DW_FORM_ref4:
  case DW_FORM_ref8:
  case DW_FORM_ref_udata: {
    // Verify all CU relative references are valid CU offsets.
    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
    assert(RefVal);
    if (RefVal) {
      auto DieCU = Die.getDwarfUnit();
      auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
      auto CUOffset = AttrValue.Value.getRawUValue();
      if (CUOffset >= CUSize) {
        ++NumDebugInfoErrors;
        OS << "error: " << FormEncodingString(Form) << " CU offset "
           << format("0x%08" PRIx32, CUOffset)
           << " is invalid (must be less than CU size of "
           << format("0x%08" PRIx32, CUSize) << "):\n";
        Die.dump(OS, 0);
        OS << "\n";
      } else {
        // Valid reference, but we will verify it points to an actual
        // DIE later.
        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
      }
    }
    break;
  }
  case DW_FORM_ref_addr: {
    // Verify all absolute DIE references have valid offsets in the
    // .debug_info section.
    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
    assert(RefVal);
    if (RefVal) {
      if (*RefVal >= DCtx.getInfoSection().Data.size()) {
        ++NumDebugInfoErrors;
        OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
              "bounds:\n";
        Die.dump(OS, 0);
        OS << "\n";
      } else {
        // Valid reference, but we will verify it points to an actual
        // DIE later.
        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
      }
    }
    break;
  }
  case DW_FORM_strp: {
    auto SecOffset = AttrValue.Value.getAsSectionOffset();
    assert(SecOffset); // DW_FORM_strp is a section offset.
    if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) {
      ++NumDebugInfoErrors;
      OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
      Die.dump(OS, 0);
      OS << "\n";
    }
    break;
  }
  default:
    break;
  }
}

void DWARFVerifier::verifyDebugInfoReferences() {
  // Take all references and make sure they point to an actual DIE by
  // getting the DIE by offset and emitting an error
  OS << "Verifying .debug_info references...\n";
  for (auto Pair : ReferenceToDIEOffsets) {
    auto Die = DCtx.getDIEForOffset(Pair.first);
    if (Die)
      continue;
    ++NumDebugInfoErrors;
    OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
       << ". Offset is in between DIEs:\n";
    for (auto Offset : Pair.second) {
      auto ReferencingDie = DCtx.getDIEForOffset(Offset);
      ReferencingDie.dump(OS, 0);
      OS << "\n";
    }
    OS << "\n";
  }
}

bool DWARFVerifier::handleDebugInfo() {
  NumDebugInfoErrors = 0;
  OS << "Verifying .debug_info...\n";
  for (const auto &CU : DCtx.compile_units()) {
    unsigned NumDies = CU->getNumDIEs();
    for (unsigned I = 0; I < NumDies; ++I) {
      auto Die = CU->getDIEAtIndex(I);
      const auto Tag = Die.getTag();
      if (Tag == DW_TAG_null)
        continue;
      for (auto AttrValue : Die.attributes()) {
        verifyDebugInfoAttribute(Die, AttrValue);
        verifyDebugInfoForm(Die, AttrValue);
      }
    }
  }
  // FIXME: This introduced unexplained failures on buildbots (PR32972)
  //verifyDebugInfoReferences();
  return NumDebugInfoErrors == 0;
}

void DWARFVerifier::verifyDebugLineStmtOffsets() {
  std::map<uint64_t, DWARFDie> StmtListToDie;
  for (const auto &CU : DCtx.compile_units()) {
    auto Die = CU->getUnitDIE();
    // Get the attribute value as a section offset. No need to produce an
    // error here if the encoding isn't correct because we validate this in
    // the .debug_info verifier.
    auto StmtSectionOffset = toSectionOffset(Die.find(DW_AT_stmt_list));
    if (!StmtSectionOffset)
      continue;
    const uint32_t LineTableOffset = *StmtSectionOffset;
    auto LineTable = DCtx.getLineTableForUnit(CU.get());
    if (LineTableOffset < DCtx.getLineSection().Data.size()) {
      if (!LineTable) {
        ++NumDebugLineErrors;
        OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
           << "] was not able to be parsed for CU:\n";
        Die.dump(OS, 0);
        OS << '\n';
        continue;
      }
    } else {
      // Make sure we don't get a valid line table back if the offset is wrong.
      assert(LineTable == nullptr);
      // Skip this line table as it isn't valid. No need to create an error
      // here because we validate this in the .debug_info verifier.
      continue;
    }
    auto Iter = StmtListToDie.find(LineTableOffset);
    if (Iter != StmtListToDie.end()) {
      ++NumDebugLineErrors;
      OS << "error: two compile unit DIEs, "
         << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
         << format("0x%08" PRIx32, Die.getOffset())
         << ", have the same DW_AT_stmt_list section offset:\n";
      Iter->second.dump(OS, 0);
      Die.dump(OS, 0);
      OS << '\n';
      // Already verified this line table before, no need to do it again.
      continue;
    }
    StmtListToDie[LineTableOffset] = Die;
  }
}

void DWARFVerifier::verifyDebugLineRows() {
  for (const auto &CU : DCtx.compile_units()) {
    auto Die = CU->getUnitDIE();
    auto LineTable = DCtx.getLineTableForUnit(CU.get());
    // If there is no line table we will have created an error in the
    // .debug_info verifier or in verifyDebugLineStmtOffsets().
    if (!LineTable)
      continue;
    uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
    uint64_t PrevAddress = 0;
    uint32_t RowIndex = 0;
    for (const auto &Row : LineTable->Rows) {
      if (Row.Address < PrevAddress) {
        ++NumDebugLineErrors;
        OS << "error: .debug_line["
           << format("0x%08" PRIx32,
                     *toSectionOffset(Die.find(DW_AT_stmt_list)))
           << "] row[" << RowIndex
           << "] decreases in address from previous row:\n";

        DWARFDebugLine::Row::dumpTableHeader(OS);
        if (RowIndex > 0)
          LineTable->Rows[RowIndex - 1].dump(OS);
        Row.dump(OS);
        OS << '\n';
      }

      if (Row.File > MaxFileIndex) {
        ++NumDebugLineErrors;
        OS << "error: .debug_line["
           << format("0x%08" PRIx32,
                     *toSectionOffset(Die.find(DW_AT_stmt_list)))
           << "][" << RowIndex << "] has invalid file index " << Row.File
           << " (valid values are [1," << MaxFileIndex << "]):\n";
        DWARFDebugLine::Row::dumpTableHeader(OS);
        Row.dump(OS);
        OS << '\n';
      }
      if (Row.EndSequence)
        PrevAddress = 0;
      else
        PrevAddress = Row.Address;
      ++RowIndex;
    }
  }
}

bool DWARFVerifier::handleDebugLine() {
  NumDebugLineErrors = 0;
  OS << "Verifying .debug_line...\n";
  verifyDebugLineStmtOffsets();
  verifyDebugLineRows();
  return NumDebugLineErrors == 0;
}
<commit_msg>Revert "[Dwarf] Disable reference verification for now (PR32972)"<commit_after>//===- DWARFVerifier.cpp --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <set>
#include <vector>

using namespace llvm;
using namespace dwarf;
using namespace object;

void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
                                             DWARFAttribute &AttrValue) {
  const auto Attr = AttrValue.Attr;
  switch (Attr) {
  case DW_AT_ranges:
    // Make sure the offset in the DW_AT_ranges attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DCtx.getRangeSection().Data.size()) {
        ++NumDebugInfoErrors;
        OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
              "bounds:\n";
        Die.dump(OS, 0);
        OS << "\n";
      }
    } else {
      ++NumDebugInfoErrors;
      OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
      Die.dump(OS, 0);
      OS << "\n";
    }
    break;
  case DW_AT_stmt_list:
    // Make sure the offset in the DW_AT_stmt_list attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DCtx.getLineSection().Data.size()) {
        ++NumDebugInfoErrors;
        OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
              "bounds: "
           << format("0x%08" PRIx32, *SectionOffset) << "\n";
        Die.dump(OS, 0);
        OS << "\n";
      }
    } else {
      ++NumDebugInfoErrors;
      OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
      Die.dump(OS, 0);
      OS << "\n";
    }
    break;

  default:
    break;
  }
}

void DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
                                        DWARFAttribute &AttrValue) {
  const auto Form = AttrValue.Value.getForm();
  switch (Form) {
  case DW_FORM_ref1:
  case DW_FORM_ref2:
  case DW_FORM_ref4:
  case DW_FORM_ref8:
  case DW_FORM_ref_udata: {
    // Verify all CU relative references are valid CU offsets.
    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
    assert(RefVal);
    if (RefVal) {
      auto DieCU = Die.getDwarfUnit();
      auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
      auto CUOffset = AttrValue.Value.getRawUValue();
      if (CUOffset >= CUSize) {
        ++NumDebugInfoErrors;
        OS << "error: " << FormEncodingString(Form) << " CU offset "
           << format("0x%08" PRIx32, CUOffset)
           << " is invalid (must be less than CU size of "
           << format("0x%08" PRIx32, CUSize) << "):\n";
        Die.dump(OS, 0);
        OS << "\n";
      } else {
        // Valid reference, but we will verify it points to an actual
        // DIE later.
        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
      }
    }
    break;
  }
  case DW_FORM_ref_addr: {
    // Verify all absolute DIE references have valid offsets in the
    // .debug_info section.
    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
    assert(RefVal);
    if (RefVal) {
      if (*RefVal >= DCtx.getInfoSection().Data.size()) {
        ++NumDebugInfoErrors;
        OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
              "bounds:\n";
        Die.dump(OS, 0);
        OS << "\n";
      } else {
        // Valid reference, but we will verify it points to an actual
        // DIE later.
        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
      }
    }
    break;
  }
  case DW_FORM_strp: {
    auto SecOffset = AttrValue.Value.getAsSectionOffset();
    assert(SecOffset); // DW_FORM_strp is a section offset.
    if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) {
      ++NumDebugInfoErrors;
      OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
      Die.dump(OS, 0);
      OS << "\n";
    }
    break;
  }
  default:
    break;
  }
}

void DWARFVerifier::verifyDebugInfoReferences() {
  // Take all references and make sure they point to an actual DIE by
  // getting the DIE by offset and emitting an error
  OS << "Verifying .debug_info references...\n";
  for (auto Pair : ReferenceToDIEOffsets) {
    auto Die = DCtx.getDIEForOffset(Pair.first);
    if (Die)
      continue;
    ++NumDebugInfoErrors;
    OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
       << ". Offset is in between DIEs:\n";
    for (auto Offset : Pair.second) {
      auto ReferencingDie = DCtx.getDIEForOffset(Offset);
      ReferencingDie.dump(OS, 0);
      OS << "\n";
    }
    OS << "\n";
  }
}

bool DWARFVerifier::handleDebugInfo() {
  NumDebugInfoErrors = 0;
  OS << "Verifying .debug_info...\n";
  for (const auto &CU : DCtx.compile_units()) {
    unsigned NumDies = CU->getNumDIEs();
    for (unsigned I = 0; I < NumDies; ++I) {
      auto Die = CU->getDIEAtIndex(I);
      const auto Tag = Die.getTag();
      if (Tag == DW_TAG_null)
        continue;
      for (auto AttrValue : Die.attributes()) {
        verifyDebugInfoAttribute(Die, AttrValue);
        verifyDebugInfoForm(Die, AttrValue);
      }
    }
  }
  verifyDebugInfoReferences();
  return NumDebugInfoErrors == 0;
}

void DWARFVerifier::verifyDebugLineStmtOffsets() {
  std::map<uint64_t, DWARFDie> StmtListToDie;
  for (const auto &CU : DCtx.compile_units()) {
    auto Die = CU->getUnitDIE();
    // Get the attribute value as a section offset. No need to produce an
    // error here if the encoding isn't correct because we validate this in
    // the .debug_info verifier.
    auto StmtSectionOffset = toSectionOffset(Die.find(DW_AT_stmt_list));
    if (!StmtSectionOffset)
      continue;
    const uint32_t LineTableOffset = *StmtSectionOffset;
    auto LineTable = DCtx.getLineTableForUnit(CU.get());
    if (LineTableOffset < DCtx.getLineSection().Data.size()) {
      if (!LineTable) {
        ++NumDebugLineErrors;
        OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
           << "] was not able to be parsed for CU:\n";
        Die.dump(OS, 0);
        OS << '\n';
        continue;
      }
    } else {
      // Make sure we don't get a valid line table back if the offset is wrong.
      assert(LineTable == nullptr);
      // Skip this line table as it isn't valid. No need to create an error
      // here because we validate this in the .debug_info verifier.
      continue;
    }
    auto Iter = StmtListToDie.find(LineTableOffset);
    if (Iter != StmtListToDie.end()) {
      ++NumDebugLineErrors;
      OS << "error: two compile unit DIEs, "
         << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
         << format("0x%08" PRIx32, Die.getOffset())
         << ", have the same DW_AT_stmt_list section offset:\n";
      Iter->second.dump(OS, 0);
      Die.dump(OS, 0);
      OS << '\n';
      // Already verified this line table before, no need to do it again.
      continue;
    }
    StmtListToDie[LineTableOffset] = Die;
  }
}

void DWARFVerifier::verifyDebugLineRows() {
  for (const auto &CU : DCtx.compile_units()) {
    auto Die = CU->getUnitDIE();
    auto LineTable = DCtx.getLineTableForUnit(CU.get());
    // If there is no line table we will have created an error in the
    // .debug_info verifier or in verifyDebugLineStmtOffsets().
    if (!LineTable)
      continue;
    uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
    uint64_t PrevAddress = 0;
    uint32_t RowIndex = 0;
    for (const auto &Row : LineTable->Rows) {
      if (Row.Address < PrevAddress) {
        ++NumDebugLineErrors;
        OS << "error: .debug_line["
           << format("0x%08" PRIx32,
                     *toSectionOffset(Die.find(DW_AT_stmt_list)))
           << "] row[" << RowIndex
           << "] decreases in address from previous row:\n";

        DWARFDebugLine::Row::dumpTableHeader(OS);
        if (RowIndex > 0)
          LineTable->Rows[RowIndex - 1].dump(OS);
        Row.dump(OS);
        OS << '\n';
      }

      if (Row.File > MaxFileIndex) {
        ++NumDebugLineErrors;
        OS << "error: .debug_line["
           << format("0x%08" PRIx32,
                     *toSectionOffset(Die.find(DW_AT_stmt_list)))
           << "][" << RowIndex << "] has invalid file index " << Row.File
           << " (valid values are [1," << MaxFileIndex << "]):\n";
        DWARFDebugLine::Row::dumpTableHeader(OS);
        Row.dump(OS);
        OS << '\n';
      }
      if (Row.EndSequence)
        PrevAddress = 0;
      else
        PrevAddress = Row.Address;
      ++RowIndex;
    }
  }
}

bool DWARFVerifier::handleDebugLine() {
  NumDebugLineErrors = 0;
  OS << "Verifying .debug_line...\n";
  verifyDebugLineStmtOffsets();
  verifyDebugLineRows();
  return NumDebugLineErrors == 0;
}
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>

*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// 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.

// Internal Includes
#include <osvr/PluginKit/EyeTrackerInterfaceC.h>
#include <osvr/Connection/DeviceInitObject.h>
#include <osvr/Connection/DeviceToken.h>
#include <osvr/PluginHost/PluginSpecificRegistrationContext.h>
#include <osvr/Util/PointerWrapper.h>
#include "HandleNullContext.h"
#include <osvr/Util/Verbosity.h>
#include <osvr/Common/EyeTrackerComponent.h>
#include <osvr/Common/Location2DComponent.h>
#include <osvr/Common/DirectionComponent.h>
#include <osvr/Connection/TrackerServerInterface.h>
#include <osvr/Connection/ButtonServerInterface.h>
#include <osvr/Connection/DeviceInterfaceBase.h>

// Library/third-party includes
// - none

// Standard includes
// - none

using osvr::util::PointerWrapper;

struct OSVR_EyeTrackerDeviceInterfaceObject
    : public osvr::connection::DeviceInterfaceBase {
    osvr::common::EyeTrackerComponent *eyetracker;
    osvr::common::Location2DComponent *location;
    osvr::common::DirectionComponent *direction;
    PointerWrapper<osvr::connection::ButtonServerInterface> button;
    PointerWrapper<osvr::connection::TrackerServerInterface> tracker;
};

OSVR_ReturnCode osvrDeviceEyeTrackerConfigure(
    OSVR_INOUT_PTR OSVR_DeviceInitOptions opts,
    OSVR_OUT_PTR OSVR_EyeTrackerDeviceInterface *iface,
    OSVR_IN OSVR_ChannelCount numChan) {

    OSVR_PLUGIN_HANDLE_NULL_CONTEXT("osvrDeviceEyeTrackerConfigure", opts);
    OSVR_PLUGIN_HANDLE_NULL_CONTEXT("osvrDeviceEyeTrackerConfigure", iface);
    auto ifaceObj = opts->getContext()->registerDataWithGenericDelete(
        new OSVR_EyeTrackerDeviceInterfaceObject);
    *iface = ifaceObj;

    auto location = osvr::common::Location2DComponent::create();
    ifaceObj->location = location.get();
    opts->addComponent(location);

    auto direction = osvr::common::DirectionComponent::create();
    ifaceObj->direction = direction.get();
    opts->addComponent(direction);

    auto eyetracker = osvr::common::EyeTrackerComponent::create();
    ifaceObj->eyetracker = eyetracker.get();
    opts->addComponent(eyetracker);

    opts->setButtons(numChan, ifaceObj->button.getContainerLocation());
    opts->setTracker(ifaceObj->tracker.getContainerLocation());
    opts->addTokenInterest(ifaceObj);

    return OSVR_RETURN_SUCCESS;
}

OSVR_ReturnCode osvrDeviceEyeTrackerReport2DGaze(
    OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
    OSVR_IN OSVR_EyeGazePosition2DState gazePosition,
    OSVR_IN OSVR_ChannelCount sensor,
    OSVR_IN_PTR OSVR_TimeValue const *timestamp) {

    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->location->sendLocationData(gazePosition, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
        return OSVR_RETURN_SUCCESS;
    }

    return OSVR_RETURN_FAILURE;
}

OSVR_ReturnCode osvrDeviceEyeTrackerReport3DGaze(
    OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
    OSVR_IN OSVR_EyeGazeDirectionState gazeDirection,
    OSVR_IN OSVR_EyeGazeBasePoint3DState gazeBasePoint,
    OSVR_IN OSVR_ChannelCount sensor,
    OSVR_IN_PTR OSVR_TimeValue const *timestamp) {
    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->direction->sendDirectionData(gazeDirection, sensor, *timestamp);
        iface->tracker->sendReport(gazeBasePoint, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
        return OSVR_RETURN_SUCCESS;
    }

    return OSVR_RETURN_FAILURE;
}

OSVR_ReturnCode osvrDeviceEyeTrackerReport3DGazeDirection(
    OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
    OSVR_IN OSVR_EyeGazeDirectionState gazeDirection,
    OSVR_IN OSVR_ChannelCount sensor,
    OSVR_IN_PTR OSVR_TimeValue const *timestamp) {

    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->direction->sendDirectionData(gazeDirection, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
        return OSVR_RETURN_SUCCESS;
    }

    return OSVR_RETURN_FAILURE;
}

OSVR_ReturnCode
osvrDeviceEyeTrackerReportGaze(OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
                               OSVR_IN OSVR_EyeGazePosition2DState gazePosition,
                               OSVR_IN OSVR_EyeGazeDirectionState gazeDirection,
                               OSVR_IN OSVR_EyeGazeBasePoint3DState
                                   gazeBasePoint,
                               OSVR_IN OSVR_ChannelCount sensor,
                               OSVR_IN_PTR OSVR_TimeValue const *timestamp) {

    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->location->sendLocationData(gazePosition, sensor, *timestamp);
        iface->tracker->sendReport(gazeBasePoint, sensor, *timestamp);
        iface->direction->sendDirectionData(gazeDirection, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
        return OSVR_RETURN_SUCCESS;
    }

    return OSVR_RETURN_FAILURE;
}

OSVR_ReturnCode osvrDeviceEyeTrackerReportBlink(
    OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
    OSVR_IN OSVR_EyeTrackerBlinkState blink, OSVR_IN OSVR_ChannelCount sensor,
    OSVR_IN_PTR OSVR_TimeValue const *timestamp) {

    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->button->setValue(blink, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
    }
    return OSVR_RETURN_SUCCESS;
}
<commit_msg>Use the simplified API in EyeTrackerInterface<commit_after>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>

*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// 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.

// Internal Includes
#include <osvr/PluginKit/EyeTrackerInterfaceC.h>
#include <osvr/Connection/DeviceInitObject.h>
#include <osvr/Connection/DeviceToken.h>
#include <osvr/PluginHost/PluginSpecificRegistrationContext.h>
#include <osvr/Util/PointerWrapper.h>
#include "HandleNullContext.h"
#include <osvr/Util/Verbosity.h>
#include <osvr/Common/EyeTrackerComponent.h>
#include <osvr/Common/Location2DComponent.h>
#include <osvr/Common/DirectionComponent.h>
#include <osvr/Connection/TrackerServerInterface.h>
#include <osvr/Connection/ButtonServerInterface.h>
#include <osvr/Connection/DeviceInterfaceBase.h>

// Library/third-party includes
// - none

// Standard includes
// - none

using osvr::util::PointerWrapper;

struct OSVR_EyeTrackerDeviceInterfaceObject
    : public osvr::connection::DeviceInterfaceBase {
    osvr::common::EyeTrackerComponent *eyetracker;
    osvr::common::Location2DComponent *location;
    osvr::common::DirectionComponent *direction;
    PointerWrapper<osvr::connection::ButtonServerInterface> button;
    PointerWrapper<osvr::connection::TrackerServerInterface> tracker;
};

OSVR_ReturnCode osvrDeviceEyeTrackerConfigure(
    OSVR_INOUT_PTR OSVR_DeviceInitOptions opts,
    OSVR_OUT_PTR OSVR_EyeTrackerDeviceInterface *iface,
    OSVR_IN OSVR_ChannelCount numChan) {

    OSVR_PLUGIN_HANDLE_NULL_CONTEXT("osvrDeviceEyeTrackerConfigure", opts);
    OSVR_PLUGIN_HANDLE_NULL_CONTEXT("osvrDeviceEyeTrackerConfigure", iface);
    auto ifaceObj =
        opts->makeInterfaceObject<OSVR_EyeTrackerDeviceInterfaceObject>();
    *iface = ifaceObj;

    auto location = osvr::common::Location2DComponent::create();
    ifaceObj->location = location.get();
    opts->addComponent(location);

    auto direction = osvr::common::DirectionComponent::create();
    ifaceObj->direction = direction.get();
    opts->addComponent(direction);

    auto eyetracker = osvr::common::EyeTrackerComponent::create();
    ifaceObj->eyetracker = eyetracker.get();
    opts->addComponent(eyetracker);

    opts->setButtons(numChan, ifaceObj->button.getContainerLocation());
    opts->setTracker(ifaceObj->tracker.getContainerLocation());

    return OSVR_RETURN_SUCCESS;
}

OSVR_ReturnCode osvrDeviceEyeTrackerReport2DGaze(
    OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
    OSVR_IN OSVR_EyeGazePosition2DState gazePosition,
    OSVR_IN OSVR_ChannelCount sensor,
    OSVR_IN_PTR OSVR_TimeValue const *timestamp) {

    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->location->sendLocationData(gazePosition, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
        return OSVR_RETURN_SUCCESS;
    }

    return OSVR_RETURN_FAILURE;
}

OSVR_ReturnCode osvrDeviceEyeTrackerReport3DGaze(
    OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
    OSVR_IN OSVR_EyeGazeDirectionState gazeDirection,
    OSVR_IN OSVR_EyeGazeBasePoint3DState gazeBasePoint,
    OSVR_IN OSVR_ChannelCount sensor,
    OSVR_IN_PTR OSVR_TimeValue const *timestamp) {
    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->direction->sendDirectionData(gazeDirection, sensor, *timestamp);
        iface->tracker->sendReport(gazeBasePoint, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
        return OSVR_RETURN_SUCCESS;
    }

    return OSVR_RETURN_FAILURE;
}

OSVR_ReturnCode osvrDeviceEyeTrackerReport3DGazeDirection(
    OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
    OSVR_IN OSVR_EyeGazeDirectionState gazeDirection,
    OSVR_IN OSVR_ChannelCount sensor,
    OSVR_IN_PTR OSVR_TimeValue const *timestamp) {

    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->direction->sendDirectionData(gazeDirection, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
        return OSVR_RETURN_SUCCESS;
    }

    return OSVR_RETURN_FAILURE;
}

OSVR_ReturnCode
osvrDeviceEyeTrackerReportGaze(OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
                               OSVR_IN OSVR_EyeGazePosition2DState gazePosition,
                               OSVR_IN OSVR_EyeGazeDirectionState gazeDirection,
                               OSVR_IN OSVR_EyeGazeBasePoint3DState
                                   gazeBasePoint,
                               OSVR_IN OSVR_ChannelCount sensor,
                               OSVR_IN_PTR OSVR_TimeValue const *timestamp) {

    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->location->sendLocationData(gazePosition, sensor, *timestamp);
        iface->tracker->sendReport(gazeBasePoint, sensor, *timestamp);
        iface->direction->sendDirectionData(gazeDirection, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
        return OSVR_RETURN_SUCCESS;
    }

    return OSVR_RETURN_FAILURE;
}

OSVR_ReturnCode osvrDeviceEyeTrackerReportBlink(
    OSVR_IN_PTR OSVR_EyeTrackerDeviceInterface iface,
    OSVR_IN OSVR_EyeTrackerBlinkState blink, OSVR_IN OSVR_ChannelCount sensor,
    OSVR_IN_PTR OSVR_TimeValue const *timestamp) {

    auto guard = iface->getSendGuard();
    if (guard->lock()) {
        iface->button->setValue(blink, sensor, *timestamp);
        iface->eyetracker->sendNotification(sensor, *timestamp);
    }
    return OSVR_RETURN_SUCCESS;
}
<|endoftext|>


<commit_before><commit_msg>BUG: missing include<commit_after><|endoftext|>


<commit_before>//===-- Intercept.cpp - System function interception routines -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// If a function call occurs to an external function, the JIT is designed to use
// the dynamic loader interface to find a function to call.  This is useful for
// calling system calls and library functions that are not available in LLVM.
// Some system calls, however, need to be handled specially.  For this reason,
// we intercept some of them here and use our own stubs to handle them.
//
//===----------------------------------------------------------------------===//

#include "JIT.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Config/config.h"
#include <iostream>
using namespace llvm;

// AtExitHandlers - List of functions to call when the program exits,
// registered with the atexit() library function.
static std::vector<void (*)()> AtExitHandlers;

/// runAtExitHandlers - Run any functions registered by the program's
/// calls to atexit(3), which we intercept and store in
/// AtExitHandlers.
///
static void runAtExitHandlers() {
  while (!AtExitHandlers.empty()) {
    void (*Fn)() = AtExitHandlers.back();
    AtExitHandlers.pop_back();
    Fn();
  }
}

//===----------------------------------------------------------------------===//
// Function stubs that are invoked instead of certain library calls
//===----------------------------------------------------------------------===//

// Force the following functions to be linked in to anything that uses the
// JIT. This is a hack designed to work around the all-too-clever Glibc
// strategy of making these functions work differently when inlined vs. when
// not inlined, and hiding their real definitions in a separate archive file
// that the dynamic linker can't see. For more info, search for
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
#if defined(__linux__)
#if defined(HAVE_SYS_STAT_H)
#include <sys/stat.h>
#endif
void *FunctionPointers[] = {
  (void *) stat,
  (void *) fstat,
  (void *) lstat,
  (void *) stat64,
  (void *) fstat64,
  (void *) lstat64,
  (void *) atexit,
  (void *) mknod
};
#endif // __linux__

// __mainFunc - If the program does not have a linked in __main function, allow
// it to run, but print a warning.
static void __mainFunc() {
  fprintf(stderr, "WARNING: Program called __main but was not linked to "
          "libcrtend.a.\nThis probably won't hurt anything unless the "
          "program is written in C++.\n");
}

// jit_exit - Used to intercept the "exit" library call.
static void jit_exit(int Status) {
  runAtExitHandlers();   // Run atexit handlers...
  exit(Status);
}

// jit_atexit - Used to intercept the "atexit" library call.
static int jit_atexit(void (*Fn)(void)) {
  AtExitHandlers.push_back(Fn);    // Take note of atexit handler...
  return 0;  // Always successful
}

//===----------------------------------------------------------------------===//
//
/// getPointerToNamedFunction - This method returns the address of the specified
/// function by using the dynamic loader interface.  As such it is only useful
/// for resolving library symbols, not code generated symbols.
///
void *JIT::getPointerToNamedFunction(const std::string &Name) {
  // Check to see if this is one of the functions we want to intercept...
  if (Name == "exit") return (void*)&jit_exit;
  if (Name == "atexit") return (void*)&jit_atexit;

  // If the program does not have a linked in __main function, allow it to run,
  // but print a warning.
  if (Name == "__main") return (void*)&__mainFunc;

  // If it's an external function, look it up in the process image...
  void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(Name);
  if (Ptr) return Ptr;

  std::cerr << "ERROR: Program used external function '" << Name
            << "' which could not be resolved!\n";
  abort();
  return 0;
}
<commit_msg>Silence some -pedantic warnings.<commit_after>//===-- Intercept.cpp - System function interception routines -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// If a function call occurs to an external function, the JIT is designed to use
// the dynamic loader interface to find a function to call.  This is useful for
// calling system calls and library functions that are not available in LLVM.
// Some system calls, however, need to be handled specially.  For this reason,
// we intercept some of them here and use our own stubs to handle them.
//
//===----------------------------------------------------------------------===//

#include "JIT.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Config/config.h"
#include <iostream>
using namespace llvm;

// AtExitHandlers - List of functions to call when the program exits,
// registered with the atexit() library function.
static std::vector<void (*)()> AtExitHandlers;

/// runAtExitHandlers - Run any functions registered by the program's
/// calls to atexit(3), which we intercept and store in
/// AtExitHandlers.
///
static void runAtExitHandlers() {
  while (!AtExitHandlers.empty()) {
    void (*Fn)() = AtExitHandlers.back();
    AtExitHandlers.pop_back();
    Fn();
  }
}

//===----------------------------------------------------------------------===//
// Function stubs that are invoked instead of certain library calls
//===----------------------------------------------------------------------===//

// Force the following functions to be linked in to anything that uses the
// JIT. This is a hack designed to work around the all-too-clever Glibc
// strategy of making these functions work differently when inlined vs. when
// not inlined, and hiding their real definitions in a separate archive file
// that the dynamic linker can't see. For more info, search for
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
#if defined(__linux__)
#if defined(HAVE_SYS_STAT_H)
#include <sys/stat.h>
#endif
void *FunctionPointers[] = {
  (void *) stat,
  (void *) fstat,
  (void *) lstat,
  (void *) stat64,
  (void *) fstat64,
  (void *) lstat64,
  (void *) atexit,
  (void *) mknod
};
#endif // __linux__

// __mainFunc - If the program does not have a linked in __main function, allow
// it to run, but print a warning.
static void __mainFunc() {
  fprintf(stderr, "WARNING: Program called __main but was not linked to "
          "libcrtend.a.\nThis probably won't hurt anything unless the "
          "program is written in C++.\n");
}

// jit_exit - Used to intercept the "exit" library call.
static void jit_exit(int Status) {
  runAtExitHandlers();   // Run atexit handlers...
  exit(Status);
}

// jit_atexit - Used to intercept the "atexit" library call.
static int jit_atexit(void (*Fn)(void)) {
  AtExitHandlers.push_back(Fn);    // Take note of atexit handler...
  return 0;  // Always successful
}

//===----------------------------------------------------------------------===//
//
/// getPointerToNamedFunction - This method returns the address of the specified
/// function by using the dynamic loader interface.  As such it is only useful
/// for resolving library symbols, not code generated symbols.
///
void *JIT::getPointerToNamedFunction(const std::string &Name) {
  // Check to see if this is one of the functions we want to intercept.  Note,
  // we cast to intptr_t here to silence a -pedantic warning that complains
  // about casting a function pointer to a normal pointer.
  if (Name == "exit") return (void*)(intptr_t)&jit_exit;
  if (Name == "atexit") return (void*)(intptr_t)&jit_atexit;

  // If the program does not have a linked in __main function, allow it to run,
  // but print a warning.
  if (Name == "__main") return (void*)(intptr_t)&__mainFunc;

  // If it's an external function, look it up in the process image...
  void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(Name);
  if (Ptr) return Ptr;

  std::cerr << "ERROR: Program used external function '" << Name
            << "' which could not be resolved!\n";
  abort();
  return 0;
}
<|endoftext|>