<commit_before>/*
 * Copyright (c) 2015 Intel Corporation.  All rights reserved.
 *
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "BleCharacteristic.h"

#include "internal/ble_client.h"

#define BLE_CCCD_DESCRIPTOR_UUID 0x2092

#define BLE_CCCD_NOTIFY_EN_MASK   0x1
#define BLE_CCCD_INDICATE_EN_MASK 0x2

/* Each characteristic has a Client Characteristic Configuration Descriptor (CCCD)
 * This callback is invoked whenever the CCCD for a given characteristic is updated
 * by a remote client to enable/disable receipt of notifications/indications
 */
void
_cccdEventHandler(BleDescriptor &cccd, BleDescriptorEvent event, void *arg)
{
    if (BLE_DESC_EVENT_WRITE == event) {
        BleStatus status;
        uint16_t cccdVal;
        BleCharacteristic *ch = (BleCharacteristic *)arg;

        status = cccd.getValue(cccdVal);
        if (BLE_STATUS_SUCCESS != status)
            return;

        ch->_notifyEnabled = (cccdVal & BLE_CCCD_NOTIFY_EN_MASK) ? true : false;
        ch->_indicateEnabled = (cccdVal & BLE_CCCD_INDICATE_EN_MASK) ? true : false;
    }
}

BleCharacteristic::BleCharacteristic(const uint16_t maxLength,
                                     const BleClientAccessMode clientAccess,
                                     const BleClientNotifyMode clientNotify)
    : _cccd(BLE_CCCD_DESCRIPTOR_UUID, sizeof(uint16_t), BLE_CLIENT_ACCESS_READ_WRITE)
{
    _initialised = false;
    _connected = false;
    _notifyEnabled = false;
    _indicateEnabled = false;

    _data_len = 0;
    _data[0] = 0;

    _clientAccess = clientAccess;
    _clientNotify = clientNotify;

    memset(&_char_data, 0, sizeof(_char_data));

    _char_data.p_uuid = &_uuid;

    if ((_clientAccess == BLE_CLIENT_ACCESS_READ_ONLY) ||
        (_clientAccess == BLE_CLIENT_ACCESS_READ_WRITE)) {
        _char_data.perms.rd = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1;
        _char_data.props.props |= BLE_GATT_CHAR_PROP_BIT_READ;

        /* Enable notifications only if characteristic is also readable by client */
        if (_clientNotify == BLE_CLIENT_NOTIFY_ENABLED)
            _char_data.props.props |= BLE_GATT_CHAR_PROP_BIT_NOTIFY;
        else if (_clientNotify == BLE_CLIENT_NOTIFY_WITH_ACK)
            _char_data.props.props |= BLE_GATT_CHAR_PROP_BIT_INDICATE;
    }
    else {
        _char_data.perms.rd = GAP_SEC_NO_PERMISSION;
    }

    if ((_clientAccess == BLE_CLIENT_ACCESS_WRITE_ONLY) ||
        (_clientAccess == BLE_CLIENT_ACCESS_READ_WRITE)) {
        _char_data.perms.wr = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1;
        _char_data.props.props |= (BLE_GATT_CHAR_PROP_BIT_WRITE | BLE_GATT_CHAR_PROP_BIT_WRITE_NR);
    }
    else {
        _char_data.perms.wr = GAP_SEC_NO_PERMISSION;
    }

    _char_data.init_len = _data_len;
    _char_data.max_len = maxLength > BLE_MAX_ATTR_DATA_LEN ? BLE_MAX_ATTR_DATA_LEN : maxLength;
    _char_data.p_value = _data;
}

BleCharacteristic::BleCharacteristic(const uint16_t uuid16,
                                     const uint16_t maxLength,
                                     const BleClientAccessMode clientAccess,
                                     const BleClientNotifyMode clientNotify)
    : BleCharacteristic(maxLength, clientAccess, clientNotify)
{
    _uuid.type = BT_UUID16;
    _uuid.uuid16 = uuid16;
}

BleCharacteristic::BleCharacteristic(const uint8_t uuid128[],
                                     const uint16_t maxLength,
                                     const BleClientAccessMode clientAccess,
                                     const BleClientNotifyMode clientNotify)
    : BleCharacteristic(maxLength, clientAccess, clientNotify)
{
    _uuid.type = BT_UUID128;
    memcpy(&_uuid.uuid128, uuid128, MAX_UUID_SIZE);
}

BleStatus
BleCharacteristic::addUserDescription(const char *description)
{
    if (_initialised)
        return BLE_STATUS_WRONG_STATE;

    if (description && description[0]) {
        _user_desc.len = strlen(description);
        if (_user_desc.len > sizeof(_user_desc_data))
            _user_desc.len = sizeof(_user_desc_data);
        memset(_user_desc_data, 0, sizeof(_user_desc_data));
        memcpy(_user_desc_data, description, _user_desc.len);
        _user_desc.buffer = _user_desc_data;

        _char_data.p_user_desc = &_user_desc;
    }

    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::addPresentationFormat(const uint8_t  format,
                                         const int8_t   exponent,
                                         const uint16_t unit,
                                         const uint8_t  nameSpace,
                                         const uint16_t description)
{
    if (_initialised)
        return BLE_STATUS_WRONG_STATE;

    _pf_desc.format = format;
    _pf_desc.exp = exponent;
    _pf_desc.unit = unit;
    _pf_desc.name_spc = nameSpace;
    _pf_desc.descr = description;

    _char_data.p_char_pf_desc = &_pf_desc;

    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::_setValue(void)
{
    BleStatus status;

    if (!_initialised)
        return BLE_STATUS_WRONG_STATE;

    status = ble_client_gatts_set_attribute_value(_handles.value_handle,
                                                  _data_len, _data, 0);
    if (BLE_STATUS_SUCCESS != status)
        return status;

    if (_notifyEnabled || _indicateEnabled) {
        status = ble_client_gatts_send_notif_ind(_handles.value_handle, _data_len, _data, 0, _indicateEnabled);
        if (BLE_STATUS_SUCCESS != status)
            return status;

        if (_indicateEnabled && _event_cb)
            _event_cb(*this, BLE_CHAR_EVENT_INDICATION_ACK, _event_cb_arg);
    }

    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::setValue(const uint8_t value[], const uint16_t length)
{
    if (!value)
        return BLE_STATUS_NOT_ALLOWED;
    if (length > _char_data.max_len)
        return BLE_STATUS_NOT_ALLOWED;

    /* Cache the value locally */
    memcpy(_data, value, length);
    _data_len = length;

    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const String &str)
{
    str.getBytes((unsigned char *)&_data, (unsigned int)_char_data.max_len, 0U);
    _data_len = str.len + 1;
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const char *cstr)
{
    return setValue((uint8_t *)cstr, (uint16_t) (strlen(cstr) + 1));
}

BleStatus
BleCharacteristic::setValue(const char &value)
{
    uint8_t *p = _data;
    INT8_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const unsigned char &value)
{
    uint8_t *p = _data;
    UINT8_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const short &value)
{
    uint8_t *p = _data;
    INT16_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const unsigned short &value)
{
    uint8_t *p = _data;
    UINT16_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const int &value)
{
    uint8_t *p = _data;
    INT32_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const unsigned int &value)
{
    uint8_t *p = _data;
    UINT32_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const long &value)
{
    uint8_t *p = _data;
    INT32_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const unsigned long &value)
{
    uint8_t *p = _data;
    UINT32_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::getValue(uint8_t value[], uint16_t &length) const
{
    if (!_initialised)
        return BLE_STATUS_WRONG_STATE;

    memcpy(value, _data, _data_len);
    length = _data_len;

    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(String &str) const
{
    str = (char *)_data;
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(char *cstr) const
{
    memcpy(cstr, _data, _data_len);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(char &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_INT8(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(unsigned char &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_UINT8(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(short &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_INT16(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(unsigned short &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_UINT16(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(int &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_INT32(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(unsigned int &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_UINT32(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(long &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_INT32(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(unsigned long &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_UINT32(p, value);
    return BLE_STATUS_SUCCESS;
}

void
BleCharacteristic::setEventCallback(BleCharacteristicEventCb callback,
                                    void *arg)
{
    noInterrupts();
    _event_cb = callback; /* callback disabled if NULL */
    _event_cb_arg = arg;
    interrupts();
}

BleStatus
BleCharacteristic::addDescriptor(BleDescriptor &descriptor)
{
    BleStatus status;

    if (!_initialised)
        return BLE_STATUS_WRONG_STATE;
    if (_num_descriptors >= BLE_MAX_DESCRIPTORS)
        return BLE_STATUS_ERROR;

    /* If this service has a 128-bit UUID, it shall be inherited
     * by included services, characteristics, and descriptors
     */
    if ((BT_UUID128 == _uuid.type) && (BT_UUID16 == descriptor._uuid.type))
        BLE_UUID16_TO_UUID128(descriptor._uuid, _uuid);

    status = ble_client_gatts_add_descriptor(_svc_handle,
                                             &descriptor._desc,
                                             &descriptor._handle);
    if (BLE_STATUS_SUCCESS == status) {
        descriptor._initialised = true;
        _descriptors[_num_descriptors++] = &descriptor;
    }

    return status;
}

BleDescriptor *
BleCharacteristic::_matchDescriptor(uint16_t handle) const
{
    for (unsigned i = 0; i < _num_descriptors; i++) {
        BleDescriptor *desc = _descriptors[i];
        if (handle == desc->_handle)
            return desc;
    }

    return NULL;
}

void
BleCharacteristic::_addCCCDescriptor(void)
{
    /* Activate our CCCD descriptor object */
    _cccd._handle = _handles.cccd_handle;
    _cccd._initialised = true;
    _cccd.setEventCallback(_cccdEventHandler, (void *)this);
    _descriptors[_num_descriptors++] = &_cccd;
}

void
BleCharacteristic::_setConnectedState(boolean_t connected)
{
    _connected = connected;

    /* Reset the state of these internal variables when connection is dropped */
    if (!connected) {
        _notifyEnabled = false;
        _indicateEnabled = false;
    }

    /* Cascade the connected-state update to descriptors */
    for (unsigned i = 0; i < _num_descriptors; i++)
        _descriptors[i]->_setConnectedState(connected);
}
<commit_msg>Fix Klocwork#2051,2060: Array may be outside index<commit_after>/*
 * Copyright (c) 2015 Intel Corporation.  All rights reserved.
 *
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "BleCharacteristic.h"

#include "internal/ble_client.h"

#define BLE_CCCD_DESCRIPTOR_UUID 0x2092

#define BLE_CCCD_NOTIFY_EN_MASK   0x1
#define BLE_CCCD_INDICATE_EN_MASK 0x2

/* Each characteristic has a Client Characteristic Configuration Descriptor (CCCD)
 * This callback is invoked whenever the CCCD for a given characteristic is updated
 * by a remote client to enable/disable receipt of notifications/indications
 */
void
_cccdEventHandler(BleDescriptor &cccd, BleDescriptorEvent event, void *arg)
{
    if (BLE_DESC_EVENT_WRITE == event) {
        BleStatus status;
        uint16_t cccdVal;
        BleCharacteristic *ch = (BleCharacteristic *)arg;

        status = cccd.getValue(cccdVal);
        if (BLE_STATUS_SUCCESS != status)
            return;

        ch->_notifyEnabled = (cccdVal & BLE_CCCD_NOTIFY_EN_MASK) ? true : false;
        ch->_indicateEnabled = (cccdVal & BLE_CCCD_INDICATE_EN_MASK) ? true : false;
    }
}

BleCharacteristic::BleCharacteristic(const uint16_t maxLength,
                                     const BleClientAccessMode clientAccess,
                                     const BleClientNotifyMode clientNotify)
    : _cccd(BLE_CCCD_DESCRIPTOR_UUID, sizeof(uint16_t), BLE_CLIENT_ACCESS_READ_WRITE)
{
    _initialised = false;
    _connected = false;
    _notifyEnabled = false;
    _indicateEnabled = false;

    _data_len = 0;
    _data[0] = 0;

    _clientAccess = clientAccess;
    _clientNotify = clientNotify;

    memset(&_char_data, 0, sizeof(_char_data));

    _char_data.p_uuid = &_uuid;

    if ((_clientAccess == BLE_CLIENT_ACCESS_READ_ONLY) ||
        (_clientAccess == BLE_CLIENT_ACCESS_READ_WRITE)) {
        _char_data.perms.rd = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1;
        _char_data.props.props |= BLE_GATT_CHAR_PROP_BIT_READ;

        /* Enable notifications only if characteristic is also readable by client */
        if (_clientNotify == BLE_CLIENT_NOTIFY_ENABLED)
            _char_data.props.props |= BLE_GATT_CHAR_PROP_BIT_NOTIFY;
        else if (_clientNotify == BLE_CLIENT_NOTIFY_WITH_ACK)
            _char_data.props.props |= BLE_GATT_CHAR_PROP_BIT_INDICATE;
    }
    else {
        _char_data.perms.rd = GAP_SEC_NO_PERMISSION;
    }

    if ((_clientAccess == BLE_CLIENT_ACCESS_WRITE_ONLY) ||
        (_clientAccess == BLE_CLIENT_ACCESS_READ_WRITE)) {
        _char_data.perms.wr = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1;
        _char_data.props.props |= (BLE_GATT_CHAR_PROP_BIT_WRITE | BLE_GATT_CHAR_PROP_BIT_WRITE_NR);
    }
    else {
        _char_data.perms.wr = GAP_SEC_NO_PERMISSION;
    }

    _char_data.init_len = _data_len;
    _char_data.max_len = maxLength > BLE_MAX_ATTR_DATA_LEN ? BLE_MAX_ATTR_DATA_LEN : maxLength;
    _char_data.p_value = _data;
}

BleCharacteristic::BleCharacteristic(const uint16_t uuid16,
                                     const uint16_t maxLength,
                                     const BleClientAccessMode clientAccess,
                                     const BleClientNotifyMode clientNotify)
    : BleCharacteristic(maxLength, clientAccess, clientNotify)
{
    _uuid.type = BT_UUID16;
    _uuid.uuid16 = uuid16;
}

BleCharacteristic::BleCharacteristic(const uint8_t uuid128[],
                                     const uint16_t maxLength,
                                     const BleClientAccessMode clientAccess,
                                     const BleClientNotifyMode clientNotify)
    : BleCharacteristic(maxLength, clientAccess, clientNotify)
{
    _uuid.type = BT_UUID128;
    memcpy(&_uuid.uuid128, uuid128, MAX_UUID_SIZE);
}

BleStatus
BleCharacteristic::addUserDescription(const char *description)
{
    if (_initialised)
        return BLE_STATUS_WRONG_STATE;

    if (description && description[0]) {
        _user_desc.len = strlen(description);
        if (_user_desc.len > sizeof(_user_desc_data))
            _user_desc.len = sizeof(_user_desc_data);
        memset(_user_desc_data, 0, sizeof(_user_desc_data));
        memcpy(_user_desc_data, description, _user_desc.len);
        _user_desc.buffer = _user_desc_data;

        _char_data.p_user_desc = &_user_desc;
    }

    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::addPresentationFormat(const uint8_t  format,
                                         const int8_t   exponent,
                                         const uint16_t unit,
                                         const uint8_t  nameSpace,
                                         const uint16_t description)
{
    if (_initialised)
        return BLE_STATUS_WRONG_STATE;

    _pf_desc.format = format;
    _pf_desc.exp = exponent;
    _pf_desc.unit = unit;
    _pf_desc.name_spc = nameSpace;
    _pf_desc.descr = description;

    _char_data.p_char_pf_desc = &_pf_desc;

    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::_setValue(void)
{
    BleStatus status;

    if (!_initialised)
        return BLE_STATUS_WRONG_STATE;

    if (_data_len > _char_data.max_len)
        return BLE_STATUS_NOT_ALLOWED;

    status = ble_client_gatts_set_attribute_value(_handles.value_handle,
                                                  _data_len, _data, 0);
    if (BLE_STATUS_SUCCESS != status)
        return status;

    if (_notifyEnabled || _indicateEnabled) {
        status = ble_client_gatts_send_notif_ind(_handles.value_handle, _data_len, _data, 0, _indicateEnabled);
        if (BLE_STATUS_SUCCESS != status)
            return status;

        if (_indicateEnabled && _event_cb)
            _event_cb(*this, BLE_CHAR_EVENT_INDICATION_ACK, _event_cb_arg);
    }

    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::setValue(const uint8_t value[], const uint16_t length)
{
    if (!value)
        return BLE_STATUS_NOT_ALLOWED;
    if (length > _char_data.max_len)
        return BLE_STATUS_NOT_ALLOWED;

    /* Cache the value locally */
    memcpy(_data, value, length);
    _data_len = length;

    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const String &str)
{
    str.getBytes((unsigned char *)&_data, (unsigned int)_char_data.max_len, 0U);
    _data_len = str.len + 1;
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const char *cstr)
{
    return setValue((uint8_t *)cstr, (uint16_t) (strlen(cstr) + 1));
}

BleStatus
BleCharacteristic::setValue(const char &value)
{
    uint8_t *p = _data;
    INT8_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const unsigned char &value)
{
    uint8_t *p = _data;
    UINT8_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const short &value)
{
    uint8_t *p = _data;
    INT16_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const unsigned short &value)
{
    uint8_t *p = _data;
    UINT16_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const int &value)
{
    uint8_t *p = _data;
    INT32_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const unsigned int &value)
{
    uint8_t *p = _data;
    UINT32_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const long &value)
{
    uint8_t *p = _data;
    INT32_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::setValue(const unsigned long &value)
{
    uint8_t *p = _data;
    UINT32_TO_LESTREAM(p, value);
    _data_len = sizeof(value);
    return _setValue();
}

BleStatus
BleCharacteristic::getValue(uint8_t value[], uint16_t &length) const
{
    if (!_initialised)
        return BLE_STATUS_WRONG_STATE;

    memcpy(value, _data, _data_len);
    length = _data_len;

    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(String &str) const
{
    str = (char *)_data;
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(char *cstr) const
{
    memcpy(cstr, _data, _data_len);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(char &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_INT8(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(unsigned char &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_UINT8(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(short &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_INT16(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(unsigned short &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_UINT16(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(int &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_INT32(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(unsigned int &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_UINT32(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(long &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_INT32(p, value);
    return BLE_STATUS_SUCCESS;
}

BleStatus
BleCharacteristic::getValue(unsigned long &value) const
{
    const uint8_t *p = _data;
    LESTREAM_TO_UINT32(p, value);
    return BLE_STATUS_SUCCESS;
}

void
BleCharacteristic::setEventCallback(BleCharacteristicEventCb callback,
                                    void *arg)
{
    noInterrupts();
    _event_cb = callback; /* callback disabled if NULL */
    _event_cb_arg = arg;
    interrupts();
}

BleStatus
BleCharacteristic::addDescriptor(BleDescriptor &descriptor)
{
    BleStatus status;

    if (!_initialised)
        return BLE_STATUS_WRONG_STATE;
    if (_num_descriptors >= BLE_MAX_DESCRIPTORS)
        return BLE_STATUS_ERROR;

    /* If this service has a 128-bit UUID, it shall be inherited
     * by included services, characteristics, and descriptors
     */
    if ((BT_UUID128 == _uuid.type) && (BT_UUID16 == descriptor._uuid.type))
        BLE_UUID16_TO_UUID128(descriptor._uuid, _uuid);

    status = ble_client_gatts_add_descriptor(_svc_handle,
                                             &descriptor._desc,
                                             &descriptor._handle);
    if (BLE_STATUS_SUCCESS == status) {
        descriptor._initialised = true;
        _descriptors[_num_descriptors++] = &descriptor;
    }

    return status;
}

BleDescriptor *
BleCharacteristic::_matchDescriptor(uint16_t handle) const
{
    for (unsigned i = 0; i < _num_descriptors; i++) {
        BleDescriptor *desc = _descriptors[i];
        if (handle == desc->_handle)
            return desc;
    }

    return NULL;
}

void
BleCharacteristic::_addCCCDescriptor(void)
{
    /* Activate our CCCD descriptor object */
    _cccd._handle = _handles.cccd_handle;
    _cccd._initialised = true;
    _cccd.setEventCallback(_cccdEventHandler, (void *)this);
    _descriptors[_num_descriptors++] = &_cccd;
}

void
BleCharacteristic::_setConnectedState(boolean_t connected)
{
    _connected = connected;

    /* Reset the state of these internal variables when connection is dropped */
    if (!connected) {
        _notifyEnabled = false;
        _indicateEnabled = false;
    }

    /* Cascade the connected-state update to descriptors */
    for (unsigned i = 0; i < _num_descriptors; i++)
        _descriptors[i]->_setConnectedState(connected);
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#include <stdio.h>

#include <osl/mutex.hxx>
#include <osl/thread.h>
#include <cppuhelper/factory.hxx>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>

#include "LotusWordProImportFilter.hxx"

using namespace ::cppu;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

extern "C"
{
SAL_DLLPUBLIC_EXPORT void * SAL_CALL lotuswordpro_component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
{
    void * pRet = 0;

    OUString implName = OUString::createFromAscii( pImplName );
    if ( pServiceManager && implName.equals(LotusWordProImportFilter_getImplementationName()) )
    {
        Reference< XSingleServiceFactory > xFactory( createSingleFactory(
            reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
            OUString::createFromAscii( pImplName ),
            LotusWordProImportFilter_createInstance, LotusWordProImportFilter_getSupportedServiceNames() ) );

        if (xFactory.is())
        {
            xFactory->acquire();
            pRet = xFactory.get();
        }
    }

    return pRet;
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Reduce to static_cast any reinterpret_cast from void pointers<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#include <stdio.h>

#include <osl/mutex.hxx>
#include <osl/thread.h>
#include <cppuhelper/factory.hxx>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>

#include "LotusWordProImportFilter.hxx"

using namespace ::cppu;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

extern "C"
{
SAL_DLLPUBLIC_EXPORT void * SAL_CALL lotuswordpro_component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
{
    void * pRet = 0;

    OUString implName = OUString::createFromAscii( pImplName );
    if ( pServiceManager && implName.equals(LotusWordProImportFilter_getImplementationName()) )
    {
        Reference< XSingleServiceFactory > xFactory( createSingleFactory(
            static_cast< XMultiServiceFactory * >( pServiceManager ),
            OUString::createFromAscii( pImplName ),
            LotusWordProImportFilter_createInstance, LotusWordProImportFilter_getSupportedServiceNames() ) );

        if (xFactory.is())
        {
            xFactory->acquire();
            pRet = xFactory.get();
        }
    }

    return pRet;
}
}

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


<commit_before>/*
 * This file is part of meego-keyboard
 *
 * Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * 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.
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 * used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * 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 "mimsnapshotpixmapitem.h"
#include "mplainwindow.h"
#include "panparameters.h"

#include <MNamespace>
#include <QDebug>
#include <MScene>
#include <MSceneManager>

namespace
{
}

MImSnapshotPixmapItem::MImSnapshotPixmapItem(const QPixmap &pixmap,
                                             QGraphicsItem* parent)
    : QObject(),
      QGraphicsPixmapItem(pixmap, parent)
{
}

MImSnapshotPixmapItem::MImSnapshotPixmapItem(QGraphicsItem *parent)
    : QObject(),
      QGraphicsPixmapItem(parent)
{
}

MImSnapshotPixmapItem::~MImSnapshotPixmapItem()
{
    connectPanParameters(0);
}

void MImSnapshotPixmapItem::grabScreen(const QRect &rect)
{
    QPixmap pixmap = QPixmap::grabWidget(scene()->views().at(0), rect);

    if (MPlainWindow::instance()->sceneManager()->orientation() == M::Portrait) {
        QTransform portraitTransform;
        portraitTransform.rotate(90);
        pixmap = pixmap.transformed(portraitTransform);
    }

    setPixmap(pixmap);
}

void MImSnapshotPixmapItem::grabWidgets(const QList<QPointer<QGraphicsWidget> > &widgets)
{
    if (not MPlainWindow::instance() || widgets.isEmpty()) {
        // clear by setting empty pixmap
        setPixmap(QPixmap());
        return;
    }

    // Querying visible scene size for landscape orientation, because
    // widget->sceneBoundingRect() always returns the bounding rectangle of
    // the widget for landscape orientation:
    const QSize &visibleSceneSize(MPlainWindow::instance()->visibleSceneSize(M::Landscape));

    const bool isPortrait((MPlainWindow::instance()->sceneManager()->orientation() == M::Portrait));
    const QRectF &screenRect(QRectF(QPoint(0, 0), visibleSceneSize));

    QRectF rect;
    foreach (const QGraphicsWidget *widget, widgets) {
        rect |= (widget->sceneBoundingRect() & screenRect);
    }

    qreal posY = 0;
    if (isPortrait) {
        posY = visibleSceneSize.width() - rect.width();
        rect = QRectF(0, 0, rect.height(), rect.width());
    } else {
        posY = visibleSceneSize.height() - rect.height();
    }

    const QPointF pos(0, posY);
    QPixmap pixmap(rect.width(), rect.height());

    if (pixmap.isNull()) {
        // Avoid painting on invalid pixmap => could crash otherwise.
        return;
    }

    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    foreach (QGraphicsWidget *widget, widgets) {
        const QPointF tp(isPortrait ? QPointF(0, widget->scenePos().x() - pos.y())
                                    : widget->scenePos() - pos);

        QTransform t;
        t.translate(tp.x(), tp.y());
        painter.setTransform(t);

        foreach (QGraphicsItem *item, widget->childItems())
            item->paint(&painter, 0, 0);

        widget->paint(&painter, 0, 0);
    }

    setPixmap(pixmap);
}

void MImSnapshotPixmapItem::grabPixmaps(const QMap<QPixmap*, QPoint > &pixmaps)
{
    qDebug() << __PRETTY_FUNCTION__ << " with pixmaps:" <<  pixmaps.count();
    if (pixmaps.isEmpty()) {
        // clear by setting empty pixmap
        setPixmap(QPixmap());
        return;
    }

    const bool isPortrait =
        (MPlainWindow::instance()->sceneManager()->orientation() == M::Portrait);

    QRect rect;
    QMap<QPixmap*, QPoint>::const_iterator it = pixmaps.constBegin();
    QPoint basePos = it.value();

    for (it = pixmaps.constBegin(); it != pixmaps.constEnd(); it++) {
        if (!it.key())
            continue;
        rect |= QRect(it.value(), it.key()->size());
        basePos.setX(qMin(it.value().x(), basePos.x()));
        basePos.setY(qMin(it.value().y(), basePos.y()));
    }

    QPixmap pixmap(isPortrait ? QSize(rect.height(), rect.width())
                              : rect.size());

    if (pixmap.isNull()) {
        // Avoid painting on invalid pixmap => could crash otherwise.
        return;
    }

    QPainter painter(&pixmap);

    if (isPortrait) {
        QTransform portraitTransform;
        portraitTransform.rotate(90);
        for (it = pixmaps.constBegin(); it != pixmaps.constEnd(); it++) {
            if (!it.key())
                continue;
            painter.drawPixmap(QPointF(it.value() - basePos),
                               QPixmap(*it.key()).transformed(portraitTransform));
        }
    } else {
        for (it = pixmaps.constBegin(); it != pixmaps.constEnd(); it++) {
            if (!it.key())
                continue;
            painter.drawPixmap(QPointF(it.value() - basePos),
                               *it.key());
        }
    }

    setPixmap(pixmap);
}

void MImSnapshotPixmapItem::updatePos(const QPointF &pos)
{
    setPos(pos);
}

void MImSnapshotPixmapItem::updateOpacity(qreal opacity)
{
    setOpacity(opacity);
}

void MImSnapshotPixmapItem::updateScale(qreal scale)
{
    setScale(scale);
}

void MImSnapshotPixmapItem::connectPanParameters(PanParameters *parameters)
{
    if (!mParameters.isNull()) {
        disconnect(mParameters.data(), 0, this, 0);
    }
    mParameters = parameters;

    if (!mParameters.isNull())  {
        connect(parameters, SIGNAL(positionChanged(QPointF)),
                this,       SLOT(updatePos(QPointF)));

        connect(parameters, SIGNAL(opacityChanged(qreal)),
                this,       SLOT(updateOpacity(qreal)));

        connect(parameters, SIGNAL(scaleChanged(qreal)),
                this,       SLOT(updateScale(qreal)));
    }
}
<commit_msg>Fixes: Blit children items correctly on widget surface<commit_after>/*
 * This file is part of meego-keyboard
 *
 * Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * 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.
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 * used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * 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 "mimsnapshotpixmapitem.h"
#include "mplainwindow.h"
#include "panparameters.h"

#include <MNamespace>
#include <QDebug>
#include <MScene>
#include <MSceneManager>

namespace
{
}

MImSnapshotPixmapItem::MImSnapshotPixmapItem(const QPixmap &pixmap,
                                             QGraphicsItem* parent)
    : QObject(),
      QGraphicsPixmapItem(pixmap, parent)
{
}

MImSnapshotPixmapItem::MImSnapshotPixmapItem(QGraphicsItem *parent)
    : QObject(),
      QGraphicsPixmapItem(parent)
{
}

MImSnapshotPixmapItem::~MImSnapshotPixmapItem()
{
    connectPanParameters(0);
}

void MImSnapshotPixmapItem::grabScreen(const QRect &rect)
{
    QPixmap pixmap = QPixmap::grabWidget(scene()->views().at(0), rect);

    if (MPlainWindow::instance()->sceneManager()->orientation() == M::Portrait) {
        QTransform portraitTransform;
        portraitTransform.rotate(90);
        pixmap = pixmap.transformed(portraitTransform);
    }

    setPixmap(pixmap);
}

void MImSnapshotPixmapItem::grabWidgets(const QList<QPointer<QGraphicsWidget> > &widgets)
{
    if (not MPlainWindow::instance() || widgets.isEmpty()) {
        // clear by setting empty pixmap
        setPixmap(QPixmap());
        return;
    }

    // Querying visible scene size for landscape orientation, because
    // widget->sceneBoundingRect() always returns the bounding rectangle of
    // the widget for landscape orientation:
    const QSize &visibleSceneSize(MPlainWindow::instance()->visibleSceneSize(M::Landscape));

    const bool isPortrait((MPlainWindow::instance()->sceneManager()->orientation() == M::Portrait));
    const QRectF &screenRect(QRectF(QPoint(0, 0), visibleSceneSize));

    QRectF rect;
    foreach (const QGraphicsWidget *widget, widgets) {
        rect |= (widget->sceneBoundingRect() & screenRect);
    }

    qreal posY = 0;
    if (isPortrait) {
        posY = visibleSceneSize.width() - rect.width();
        rect = QRectF(0, 0, rect.height(), rect.width());
    } else {
        posY = visibleSceneSize.height() - rect.height();
    }

    const QPointF pos(0, posY);
    QPixmap pixmap(rect.width(), rect.height());

    if (pixmap.isNull()) {
        // Avoid painting on invalid pixmap => could crash otherwise.
        return;
    }

    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    foreach (QGraphicsWidget *widget, widgets) {
        const QPointF tp(isPortrait ? QPointF(0, widget->scenePos().x() - pos.y())
                                    : widget->scenePos() - pos);

        QTransform t;
        t.translate(tp.x(), tp.y());
        painter.setTransform(t);

        widget->paint(&painter, 0, 0);
        foreach (QGraphicsItem *item, widget->childItems()) {
            // If isPortrait is true, then keep in mind that "rect" is also
            // "rotated" to portrait mode and moved to the area covered by the
            // VKB  (on the display). We still need to adjust the item (in
            // scene position) to that area.
            const QPointF &itemPos(isPortrait ? QPointF(rect.width() - item->scenePos().y(),
                                                        item->scenePos().x() - pos.y())
                                              : item->scenePos() - pos);
            QTransform itemTransform;
            itemTransform.translate(itemPos.x(), itemPos.y());
            painter.setTransform(itemTransform);
            item->paint(&painter, 0, 0);
        }
    }

    setPixmap(pixmap);
}

void MImSnapshotPixmapItem::grabPixmaps(const QMap<QPixmap*, QPoint > &pixmaps)
{
    qDebug() << __PRETTY_FUNCTION__ << " with pixmaps:" <<  pixmaps.count();
    if (pixmaps.isEmpty()) {
        // clear by setting empty pixmap
        setPixmap(QPixmap());
        return;
    }

    const bool isPortrait =
        (MPlainWindow::instance()->sceneManager()->orientation() == M::Portrait);

    QRect rect;
    QMap<QPixmap*, QPoint>::const_iterator it = pixmaps.constBegin();
    QPoint basePos = it.value();

    for (it = pixmaps.constBegin(); it != pixmaps.constEnd(); it++) {
        if (!it.key())
            continue;
        rect |= QRect(it.value(), it.key()->size());
        basePos.setX(qMin(it.value().x(), basePos.x()));
        basePos.setY(qMin(it.value().y(), basePos.y()));
    }

    QPixmap pixmap(isPortrait ? QSize(rect.height(), rect.width())
                              : rect.size());

    if (pixmap.isNull()) {
        // Avoid painting on invalid pixmap => could crash otherwise.
        return;
    }

    QPainter painter(&pixmap);

    if (isPortrait) {
        QTransform portraitTransform;
        portraitTransform.rotate(90);
        for (it = pixmaps.constBegin(); it != pixmaps.constEnd(); it++) {
            if (!it.key())
                continue;
            painter.drawPixmap(QPointF(it.value() - basePos),
                               QPixmap(*it.key()).transformed(portraitTransform));
        }
    } else {
        for (it = pixmaps.constBegin(); it != pixmaps.constEnd(); it++) {
            if (!it.key())
                continue;
            painter.drawPixmap(QPointF(it.value() - basePos),
                               *it.key());
        }
    }

    setPixmap(pixmap);
}

void MImSnapshotPixmapItem::updatePos(const QPointF &pos)
{
    setPos(pos);
}

void MImSnapshotPixmapItem::updateOpacity(qreal opacity)
{
    setOpacity(opacity);
}

void MImSnapshotPixmapItem::updateScale(qreal scale)
{
    setScale(scale);
}

void MImSnapshotPixmapItem::connectPanParameters(PanParameters *parameters)
{
    if (!mParameters.isNull()) {
        disconnect(mParameters.data(), 0, this, 0);
    }
    mParameters = parameters;

    if (!mParameters.isNull())  {
        connect(parameters, SIGNAL(positionChanged(QPointF)),
                this,       SLOT(updatePos(QPointF)));

        connect(parameters, SIGNAL(opacityChanged(qreal)),
                this,       SLOT(updateOpacity(qreal)));

        connect(parameters, SIGNAL(scaleChanged(qreal)),
                this,       SLOT(updateScale(qreal)));
    }
}
<|endoftext|>


<commit_before>/*
* File: messages.cpp
* Author: m79lol, iskinmike
*
*/

#include <iostream>
#include <windows.h>
#include <vector>

#include "../module_headers/module.h"
#include "../module_headers/function_module.h"
#include "u3d_function_module.h"
#include "messagesf.h"

// GLOBAL VARIABLES
const int COUNT_U3D_FUNCTIONS = 3;

u3dFunctionModule::u3dFunctionModule() {
	u3d_functions = new FunctionData*[COUNT_U3D_FUNCTIONS];
	system_value function_id = 0;

	FunctionData::ParamTypes *Params = new FunctionData::ParamTypes[7];
	Params[0] = FunctionData::FLOAT;
	Params[1] = FunctionData::FLOAT;
	Params[2] = FunctionData::FLOAT;
	Params[3] = FunctionData::FLOAT;
	Params[4] = FunctionData::FLOAT;
	Params[5] = FunctionData::FLOAT;
	Params[6] = FunctionData::STRING;

	u3d_functions[function_id] = new FunctionData(function_id + 1, 7, Params, "spawnCube");
	function_id++;

	Params = new FunctionData::ParamTypes[5];
	Params[0] = FunctionData::FLOAT;
	Params[1] = FunctionData::FLOAT;
	Params[2] = FunctionData::FLOAT;
	Params[3] = FunctionData::FLOAT;
	Params[4] = FunctionData::STRING;

	u3d_functions[function_id] = new FunctionData(function_id + 1, 5, Params, "spawnSphere");
	function_id++;

	Params = new FunctionData::ParamTypes[1];
	Params[0] = FunctionData::FLOAT;
	u3d_functions[function_id] = new FunctionData(function_id + 1, 1, Params, "deleteCreatedObject");
};

FunctionResult* u3dFunctionModule::executeFunction(system_value function_index, void **args) {
	if ((function_index < 1) || (function_index > COUNT_U3D_FUNCTIONS)) {
		return NULL;
	}
	variable_value rez = 0;
	try {
		switch (function_index) {
		case 1: {
			variable_value *input1 = (variable_value *)args[0];
			variable_value *input2 = (variable_value *)args[1];
			variable_value *input3 = (variable_value *)args[2];
			variable_value *input4 = (variable_value *)args[3];
			variable_value *input5 = (variable_value *)args[4];
			variable_value *input6 = (variable_value *)args[5];
			std::string input7((const char *)args[6]);
			rez = createCube((int)*input1, (int)*input2, (int)*input3, (int)*input4, (int)*input5, (int) *input6, input7);
			break;
		}
		case 2: {
			variable_value *input1 = (variable_value *)args[0];
			variable_value *input2 = (variable_value *)args[1];
			variable_value *input3 = (variable_value *)args[2];
			variable_value *input4 = (variable_value *)args[3];
			std::string input5((const char *)(args[4]));
			rez = createSphere((int)*input1, (int)*input2, (int)*input3, (int)*input4, input5);
			break;
		}
		case 3: {
			variable_value *input1 = (variable_value *)args[0];
			deleteCreatedObject( (int) *input1);
			break;
		}
		};
		return new FunctionResult(1, rez);
	}
	catch (...){
		return new FunctionResult(0);
	};
};

void u3dFunctionModule::prepare(colorPrintf_t *colorPrintf_p, colorPrintfVA_t *colorPrintfVA_p) {
	colorPrintf = colorPrintf_p;
}
FunctionData** u3dFunctionModule::getFunctions(unsigned int *count_functions) {
	*count_functions = COUNT_U3D_FUNCTIONS;
	return u3d_functions;
};
const char* u3dFunctionModule::getUID() {
	return "u3dfunction_dll";
};
void *u3dFunctionModule::writePC(unsigned int *buffer_length) {
	*buffer_length = 0;
	return NULL;
}
int u3dFunctionModule::startProgram(int uniq_index, void *buffer, unsigned int buffer_length) {
	return 0;
}
int u3dFunctionModule::endProgram(int uniq_index) {
	return 0;
}
void u3dFunctionModule::destroy() {
	for (unsigned int j = 0; j < COUNT_U3D_FUNCTIONS; ++j) {
		delete u3d_functions[j];
	}
	delete[] u3d_functions;
	delete this;
};

__declspec(dllexport) FunctionModule* getFunctionModuleObject() {
	return new u3dFunctionModule();
};
<commit_msg>Дополнен деструктор destroy()<commit_after>/*
* File: messages.cpp
* Author: m79lol, iskinmike
*
*/

#include <iostream>
#include <windows.h>
#include <vector>

#include "../module_headers/module.h"
#include "../module_headers/function_module.h"
#include "u3d_function_module.h"
#include "messagesf.h"

// GLOBAL VARIABLES
const int COUNT_U3D_FUNCTIONS = 3;

u3dFunctionModule::u3dFunctionModule() {
	u3d_functions = new FunctionData*[COUNT_U3D_FUNCTIONS];
	system_value function_id = 0;

	FunctionData::ParamTypes *Params = new FunctionData::ParamTypes[7];
	Params[0] = FunctionData::FLOAT;
	Params[1] = FunctionData::FLOAT;
	Params[2] = FunctionData::FLOAT;
	Params[3] = FunctionData::FLOAT;
	Params[4] = FunctionData::FLOAT;
	Params[5] = FunctionData::FLOAT;
	Params[6] = FunctionData::STRING;

	u3d_functions[function_id] = new FunctionData(function_id + 1, 7, Params, "spawnCube");
	function_id++;

	Params = new FunctionData::ParamTypes[5];
	Params[0] = FunctionData::FLOAT;
	Params[1] = FunctionData::FLOAT;
	Params[2] = FunctionData::FLOAT;
	Params[3] = FunctionData::FLOAT;
	Params[4] = FunctionData::STRING;

	u3d_functions[function_id] = new FunctionData(function_id + 1, 5, Params, "spawnSphere");
	function_id++;

	Params = new FunctionData::ParamTypes[1];
	Params[0] = FunctionData::FLOAT;
	u3d_functions[function_id] = new FunctionData(function_id + 1, 1, Params, "deleteCreatedObject");
};

FunctionResult* u3dFunctionModule::executeFunction(system_value function_index, void **args) {
	if ((function_index < 1) || (function_index > COUNT_U3D_FUNCTIONS)) {
		return NULL;
	}
	variable_value rez = 0;
	try {
		switch (function_index) {
		case 1: {
			variable_value *input1 = (variable_value *)args[0];
			variable_value *input2 = (variable_value *)args[1];
			variable_value *input3 = (variable_value *)args[2];
			variable_value *input4 = (variable_value *)args[3];
			variable_value *input5 = (variable_value *)args[4];
			variable_value *input6 = (variable_value *)args[5];
			std::string input7((const char *)args[6]);
			rez = createCube((int)*input1, (int)*input2, (int)*input3, (int)*input4, (int)*input5, (int) *input6, input7);
			break;
		}
		case 2: {
			variable_value *input1 = (variable_value *)args[0];
			variable_value *input2 = (variable_value *)args[1];
			variable_value *input3 = (variable_value *)args[2];
			variable_value *input4 = (variable_value *)args[3];
			std::string input5((const char *)(args[4]));
			rez = createSphere((int)*input1, (int)*input2, (int)*input3, (int)*input4, input5);
			break;
		}
		case 3: {
			variable_value *input1 = (variable_value *)args[0];
			deleteCreatedObject( (int) *input1);
			break;
		}
		};
		return new FunctionResult(1, rez);
	}
	catch (...){
		return new FunctionResult(0);
	};
};

void u3dFunctionModule::prepare(colorPrintf_t *colorPrintf_p, colorPrintfVA_t *colorPrintfVA_p) {
	colorPrintf = colorPrintf_p;
}
FunctionData** u3dFunctionModule::getFunctions(unsigned int *count_functions) {
	*count_functions = COUNT_U3D_FUNCTIONS;
	return u3d_functions;
};
const char* u3dFunctionModule::getUID() {
	return "u3dfunction_dll";
};
void *u3dFunctionModule::writePC(unsigned int *buffer_length) {
	*buffer_length = 0;
	return NULL;
}
int u3dFunctionModule::startProgram(int uniq_index, void *buffer, unsigned int buffer_length) {
	return 0;
}
int u3dFunctionModule::endProgram(int uniq_index) {
	return 0;
}
void u3dFunctionModule::destroy() {
	for (unsigned int j = 0; j < COUNT_U3D_FUNCTIONS; ++j) {
		if (u3d_functions[j]->count_params) {
			delete[] u3d_functions[j]->params;
		}
		delete u3d_functions[j];
	}
	delete[] u3d_functions;
	delete this;
};

__declspec(dllexport) FunctionModule* getFunctionModuleObject() {
	return new u3dFunctionModule();
};
<|endoftext|>


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

#include "chrome/browser/chromeos/frame/bubble_window.h"

#include <gtk/gtk.h>

#include "chrome/browser/chromeos/frame/bubble_frame_view.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "cros/chromeos_wm_ipc_enums.h"
#include "gfx/skia_utils_gtk.h"
#include "views/window/non_client_view.h"

namespace chromeos {

// static
const SkColor BubbleWindow::kBackgroundColor = SK_ColorWHITE;

BubbleWindow::BubbleWindow(views::WindowDelegate* window_delegate)
    : views::WindowGtk(window_delegate) {
  MakeTransparent();
}

void BubbleWindow::Init(GtkWindow* parent, const gfx::Rect& bounds) {
  views::WindowGtk::Init(parent, bounds);

  GdkColor background_color = gfx::SkColorToGdkColor(kBackgroundColor);
  gtk_widget_modify_bg(GetNativeView(), GTK_STATE_NORMAL, &background_color);
}

views::Window* BubbleWindow::Create(
    gfx::NativeWindow parent,
    const gfx::Rect& bounds,
    Style style,
    views::WindowDelegate* window_delegate) {
  BubbleWindow* window = new BubbleWindow(window_delegate);
  window->GetNonClientView()->SetFrameView(new BubbleFrameView(window, style));
  window->Init(parent, bounds);

  return window;
}

}  // namespace chromeos
<commit_msg>Fix a couple UI problems of ChromeOS BubbleWindow.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/frame/bubble_window.h"

#include <gtk/gtk.h>

#include "chrome/browser/chromeos/frame/bubble_frame_view.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "cros/chromeos_wm_ipc_enums.h"
#include "gfx/skia_utils_gtk.h"
#include "views/window/non_client_view.h"

namespace chromeos {

// static
const SkColor BubbleWindow::kBackgroundColor = SK_ColorWHITE;

BubbleWindow::BubbleWindow(views::WindowDelegate* window_delegate)
    : views::WindowGtk(window_delegate) {
  MakeTransparent();
}

void BubbleWindow::Init(GtkWindow* parent, const gfx::Rect& bounds) {
  views::WindowGtk::Init(parent, bounds);

  // Turn on double buffering so that the hosted GtkWidgets does not
  // flash as in http://crosbug.com/9065.
  EnableDoubleBuffer(true);

  GdkColor background_color = gfx::SkColorToGdkColor(kBackgroundColor);
  gtk_widget_modify_bg(GetNativeView(), GTK_STATE_NORMAL, &background_color);

  // A work-around for http://crosbug.com/8538. All GdkWidnow of top-level
  // GtkWindow should participate _NET_WM_SYNC_REQUEST protocol and window
  // manager should only show the window after getting notified. And we
  // should only notify window manager after at least one paint is done.
  // TODO(xiyuan): Figure out the right fix.
  gtk_widget_realize(GetNativeView());
  gdk_window_set_back_pixmap(GetNativeView()->window, NULL, FALSE);
  gtk_widget_realize(window_contents());
  gdk_window_set_back_pixmap(window_contents()->window, NULL, FALSE);
}

views::Window* BubbleWindow::Create(
    gfx::NativeWindow parent,
    const gfx::Rect& bounds,
    Style style,
    views::WindowDelegate* window_delegate) {
  BubbleWindow* window = new BubbleWindow(window_delegate);
  window->GetNonClientView()->SetFrameView(new BubbleFrameView(window, style));
  window->Init(parent, bounds);

  return window;
}

}  // namespace chromeos
<|endoftext|>


<commit_before>#include "../warnings-disable.h"

WARNINGS_DISABLE
#include <QAccessible>
#include <QApplication>
#include <QMetaObject>
#include <QObject>
#include <QPixmap>
#include <QWidget>
WARNINGS_ENABLE

#include "../macros-valgrind.h"

static void pl_nothing()
{
}

static void pl_app()
{
    T_APP_BEGIN_GUI;

    T_APP_END_GUI;
}

static void pl_object()
{
    // Create object before app
    QObject *obj = new QObject();

    T_APP_BEGIN_GUI;

    T_APP_END_GUI;

    // Delete object after app
    delete obj;
}

static void pl_exec()
{
    T_APP_BEGIN_GUI;

    // Queue a quit event.
    QMetaObject::invokeMethod(app, "quit", Qt::QueuedConnection);

    // Launch the event loop.
    app->exec();

    T_APP_END_GUI;
}

static void pl_app_pix()
{
    T_APP_BEGIN_GUI;

    QWidget *wid = new QWidget();
    QPixmap *pix = new QPixmap("16x16-white.png");
    delete pix;
    delete wid;

    T_APP_END_GUI;
}

static void pl_app_pix_two()
{
    pl_app_pix();
    pl_app_pix();
}

// clang-format off
T_TEST_BEGIN
    MEMLEAKTEST(pl_nothing),
    MEMLEAKTEST(pl_app),
    MEMLEAKTEST(pl_object),
    MEMLEAKTEST(pl_exec),
    MEMLEAKTEST(pl_app_pix_two)
T_TEST_END
<commit_msg>tests/valgrind: check QIcon::addFile()<commit_after>#include "../warnings-disable.h"

WARNINGS_DISABLE
#include <QAccessible>
#include <QApplication>
#include <QIcon>
#include <QMetaObject>
#include <QObject>
#include <QPixmap>
#include <QWidget>
WARNINGS_ENABLE

#include "../macros-valgrind.h"

static void pl_nothing()
{
}

static void pl_app()
{
    T_APP_BEGIN_GUI;

    T_APP_END_GUI;
}

static void pl_object()
{
    // Create object before app
    QObject *obj = new QObject();

    T_APP_BEGIN_GUI;

    T_APP_END_GUI;

    // Delete object after app
    delete obj;
}

static void pl_exec()
{
    T_APP_BEGIN_GUI;

    // Queue a quit event.
    QMetaObject::invokeMethod(app, "quit", Qt::QueuedConnection);

    // Launch the event loop.
    app->exec();

    T_APP_END_GUI;
}

static void pl_icon()
{
    T_APP_BEGIN_GUI;

    QIcon *icon = new QIcon();
    icon->addFile("16x16-white.png");
    delete icon;

    T_APP_END_GUI;
}

static void pl_app_pix()
{
    T_APP_BEGIN_GUI;

    QWidget *wid = new QWidget();
    QPixmap *pix = new QPixmap("16x16-white.png");
    delete pix;
    delete wid;

    T_APP_END_GUI;
}

static void pl_app_pix_two()
{
    pl_app_pix();
    pl_app_pix();
}

// clang-format off
T_TEST_BEGIN
    MEMLEAKTEST(pl_nothing),
    MEMLEAKTEST(pl_app),
    MEMLEAKTEST(pl_object),
    MEMLEAKTEST(pl_exec),
    MEMLEAKTEST(pl_icon),
    MEMLEAKTEST(pl_app_pix_two)
T_TEST_END
<|endoftext|>


<commit_before>/*
 Copyright 2021 Alain Dargelas

 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 <string>
#include <string_view>
#include <vector>

#include "SourceCompile/PreprocessHarness.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

using ::testing::ElementsAre;

namespace SURELOG {
namespace {
TEST(PreprocessTest, PreprocessWithoutPPTokens) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess("module top(); endmodule");
  EXPECT_EQ(res, "module top(); endmodule");
}

TEST(PreprocessTest, PreprocessSingleParameterExpansion) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define FOO(a) a*2
module top();
  assign b = `FOO(c);
endmodule)");

  EXPECT_EQ(res, R"(
module top();
  assign b = c*2;
endmodule)");
}

TEST(PreprocessTest, PreprocessTwoParameterExpansion) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define BAR(a, b) (a)*2+( b )
module top();
  assign b = `BAR(3 * c, 2*d);
endmodule)");

  EXPECT_EQ(res, R"(
module top();
  assign b = (3 * c)*2+( 2*d );
endmodule)");
}

TEST(PreprocessTest, PreprocessMacroExpansionInMacroCall) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define FOURTYTWO 42
`define BAR(a) a * 3
module top();
  assign b = `BAR(`FOURTYTWO);
endmodule)");

  EXPECT_EQ(res, R"(
module top();
  assign b = 42 * 3;
endmodule)");
}

TEST(PreprocessTest, PreprocessMacroExpansionWithDefaultParameter) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define FOO(a = 42) a * 2
module top();
  assign b = `FOO(1);
  assign c = `FOO();  // Default applies
endmodule)");

  EXPECT_EQ(res, R"(
module top();
  assign b = 1 * 2;
  assign c = 42 * 2;  // Default applies
endmodule)");
}

}  // namespace
}  // namespace SURELOG
<commit_msg>Add a unit-test for `ifdef<commit_after>/*
 Copyright 2021 Alain Dargelas

 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 <string>
#include <string_view>
#include <vector>

#include "SourceCompile/PreprocessHarness.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

using ::testing::ElementsAre;

namespace SURELOG {
namespace {
TEST(PreprocessTest, PreprocessWithoutPPTokens) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess("module top(); endmodule");
  EXPECT_EQ(res, "module top(); endmodule");
}

TEST(PreprocessTest, PreprocessSingleParameterExpansion) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define FOO(a) a*2
module top();
  assign b = `FOO(c);
endmodule)");

  EXPECT_EQ(res, R"(
module top();
  assign b = c*2;
endmodule)");
}

TEST(PreprocessTest, PreprocessTwoParameterExpansion) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define BAR(a, b) (a)*2+( b )
module top();
  assign b = `BAR(3 * c, 2*d);
endmodule)");

  EXPECT_EQ(res, R"(
module top();
  assign b = (3 * c)*2+( 2*d );
endmodule)");
}

TEST(PreprocessTest, PreprocessMacroExpansionInMacroCall) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define FOURTYTWO 42
`define BAR(a) a * 3
module top();
  assign b = `BAR(`FOURTYTWO);
endmodule)");

  EXPECT_EQ(res, R"(
module top();
  assign b = 42 * 3;
endmodule)");
}

TEST(PreprocessTest, PreprocessMacroExpansionWithDefaultParameter) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define FOO(a = 42) a * 2
module top();
  assign b = `FOO(1);
  assign c = `FOO();  // Default applies
endmodule)");

  EXPECT_EQ(res, R"(
module top();
  assign b = 1 * 2;
  assign c = 42 * 2;  // Default applies
endmodule)");
}

TEST(PreprocessTest, IfdefCodeSelectionIfBranch) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define FOO 1
module top();
`ifdef FOO
  assign a = 42;
`else
  assign a = 2;
`endif
endmodule)");

  // In the result it is interesting that the `define itself and the else area
  // is entirely removed and not even showing up as newline.
  // This could break line counting later in the pipeline.
  EXPECT_EQ(res, R"(
module top();

  assign a = 42;

endmodule)");
}

TEST(PreprocessTest, IfdefCodeSelectionElseBranch) {
  PreprocessHarness harness;
  const std::string res = harness.preprocess(R"(
`define BAR 1
module top();
`ifdef FOO
  assign a = 42;
`else
  assign a = 2;
`endif
endmodule)");

  // Similar observation w.r.t. missing newlines as in previous test.
  EXPECT_EQ(res, R"(
module top();

  assign a = 2;

endmodule)");
}

}  // namespace
}  // namespace SURELOG
<|endoftext|>


<commit_before>#ifndef RAPID_CXX_TEST_OBSERVER_HPP
#define RAPID_CXX_TEST_OBSERVER_HPP

# include "common.hpp"
# include <cstddef>
# include <cstdio>

namespace rapid_cxx_test
{
    class test_observer;
}                                                   // namespace rapid_cxx_test
#endif /* RAPID_CXX_TEST_OBSERVER_HPP */<commit_msg>add observer stub<commit_after>#ifndef RAPID_CXX_TEST_OBSERVER_HPP
#define RAPID_CXX_TEST_OBSERVER_HPP

# include "common.hpp"
# include <cstddef>
# include <cstdio>

namespace rapid_cxx_test
{
    class test_observer
    {
    public:
        test_observer() {}
    };

    inline test_observer & get_observer() noexcept
    {
        static test_observer o;
        return o;
    }
}                                                   // namespace rapid_cxx_test
#endif /* RAPID_CXX_TEST_OBSERVER_HPP */<|endoftext|>


<commit_before>#ifndef LUA_PROXY_INTERFACE_HPP_INCLUDED
#define LUA_PROXY_INTERFACE_HPP_INCLUDED

#include <luabind/lua_proxy.hpp>
#include <luabind/detail/call_function.hpp>
#include <ostream>

#if LUA_VERSION_NUM < 502
# define lua_compare(L, index1, index2, fn) fn(L, index1, index2)
# define LUA_OPEQ lua_equal
# define LUA_OPLT lua_lessthan
# define lua_rawlen lua_objlen
# define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX)
#endif

namespace luabind {

	namespace detail
	{

		template<class T, typename... Policies>
		void push(lua_State* interpreter, T& value, policy_list<Policies...> const& = no_policies())
		{
			using PolicyList = policy_list<Policies...>;
			typedef T unwrapped_type; // = T; //typename apply_reference_wrapper<T>::type;
			using converter_type = specialized_converter_policy_n<0, PolicyList, T/*unwrapped_type*/, cpp_to_lua >;
			converter_type().to_lua(interpreter, implicit_cast<unwrapped_type&>(value));
		}

	} // namespace detail

	namespace adl {

		template <class T>
		class lua_proxy_interface;

		namespace is_object_interface_aux
		{
			typedef char(&yes)[1];
			typedef char(&no)[2];

			template <class T>
			yes check(lua_proxy_interface<T>*);
			no check(void*);

			template <class T>
			struct impl
			{
				static const bool value = sizeof(is_object_interface_aux::check((T*) 0))==sizeof(yes);
				typedef std::integral_constant<bool, value> type;
			};

		} // namespace is_object_interface_aux

		template <class T>
		struct is_object_interface :
			is_object_interface_aux::impl<T>::type
		{};

		template <class R, class T, class U>
		struct enable_binary
			: std::enable_if< is_object_interface<T>::value||is_object_interface<U>::value, R >
		{};

		template<class T, class U>
		int binary_interpreter(lua_State*& L, T const& lhs, U const& rhs, std::true_type, std::true_type)
		{
			L = lua_proxy_traits<T>::interpreter(lhs);
			lua_State* L2 = lua_proxy_traits<U>::interpreter(rhs);

			// you are comparing objects with different interpreters
			// that's not allowed.
			assert(L==L2||L==0||L2==0);

			// if the two objects we compare have different interpreters
			// then they

			if(L!=L2) return -1;
			if(L==0) return 1;
			return 0;
		}

		template<class T, class U>
		int binary_interpreter(lua_State*& L, T const& x, U const&, std::true_type, std::false_type)
		{
			L = lua_proxy_traits<T>::interpreter(x);
			return 0;
		}

		template<class T, class U>
		int binary_interpreter(lua_State*& L, T const&, U const& x, std::false_type, std::true_type)
		{
			L = lua_proxy_traits<U>::interpreter(x);
			return 0;
		}

		template<class T, class U>
		int binary_interpreter(lua_State*& L, T const& x, U const& y)
		{
			return binary_interpreter(L, x, y, is_lua_proxy_type<T>(), is_lua_proxy_type<U>());
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
		operator==(LHS const& lhs, RHS const& rhs)
		{
			lua_State* L = 0;
			switch(binary_interpreter(L, lhs, rhs)) {
			case  1: return true;
			case-1: return false;
			}
			assert(L);
			detail::stack_pop pop1(L, 1);
			detail::push(L, lhs);
			detail::stack_pop pop2(L, 1);
			detail::push(L, rhs);
			return lua_compare(L, -1, -2, LUA_OPEQ)!=0;
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
			operator<(LHS const& lhs, RHS const& rhs)
		{
			lua_State* L = 0;
			switch(binary_interpreter(L, lhs, rhs)) {
			case  1: return true;
			case-1: return false;
			}
			assert(L);
			detail::stack_pop pop1(L, 1);
			detail::push(L, lhs);
			detail::stack_pop pop2(L, 1);
			detail::push(L, rhs);
			return lua_compare(L, -1, -2, LUA_OPLT)!=0;
		}

		template<class ValueWrapper>
		std::ostream& operator<<(std::ostream& os, lua_proxy_interface<ValueWrapper> const& v)
		{
			using namespace luabind;
			lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(
				static_cast<ValueWrapper const&>(v));
			detail::stack_pop pop(interpreter, 1);
			lua_proxy_traits<ValueWrapper>::unwrap(interpreter, static_cast<ValueWrapper const&>(v));
			char const* p = lua_tostring(interpreter, -1);
			std::size_t len = lua_rawlen(interpreter, -1);
			os.write(p, len);
			//std::copy(p, p+len, std::ostream_iterator<char>(os));
			return os;
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
			operator>(LHS const& lhs, RHS const& rhs)
		{
			return !(lhs<rhs||lhs==rhs);
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
		operator<=(LHS const& lhs, RHS const& rhs)
		{
			return lhs<rhs||lhs==rhs;
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
		operator>=(LHS const& lhs, RHS const& rhs)
		{
			return !(lhs<rhs);
			}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
			operator!=(LHS const& lhs, RHS const& rhs)
		{
			return !(lhs==rhs);
		}

		template<class Derived>
		class lua_proxy_interface
		{
		public:
			~lua_proxy_interface() {}

			// defined in luabind/detail/object.hpp
			template<typename... Args>
			object operator()(Args&&... args);

			// defined in luabind/detail/object.hpp
			template<typename PolicyList, typename... Args>
			object call(Args&&... args);

			explicit operator bool() const
			{
				lua_State* L = lua_proxy_traits<Derived>::interpreter(derived());
				if(!L) return 0;
				lua_proxy_traits<Derived>::unwrap(L, derived());
				detail::stack_pop pop(L, 1);
				return lua_toboolean(L, -1)==1;
			}

		private:
			Derived& derived() { return *static_cast<Derived*>(this); }
			Derived const& derived() const { return *static_cast<Derived const*>(this); }
		};

	}

	template<class ValueWrapper>
	std::string to_string(adl::lua_proxy_interface<ValueWrapper> const& v)
	{
		using namespace luabind;
		lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(static_cast<ValueWrapper const&>(v));
		detail::stack_pop pop(interpreter, 1);
		lua_proxy_traits<ValueWrapper>::unwrap(interpreter, static_cast<ValueWrapper const&>(v));
		char const* p = lua_tostring(interpreter, -1);
		std::size_t len = lua_rawlen(interpreter, -1);
		return std::string(p, len);
	}

	namespace detail
	{
		template<class T, class ValueWrapper, class Policies, class ErrorPolicy, class ReturnType >
		ReturnType object_cast_aux(ValueWrapper const& value_wrapper, T*, Policies*, ErrorPolicy error_policy, ReturnType*)
		{
			lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(value_wrapper);

#ifndef LUABIND_NO_ERROR_CHECKING
			if(!interpreter)
				return error_policy.handle_error(interpreter, typeid(void));
#endif
			lua_proxy_traits<ValueWrapper>::unwrap(interpreter, value_wrapper);
			detail::stack_pop pop(interpreter, 1);
			specialized_converter_policy_n<0, Policies, T, lua_to_cpp> cv;

#ifndef LUABIND_NO_ERROR_CHECKING
			if(cv.match(interpreter, decorated_type<T>(), -1)<0) {
				return error_policy.handle_error(interpreter, typeid(T));
			}
#endif
			return cv.to_cpp(interpreter, decorated_type<T>(), -1);
		}

		template<class T>
		struct throw_error_policy
		{
			T handle_error(lua_State* interpreter, type_id const& type_info)
			{
#ifndef LUABIND_NO_EXCEPTIONS
				throw cast_failed(interpreter, type_info);
#else
				cast_failed_callback_fun e = get_cast_failed_callback();
				if(e) e(interpreter, type_info);

				assert(0&&"object_cast failed. If you want to handle this error use "
					   "luabind::set_error_callback()");
				std::terminate();
#endif
				return *(typename std::remove_reference<T>::type*)0;
			}
		};

		template<class T>
		struct nothrow_error_policy
		{
			nothrow_error_policy(T rhs) : value(rhs) {}

			T handle_error(lua_State*, type_id const&)
			{
				return value;
			}
		private:
			T value;
		};
	} // namespace detail

	template<class T, class ValueWrapper> inline
	T object_cast(ValueWrapper const& value_wrapper)
	{
		return detail::object_cast_aux(value_wrapper, (T*) 0, (no_policies*) 0, detail::throw_error_policy<T>(), (T*) 0);
	}

	template<class T, class ValueWrapper, class Policies> inline
	T object_cast(ValueWrapper const& value_wrapper, Policies const&)
	{
		return detail::object_cast_aux(value_wrapper, (T*) 0, (Policies*) 0, detail::throw_error_policy<T>(), (T*) 0);
	}

	template<typename T, typename ValueWrapper, typename ReturnValue> inline
	ReturnValue object_cast_nothrow(ValueWrapper const& value_wrapper, ReturnValue default_value)
	{
		return detail::object_cast_aux(value_wrapper, (T*)0, (no_policies*)0, detail::nothrow_error_policy<ReturnValue>(default_value), (ReturnValue*)0);
	}

	template<typename T, typename ValueWrapper, typename Policies, typename ReturnValue> inline
	ReturnValue object_cast_nothrow(ValueWrapper const& value_wrapper, Policies const&, ReturnValue default_value)
	{
		return detail::object_cast_aux(value_wrapper, (T*)0, (Policies*)0, detail::nothrow_error_policy<ReturnValue>(default_value), (ReturnValue*)0);
	}

	template <class ValueWrapper>
	inline lua_CFunction tocfunction(ValueWrapper const& value)
	{
		lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(value);
		lua_proxy_traits<ValueWrapper>::unwrap(interpreter, value);
		detail::stack_pop pop(interpreter, 1);
		return lua_tocfunction(interpreter, -1);
	}

	template <class T, class ValueWrapper>
	inline T* touserdata(ValueWrapper const& value)
	{
		lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(value);

		lua_proxy_traits<ValueWrapper>::unwrap(interpreter, value);
		detail::stack_pop pop(interpreter, 1);
		return static_cast<T*>(lua_touserdata(interpreter, -1));
	}

}

#if LUA_VERSION_NUM < 502
# undef lua_compare
# undef LUA_OPEQ
# undef LUA_OPLT
# undef lua_rawlen
# undef lua_pushglobaltable
#endif

#endif

<commit_msg>Fix null pointer dereference when compiled with LUABIND_NO_ERROR_CHECKING.<commit_after>#ifndef LUA_PROXY_INTERFACE_HPP_INCLUDED
#define LUA_PROXY_INTERFACE_HPP_INCLUDED

#include <luabind/lua_proxy.hpp>
#include <luabind/detail/call_function.hpp>
#include <ostream>

#if LUA_VERSION_NUM < 502
# define lua_compare(L, index1, index2, fn) fn(L, index1, index2)
# define LUA_OPEQ lua_equal
# define LUA_OPLT lua_lessthan
# define lua_rawlen lua_objlen
# define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX)
#endif

namespace luabind {

	namespace detail
	{

		template<class T, typename... Policies>
		void push(lua_State* interpreter, T& value, policy_list<Policies...> const& = no_policies())
		{
			using PolicyList = policy_list<Policies...>;
			typedef T unwrapped_type; // = T; //typename apply_reference_wrapper<T>::type;
			using converter_type = specialized_converter_policy_n<0, PolicyList, T/*unwrapped_type*/, cpp_to_lua >;
			converter_type().to_lua(interpreter, implicit_cast<unwrapped_type&>(value));
		}

	} // namespace detail

	namespace adl {

		template <class T>
		class lua_proxy_interface;

		namespace is_object_interface_aux
		{
			typedef char(&yes)[1];
			typedef char(&no)[2];

			template <class T>
			yes check(lua_proxy_interface<T>*);
			no check(void*);

			template <class T>
			struct impl
			{
				static const bool value = sizeof(is_object_interface_aux::check((T*) 0))==sizeof(yes);
				typedef std::integral_constant<bool, value> type;
			};

		} // namespace is_object_interface_aux

		template <class T>
		struct is_object_interface :
			is_object_interface_aux::impl<T>::type
		{};

		template <class R, class T, class U>
		struct enable_binary
			: std::enable_if< is_object_interface<T>::value||is_object_interface<U>::value, R >
		{};

		template<class T, class U>
		int binary_interpreter(lua_State*& L, T const& lhs, U const& rhs, std::true_type, std::true_type)
		{
			L = lua_proxy_traits<T>::interpreter(lhs);
			lua_State* L2 = lua_proxy_traits<U>::interpreter(rhs);

			// you are comparing objects with different interpreters
			// that's not allowed.
			assert(L==L2||L==0||L2==0);

			// if the two objects we compare have different interpreters
			// then they

			if(L!=L2) return -1;
			if(L==0) return 1;
			return 0;
		}

		template<class T, class U>
		int binary_interpreter(lua_State*& L, T const& x, U const&, std::true_type, std::false_type)
		{
			L = lua_proxy_traits<T>::interpreter(x);
			return 0;
		}

		template<class T, class U>
		int binary_interpreter(lua_State*& L, T const&, U const& x, std::false_type, std::true_type)
		{
			L = lua_proxy_traits<U>::interpreter(x);
			return 0;
		}

		template<class T, class U>
		int binary_interpreter(lua_State*& L, T const& x, U const& y)
		{
			return binary_interpreter(L, x, y, is_lua_proxy_type<T>(), is_lua_proxy_type<U>());
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
		operator==(LHS const& lhs, RHS const& rhs)
		{
			lua_State* L = 0;
			switch(binary_interpreter(L, lhs, rhs)) {
			case  1: return true;
			case-1: return false;
			}
			assert(L);
			detail::stack_pop pop1(L, 1);
			detail::push(L, lhs);
			detail::stack_pop pop2(L, 1);
			detail::push(L, rhs);
			return lua_compare(L, -1, -2, LUA_OPEQ)!=0;
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
			operator<(LHS const& lhs, RHS const& rhs)
		{
			lua_State* L = 0;
			switch(binary_interpreter(L, lhs, rhs)) {
			case  1: return true;
			case-1: return false;
			}
			assert(L);
			detail::stack_pop pop1(L, 1);
			detail::push(L, lhs);
			detail::stack_pop pop2(L, 1);
			detail::push(L, rhs);
			return lua_compare(L, -1, -2, LUA_OPLT)!=0;
		}

		template<class ValueWrapper>
		std::ostream& operator<<(std::ostream& os, lua_proxy_interface<ValueWrapper> const& v)
		{
			using namespace luabind;
			lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(
				static_cast<ValueWrapper const&>(v));
			detail::stack_pop pop(interpreter, 1);
			lua_proxy_traits<ValueWrapper>::unwrap(interpreter, static_cast<ValueWrapper const&>(v));
			char const* p = lua_tostring(interpreter, -1);
			std::size_t len = lua_rawlen(interpreter, -1);
			os.write(p, len);
			//std::copy(p, p+len, std::ostream_iterator<char>(os));
			return os;
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
			operator>(LHS const& lhs, RHS const& rhs)
		{
			return !(lhs<rhs||lhs==rhs);
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
		operator<=(LHS const& lhs, RHS const& rhs)
		{
			return lhs<rhs||lhs==rhs;
		}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
		operator>=(LHS const& lhs, RHS const& rhs)
		{
			return !(lhs<rhs);
			}

		template<class LHS, class RHS>
		typename enable_binary<bool, LHS, RHS>::type
			operator!=(LHS const& lhs, RHS const& rhs)
		{
			return !(lhs==rhs);
		}

		template<class Derived>
		class lua_proxy_interface
		{
		public:
			~lua_proxy_interface() {}

			// defined in luabind/detail/object.hpp
			template<typename... Args>
			object operator()(Args&&... args);

			// defined in luabind/detail/object.hpp
			template<typename PolicyList, typename... Args>
			object call(Args&&... args);

			explicit operator bool() const
			{
				lua_State* L = lua_proxy_traits<Derived>::interpreter(derived());
				if(!L) return 0;
				lua_proxy_traits<Derived>::unwrap(L, derived());
				detail::stack_pop pop(L, 1);
				return lua_toboolean(L, -1)==1;
			}

		private:
			Derived& derived() { return *static_cast<Derived*>(this); }
			Derived const& derived() const { return *static_cast<Derived const*>(this); }
		};

	}

	template<class ValueWrapper>
	std::string to_string(adl::lua_proxy_interface<ValueWrapper> const& v)
	{
		using namespace luabind;
		lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(static_cast<ValueWrapper const&>(v));
		detail::stack_pop pop(interpreter, 1);
		lua_proxy_traits<ValueWrapper>::unwrap(interpreter, static_cast<ValueWrapper const&>(v));
		char const* p = lua_tostring(interpreter, -1);
		std::size_t len = lua_rawlen(interpreter, -1);
		return std::string(p, len);
	}

	namespace detail
	{
		template<class T, class ValueWrapper, class Policies, class ErrorPolicy, class ReturnType >
		ReturnType object_cast_aux(ValueWrapper const& value_wrapper, T*, Policies*, ErrorPolicy error_policy, ReturnType*)
		{
			lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(value_wrapper);

#ifndef LUABIND_NO_ERROR_CHECKING
			if(!interpreter)
				return error_policy.handle_error(interpreter, typeid(void));
#endif
			lua_proxy_traits<ValueWrapper>::unwrap(interpreter, value_wrapper);
			detail::stack_pop pop(interpreter, 1);
			specialized_converter_policy_n<0, Policies, T, lua_to_cpp> cv;

			if(cv.match(interpreter, decorated_type<T>(), -1)<0) {
				return error_policy.handle_error(interpreter, typeid(T));
			}
			return cv.to_cpp(interpreter, decorated_type<T>(), -1);
		}

		template<class T>
		struct throw_error_policy
		{
			T handle_error(lua_State* interpreter, type_id const& type_info)
			{
#ifndef LUABIND_NO_EXCEPTIONS
				throw cast_failed(interpreter, type_info);
#else
				cast_failed_callback_fun e = get_cast_failed_callback();
				if(e) e(interpreter, type_info);

				assert(0&&"object_cast failed. If you want to handle this error use "
					   "luabind::set_error_callback()");
				std::terminate();
#endif
				return *(typename std::remove_reference<T>::type*)0;
			}
		};

		template<class T>
		struct nothrow_error_policy
		{
			nothrow_error_policy(T rhs) : value(rhs) {}

			T handle_error(lua_State*, type_id const&)
			{
				return value;
			}
		private:
			T value;
		};
	} // namespace detail

	template<class T, class ValueWrapper> inline
	T object_cast(ValueWrapper const& value_wrapper)
	{
		return detail::object_cast_aux(value_wrapper, (T*) 0, (no_policies*) 0, detail::throw_error_policy<T>(), (T*) 0);
	}

	template<class T, class ValueWrapper, class Policies> inline
	T object_cast(ValueWrapper const& value_wrapper, Policies const&)
	{
		return detail::object_cast_aux(value_wrapper, (T*) 0, (Policies*) 0, detail::throw_error_policy<T>(), (T*) 0);
	}

	template<typename T, typename ValueWrapper, typename ReturnValue> inline
	ReturnValue object_cast_nothrow(ValueWrapper const& value_wrapper, ReturnValue default_value)
	{
		return detail::object_cast_aux(value_wrapper, (T*)0, (no_policies*)0, detail::nothrow_error_policy<ReturnValue>(default_value), (ReturnValue*)0);
	}

	template<typename T, typename ValueWrapper, typename Policies, typename ReturnValue> inline
	ReturnValue object_cast_nothrow(ValueWrapper const& value_wrapper, Policies const&, ReturnValue default_value)
	{
		return detail::object_cast_aux(value_wrapper, (T*)0, (Policies*)0, detail::nothrow_error_policy<ReturnValue>(default_value), (ReturnValue*)0);
	}

	template <class ValueWrapper>
	inline lua_CFunction tocfunction(ValueWrapper const& value)
	{
		lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(value);
		lua_proxy_traits<ValueWrapper>::unwrap(interpreter, value);
		detail::stack_pop pop(interpreter, 1);
		return lua_tocfunction(interpreter, -1);
	}

	template <class T, class ValueWrapper>
	inline T* touserdata(ValueWrapper const& value)
	{
		lua_State* interpreter = lua_proxy_traits<ValueWrapper>::interpreter(value);

		lua_proxy_traits<ValueWrapper>::unwrap(interpreter, value);
		detail::stack_pop pop(interpreter, 1);
		return static_cast<T*>(lua_touserdata(interpreter, -1));
	}

}

#if LUA_VERSION_NUM < 502
# undef lua_compare
# undef LUA_OPEQ
# undef LUA_OPLT
# undef lua_rawlen
# undef lua_pushglobaltable
#endif

#endif

<|endoftext|>


<commit_before>#include "GLRenderToImage.h"
#include "GLView.h"
#include <KrisLibrary/Logger.h>
#include <KrisLibrary/errors.h>
#include <memory.h>
#if HAVE_GLEW
#include <GL/glew.h>
#else
#include "GL.h"
#endif //HAVE_GLEW
using namespace std;
using namespace GLDraw;

#if HAVE_GLEW
  #ifndef GL_BGRA
  #ifndef GL_BGRA_EXT
  #error "GL_BGRA is not defined on your system?"
  #endif //GL_BGRA_EXT
  #define GL_BGRA GL_BGRA_EXT
  #endif //GL_BGRA
#endif // HAVE_GLEW

GLRenderToImage::GLRenderToImage()
  :width(0),height(0),color_tex(0),fb(0),depth_rb(0)
{}

GLRenderToImage::~GLRenderToImage()
{
  if(color_tex) glDeleteTextures(1, &color_tex);
#if HAVE_GLEW
  if(depth_rb) glDeleteRenderbuffersEXT(1, &depth_rb);
  if(fb) glDeleteFramebuffersEXT(1, &fb);
#endif //HAVE_GLEW
  color_tex = 0;
  depth_rb = 0;
  fb = 0;
}

bool GLRenderToImage::Setup(int w,int h)
{
#if HAVE_GLEW
  if(!GLEW_EXT_framebuffer_object) {
    GLenum err = glewInit();
    if (err != GLEW_OK)
    {
      glewExperimental=GL_TRUE;
      err = glewInit();
      if (GLEW_OK != err)
      {
        /* Problem: glewInit failed, something is seriously wrong. */
        LOG4CXX_WARN(KrisLibrary::logger(),"GLRenderToImage::glewInit() error: "<<glewGetErrorString(err));
        LOG4CXX_WARN(KrisLibrary::logger(),"  This usually happens when an OpenGL context has not been initialized.");
        return false;
      }

    }
    if(!GLEW_EXT_framebuffer_object) {
      return false;
    }
  }
  width = w;
  height = h;
  if(color_tex == 0) {
    //RGBA8 2D texture, 24 bit depth texture, 256x256
    glGenTextures(1, &color_tex);
    glBindTexture(GL_TEXTURE_2D, color_tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    //NULL means reserve texture memory, but texels are undefined
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
  }
  if(fb == 0) {
    //-------------------------
    glGenFramebuffersEXT(1, &fb);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
    //Attach 2D texture to this FBO
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0);
  }
  if(depth_rb == 0) {
    //-------------------------
    glGenRenderbuffersEXT(1, &depth_rb);
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, w, h);
    //-------------------------
    //Attach depth buffer to FBO
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
  }
  //-------------------------
  //Does the GPU support current FBO configuration?
  GLenum status;
  status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  switch(status)
  {
  case GL_FRAMEBUFFER_COMPLETE_EXT:
    break;
  default:
    //Delete resources
    glDeleteTextures(1, &color_tex);
    glDeleteRenderbuffersEXT(1, &depth_rb);
    //Bind 0, which means render to back buffer, as a result, fb is unbound
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    glDeleteFramebuffersEXT(1, &fb);
    color_tex = 0;
    depth_rb = 0;
    fb = 0;
    return false;
  }
  return true;
#else
  return false;
#endif //HAVE_GLEW
}

void GLRenderToImage::Begin(const Camera::Viewport& vp)
{
  Begin();
  GLView view;
  view.setViewport(vp);
  view.setCurrentGL();
}

void GLRenderToImage::Begin()
{
  if(!fb) return;
#if HAVE_GLEW
  //and now you can render to GL_TEXTURE_2D
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#endif
}

void GLRenderToImage::End()
{
#if HAVE_GLEW
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
#endif
}

void GLRenderToImage::GetRGBA(vector<unsigned int>& image)
{
  image.resize(width*height);
  glBindTexture(GL_TEXTURE_2D, color_tex);
  glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_INT_8_8_8_8,&image[0]);
  //OpenGL images start in lower left, so flip vertically
  int rowsize = 4*width;
  int stride = width;
  vector<unsigned char> temp(rowsize);
  for(int i=0;i<height/2;i++) {
    int iflip = height-1-i;
    memcpy(&temp[0],&image[i*stride],rowsize);
    memcpy(&image[i*stride],&image[iflip*stride],rowsize);
    memcpy(&image[iflip*stride],&temp[0],rowsize);
  }
  for(int i=0;i<width*height;i++) {
    unsigned char* argb = reinterpret_cast<unsigned char*>(&image[i]);
    unsigned char a=argb[0],b=argb[1],g=argb[2],r=argb[3];
    argb[0] = b;
    argb[1] = g;
    argb[2] = r;
    argb[3] = a;
  }
}
void GLRenderToImage::GetRGBA(vector<unsigned char>& image)
{
  image.resize(4*width*height);
  glBindTexture(GL_TEXTURE_2D, color_tex);
  glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_INT_8_8_8_8,&image[0]);
  //OpenGL images start in lower left, so flip vertically
  int rowsize = 4*width;
  int stride = 4*width;
  vector<unsigned char> temp(rowsize);
  for(int i=0;i<height/2;i++) {
    int iflip = height-1-i;
    memcpy(&temp[0],&image[i*stride],rowsize);
    memcpy(&image[i*stride],&image[iflip*stride],rowsize);
    memcpy(&image[iflip*stride],&temp[0],rowsize);
  }
}

void GLRenderToImage::GetRGBA(vector<vector<unsigned int> >& image)
{
  vector<unsigned int> pix;
  GetRGBA(pix);
  image.resize(height);
  for(int i=0;i<height;i++) {
    image[i].resize(width);
    copy(pix.begin()+i*width,pix.begin()+(i+1)*width,image[i].begin());
  }
}

void GLRenderToImage::GetRGBA(Image& image)
{
  image.initialize(width,height,Image::A8R8G8B8);
  vector<unsigned char> bytes;
  GetRGBA(bytes);
  Assert(bytes.size() == image.num_bytes);
  memcpy(image.data,&bytes[0],image.num_bytes);
  //switch the red and the blue
  for(int i=0;i<width*height;i++) {
    unsigned char* argb = image.data + i*4;
    unsigned char a=argb[0],r=argb[1],g=argb[2],b=argb[3];
    argb[0] = b;
    argb[1] = g;
    argb[2] = r;
    argb[3] = a;
  }
}

void GLRenderToImage::GetZBuffer(vector<float>& image)
{
#if HAVE_GLEW
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  image.resize(width*height);
  glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, &image[0]);
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

  int rowsize = sizeof(float)*width;
  int stride = width;
  vector<unsigned char> temp(rowsize);
  for(int i=0;i<height/2;i++) {
    int iflip = height-1-i;
    memcpy(&temp[0],&image[i*stride],rowsize);
    memcpy(&image[i*stride],&image[iflip*stride],rowsize);
    memcpy(&image[iflip*stride],&temp[0],rowsize);
  }
#endif
}

void GLRenderToImage::GetDepth(const Camera::Viewport& vp,vector<float>& image)
{
  GetZBuffer(image);
  //don't forget to flip vertically
  Real zmininv = 1.0/vp.n;
  Real zscale = (1.0/vp.n-1.0/vp.f);
  //nonlinear depth normalization
  //normal linear interpolation would give u = (z - zmin)/(zmax-zmin)
  //instead we gt u = (1/zmin-1/z)/(1/zmin-1/zmax)
  //so 1/z = 1/zmin - u(1/zmin-1/zmax)
  for(size_t i=0;i<image.size();i++) {
    if(image[i] == 1.0) { //nothing seen
      image[i] = vp.f;
    }
    else {
      image[i] = float(1.0/(zmininv - image[i]*zscale));
    }
  }
}

void GLRenderToImage::GetDepth(const Camera::Viewport& vp,vector<vector<float> >& image)
{
  vector<float> pix;
  GetDepth(vp,pix);
  image.resize(height);
  for(int i=0;i<height;i++) {
    image[i].resize(width);
    copy(pix.begin()+i*width,pix.begin()+(i+1)*width,image[i].begin());
  }
}

void GLRenderToImage::GetDepth(const Camera::Viewport& vp,Image& image)
{
  image.initialize(width,height,Image::FloatA);
  vector<float> pix;
  GetDepth(vp,pix);
  Assert(pix.size()*sizeof(float) == image.num_bytes);
  memcpy(image.data,&pix[0],image.num_bytes);
}
<commit_msg>Unbinding texture after drawing to texture<commit_after>#include "GLRenderToImage.h"
#include "GLView.h"
#include <KrisLibrary/Logger.h>
#include <KrisLibrary/errors.h>
#include <memory.h>
#if HAVE_GLEW
#include <GL/glew.h>
#else
#include "GL.h"
#endif //HAVE_GLEW
using namespace std;
using namespace GLDraw;

#if HAVE_GLEW
  #ifndef GL_BGRA
  #ifndef GL_BGRA_EXT
  #error "GL_BGRA is not defined on your system?"
  #endif //GL_BGRA_EXT
  #define GL_BGRA GL_BGRA_EXT
  #endif //GL_BGRA
#endif // HAVE_GLEW

GLRenderToImage::GLRenderToImage()
  :width(0),height(0),color_tex(0),fb(0),depth_rb(0)
{}

GLRenderToImage::~GLRenderToImage()
{
  if(color_tex) glDeleteTextures(1, &color_tex);
#if HAVE_GLEW
  if(depth_rb) glDeleteRenderbuffersEXT(1, &depth_rb);
  if(fb) glDeleteFramebuffersEXT(1, &fb);
#endif //HAVE_GLEW
  color_tex = 0;
  depth_rb = 0;
  fb = 0;
}

bool GLRenderToImage::Setup(int w,int h)
{
#if HAVE_GLEW
  if(!GLEW_EXT_framebuffer_object) {
    GLenum err = glewInit();
    if (err != GLEW_OK)
    {
      glewExperimental=GL_TRUE;
      err = glewInit();
      if (GLEW_OK != err)
      {
        /* Problem: glewInit failed, something is seriously wrong. */
        LOG4CXX_WARN(KrisLibrary::logger(),"GLRenderToImage::glewInit() error: "<<glewGetErrorString(err));
        LOG4CXX_WARN(KrisLibrary::logger(),"  This usually happens when an OpenGL context has not been initialized.");
        return false;
      }

    }
    if(!GLEW_EXT_framebuffer_object) {
      return false;
    }
  }
  width = w;
  height = h;
  if(color_tex == 0) {
    //RGBA8 2D texture, 24 bit depth texture, 256x256
    glGenTextures(1, &color_tex);
    glBindTexture(GL_TEXTURE_2D, color_tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    //NULL means reserve texture memory, but texels are undefined
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);
  }
  if(fb == 0) {
    //-------------------------
    glGenFramebuffersEXT(1, &fb);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
    //Attach 2D texture to this FBO
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0);
  }
  if(depth_rb == 0) {
    //-------------------------
    glGenRenderbuffersEXT(1, &depth_rb);
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, w, h);
    //-------------------------
    //Attach depth buffer to FBO
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
  }
  //-------------------------
  //Does the GPU support current FBO configuration?
  GLenum status;
  status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  switch(status)
  {
  case GL_FRAMEBUFFER_COMPLETE_EXT:
    break;
  default:
    //Delete resources
    glDeleteTextures(1, &color_tex);
    glDeleteRenderbuffersEXT(1, &depth_rb);
    //Bind 0, which means render to back buffer, as a result, fb is unbound
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    glDeleteFramebuffersEXT(1, &fb);
    color_tex = 0;
    depth_rb = 0;
    fb = 0;
    LOG4CXX_WARN(KrisLibrary::logger(),"GLRenderToImage: Some error setting up the framebuffer?");
    return false;
  }
  return true;
#else
  return false;
#endif //HAVE_GLEW
}

void GLRenderToImage::Begin(const Camera::Viewport& vp)
{
  Begin();
  GLView view;
  view.setViewport(vp);
  view.setCurrentGL();
}

void GLRenderToImage::Begin()
{
  if(!fb) return;
#if HAVE_GLEW
  //and now you can render to GL_TEXTURE_2D
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#endif
}

void GLRenderToImage::End()
{
#if HAVE_GLEW
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
#endif
}

void GLRenderToImage::GetRGBA(vector<unsigned int>& image)
{
  image.resize(width*height);
  glBindTexture(GL_TEXTURE_2D, color_tex);
  glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_INT_8_8_8_8,&image[0]);
  glBindTexture(GL_TEXTURE_2D,0);
  //OpenGL images start in lower left, so flip vertically
  int rowsize = 4*width;
  int stride = width;
  vector<unsigned char> temp(rowsize);
  for(int i=0;i<height/2;i++) {
    int iflip = height-1-i;
    memcpy(&temp[0],&image[i*stride],rowsize);
    memcpy(&image[i*stride],&image[iflip*stride],rowsize);
    memcpy(&image[iflip*stride],&temp[0],rowsize);
  }
  for(int i=0;i<width*height;i++) {
    unsigned char* argb = reinterpret_cast<unsigned char*>(&image[i]);
    unsigned char a=argb[0],b=argb[1],g=argb[2],r=argb[3];
    argb[0] = b;
    argb[1] = g;
    argb[2] = r;
    argb[3] = a;
  }
}
void GLRenderToImage::GetRGBA(vector<unsigned char>& image)
{
  image.resize(4*width*height);
  glBindTexture(GL_TEXTURE_2D, color_tex);
  glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_INT_8_8_8_8,&image[0]);
  glBindTexture(GL_TEXTURE_2D,0);
  //OpenGL images start in lower left, so flip vertically
  int rowsize = 4*width;
  int stride = 4*width;
  vector<unsigned char> temp(rowsize);
  for(int i=0;i<height/2;i++) {
    int iflip = height-1-i;
    memcpy(&temp[0],&image[i*stride],rowsize);
    memcpy(&image[i*stride],&image[iflip*stride],rowsize);
    memcpy(&image[iflip*stride],&temp[0],rowsize);
  }
}

void GLRenderToImage::GetRGBA(vector<vector<unsigned int> >& image)
{
  vector<unsigned int> pix;
  GetRGBA(pix);
  image.resize(height);
  for(int i=0;i<height;i++) {
    image[i].resize(width);
    copy(pix.begin()+i*width,pix.begin()+(i+1)*width,image[i].begin());
  }
}

void GLRenderToImage::GetRGBA(Image& image)
{
  image.initialize(width,height,Image::A8R8G8B8);
  vector<unsigned char> bytes;
  GetRGBA(bytes);
  Assert(bytes.size() == image.num_bytes);
  memcpy(image.data,&bytes[0],image.num_bytes);
  //switch the red and the blue
  for(int i=0;i<width*height;i++) {
    unsigned char* argb = image.data + i*4;
    unsigned char a=argb[0],r=argb[1],g=argb[2],b=argb[3];
    argb[0] = b;
    argb[1] = g;
    argb[2] = r;
    argb[3] = a;
  }
}

void GLRenderToImage::GetZBuffer(vector<float>& image)
{
#if HAVE_GLEW
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  image.resize(width*height);
  glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, &image[0]);
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

  int rowsize = sizeof(float)*width;
  int stride = width;
  vector<unsigned char> temp(rowsize);
  for(int i=0;i<height/2;i++) {
    int iflip = height-1-i;
    memcpy(&temp[0],&image[i*stride],rowsize);
    memcpy(&image[i*stride],&image[iflip*stride],rowsize);
    memcpy(&image[iflip*stride],&temp[0],rowsize);
  }
#endif
}

void GLRenderToImage::GetDepth(const Camera::Viewport& vp,vector<float>& image)
{
  GetZBuffer(image);
  //don't forget to flip vertically
  Real zmininv = 1.0/vp.n;
  Real zscale = (1.0/vp.n-1.0/vp.f);
  //nonlinear depth normalization
  //normal linear interpolation would give u = (z - zmin)/(zmax-zmin)
  //instead we gt u = (1/zmin-1/z)/(1/zmin-1/zmax)
  //so 1/z = 1/zmin - u(1/zmin-1/zmax)
  for(size_t i=0;i<image.size();i++) {
    if(image[i] == 1.0) { //nothing seen
      image[i] = vp.f;
    }
    else {
      image[i] = float(1.0/(zmininv - image[i]*zscale));
    }
  }
}

void GLRenderToImage::GetDepth(const Camera::Viewport& vp,vector<vector<float> >& image)
{
  vector<float> pix;
  GetDepth(vp,pix);
  image.resize(height);
  for(int i=0;i<height;i++) {
    image[i].resize(width);
    copy(pix.begin()+i*width,pix.begin()+(i+1)*width,image[i].begin());
  }
}

void GLRenderToImage::GetDepth(const Camera::Viewport& vp,Image& image)
{
  image.initialize(width,height,Image::FloatA);
  vector<float> pix;
  GetDepth(vp,pix);
  Assert(pix.size()*sizeof(float) == image.num_bytes);
  memcpy(image.data,&pix[0],image.num_bytes);
}
<|endoftext|>