<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2016 Couchbase, Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
#include <daemon/memcached.h>
#include <snappy-c.h>

void ship_mcbp_tap_log(McbpConnection* c) {
    bool more_data = true;
    bool send_data = false;
    bool disconnect = false;
    item* it;
    uint32_t bodylen;
    int ii = 0;

    c->addMsgHdr(true);
    /* @todo add check for buffer overflow of c->write.buf) */
    c->write.bytes = 0;
    c->write.curr = c->write.buf;

    auto tap_iterator = c->getTapIterator();
    do {
        /* @todo fixme! */
        void* engine;
        uint16_t nengine;
        uint8_t ttl;
        uint16_t tap_flags;
        uint32_t seqno;
        uint16_t vbucket;
        tap_event_t event;
        bool inflate = false;
        size_t inflated_length = 0;

        union {
            protocol_binary_request_tap_mutation mutation;
            protocol_binary_request_tap_delete del;
            protocol_binary_request_tap_flush flush;
            protocol_binary_request_tap_opaque opaque;
            protocol_binary_request_noop noop;
        } msg;
        item_info_holder info;

        if (ii++ == 10) {
            break;
        }

        event = tap_iterator(c->getBucketEngineAsV0(), c->getCookie(), &it,
                             &engine, &nengine, &ttl,
                             &tap_flags, &seqno, &vbucket);
        memset(&msg, 0, sizeof(msg));
        msg.opaque.message.header.request.magic = (uint8_t)PROTOCOL_BINARY_REQ;
        msg.opaque.message.header.request.opaque = htonl(seqno);
        msg.opaque.message.body.tap.enginespecific_length = htons(nengine);
        msg.opaque.message.body.tap.ttl = ttl;
        msg.opaque.message.body.tap.flags = htons(tap_flags);
        msg.opaque.message.header.request.extlen = 8;
        msg.opaque.message.header.request.vbucket = htons(vbucket);
        info.info.nvalue = IOV_MAX;

        switch (event) {
        case TAP_NOOP :
            send_data = true;
            msg.noop.message.header.request.opcode = PROTOCOL_BINARY_CMD_NOOP;
            msg.noop.message.header.request.extlen = 0;
            msg.noop.message.header.request.bodylen = htonl(0);
            memcpy(c->write.curr, msg.noop.bytes, sizeof(msg.noop.bytes));
            c->addIov(c->write.curr, sizeof(msg.noop.bytes));
            c->write.curr += sizeof(msg.noop.bytes);
            c->write.bytes += sizeof(msg.noop.bytes);
            break;
        case TAP_PAUSE :
            more_data = false;
            break;
        case TAP_CHECKPOINT_START:
        case TAP_CHECKPOINT_END:
        case TAP_MUTATION:
            if (!bucket_get_item_info(c, it, &info.info)) {
                bucket_release_item(c, it);
                LOG_WARNING(c, "%u: Failed to get item info", c->getId());
                break;
            }

            if (!c->reserveItem(it)) {
                bucket_release_item(c, it);
                LOG_WARNING(c, "%u: Failed to grow item array", c->getId());
                break;
            }
            send_data = true;

            if (event == TAP_CHECKPOINT_START) {
                msg.mutation.message.header.request.opcode =
                    PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START;
                tap_stats.sent.checkpoint_start++;
            } else if (event == TAP_CHECKPOINT_END) {
                msg.mutation.message.header.request.opcode =
                    PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END;
                tap_stats.sent.checkpoint_end++;
            } else if (event == TAP_MUTATION) {
                msg.mutation.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_MUTATION;
                tap_stats.sent.mutation++;
            }

            msg.mutation.message.header.request.cas = htonll(info.info.cas);
            msg.mutation.message.header.request.keylen = htons(info.info.nkey);
            msg.mutation.message.header.request.extlen = 16;
            if (c->isSupportsDatatype()) {
                msg.mutation.message.header.request.datatype = info.info.datatype;
            } else {
                inflate = mcbp::datatype::is_compressed(info.info.datatype);
                msg.mutation.message.header.request.datatype = 0;
            }

            bodylen = 16 + info.info.nkey + nengine;
            if ((tap_flags & TAP_FLAG_NO_VALUE) == 0) {
                if (inflate) {
                    if (snappy_uncompressed_length
                            (reinterpret_cast<const char*>(info.info.value[0].iov_base),
                             info.info.nbytes, &inflated_length) == SNAPPY_OK) {
                        bodylen += (uint32_t)inflated_length;
                    } else {
                        LOG_WARNING(c,
                                    "<%u Failed to determine inflated size. "
                                        "Sending as compressed",
                                    c->getId());
                        inflate = false;
                        bodylen += info.info.nbytes;
                    }
                } else {
                    bodylen += info.info.nbytes;
                }
            }
            msg.mutation.message.header.request.bodylen = htonl(bodylen);

            if ((tap_flags & TAP_FLAG_NETWORK_BYTE_ORDER) == 0) {
                msg.mutation.message.body.item.flags = htonl(info.info.flags);
            } else {
                msg.mutation.message.body.item.flags = info.info.flags;
            }
            msg.mutation.message.body.item.expiration = htonl(
                info.info.exptime);
            msg.mutation.message.body.tap.enginespecific_length = htons(
                nengine);
            msg.mutation.message.body.tap.ttl = ttl;
            msg.mutation.message.body.tap.flags = htons(tap_flags);
            memcpy(c->write.curr, msg.mutation.bytes,
                   sizeof(msg.mutation.bytes));

            c->addIov(c->write.curr, sizeof(msg.mutation.bytes));
            c->write.curr += sizeof(msg.mutation.bytes);
            c->write.bytes += sizeof(msg.mutation.bytes);

            if (nengine > 0) {
                memcpy(c->write.curr, engine, nengine);
                c->addIov(c->write.curr, nengine);
                c->write.curr += nengine;
                c->write.bytes += nengine;
            }

            c->addIov(info.info.key, info.info.nkey);
            if ((tap_flags & TAP_FLAG_NO_VALUE) == 0) {
                if (inflate) {
                    char* buf = reinterpret_cast<char*>(cb_malloc(
                        inflated_length));
                    if (buf == NULL) {
                        LOG_WARNING(c,
                                    "%u: FATAL: failed to allocate buffer "
                                        "of size %" PRIu64
                                        " to inflate object into. Shutting "
                                        "down connection",
                                    c->getId(), inflated_length);
                        c->setState(conn_closing);
                        return;
                    }
                    const char* body = reinterpret_cast<const char*>(info.info.value[0].iov_base);
                    size_t input_length = info.info.value[0].iov_len;
                    if (snappy_uncompress(body, input_length,
                                          buf, &inflated_length) == SNAPPY_OK) {
                        if (!c->pushTempAlloc(buf)) {
                            cb_free(buf);
                            LOG_WARNING(c,
                                        "%u: FATAL: failed to allocate space "
                                            "to keep temporary buffer",
                                        c->getId());
                            c->setState(conn_closing);
                            return;
                        }
                        c->addIov(buf, inflated_length);
                    } else {
                        cb_free(buf);
                        LOG_WARNING(c,
                                    "%u: FATAL: failed to inflate object. "
                                        "shutting down connection",
                                    c->getId());
                        c->setState(conn_closing);
                        return;
                    }
                } else {
                    int xx;
                    for (xx = 0; xx < info.info.nvalue; ++xx) {
                        c->addIov(info.info.value[xx].iov_base,
                                  info.info.value[xx].iov_len);
                    }
                }
            }

            break;
        case TAP_DELETION:
            /* This is a delete */
            if (!bucket_get_item_info(c, it, &info.info)) {
                bucket_release_item(c, it);
                LOG_WARNING(c, "%u: Failed to get item info", c->getId());
                break;
            }

            if (!c->reserveItem(it)) {
                bucket_release_item(c, it);
                LOG_WARNING(c, "%u: Failed to grow item array", c->getId());
                break;
            }
            send_data = true;
            msg.del.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_DELETE;
            msg.del.message.header.request.cas = htonll(info.info.cas);
            msg.del.message.header.request.keylen = htons(info.info.nkey);

            bodylen = 8 + info.info.nkey + nengine;
            if ((tap_flags & TAP_FLAG_NO_VALUE) == 0) {
                bodylen += info.info.nbytes;
            }
            msg.del.message.header.request.bodylen = htonl(bodylen);

            memcpy(c->write.curr, msg.del.bytes, sizeof(msg.del.bytes));
            c->addIov(c->write.curr, sizeof(msg.del.bytes));
            c->write.curr += sizeof(msg.del.bytes);
            c->write.bytes += sizeof(msg.del.bytes);

            if (nengine > 0) {
                memcpy(c->write.curr, engine, nengine);
                c->addIov(c->write.curr, nengine);
                c->write.curr += nengine;
                c->write.bytes += nengine;
            }

            c->addIov(info.info.key, info.info.nkey);
            if ((tap_flags & TAP_FLAG_NO_VALUE) == 0) {
                int xx;
                for (xx = 0; xx < info.info.nvalue; ++xx) {
                    c->addIov(info.info.value[xx].iov_base,
                              info.info.value[xx].iov_len);
                }
            }

            tap_stats.sent.del++;
            break;

        case TAP_DISCONNECT:
            disconnect = true;
            more_data = false;
            break;
        case TAP_VBUCKET_SET:
        case TAP_FLUSH:
        case TAP_OPAQUE:
            send_data = true;

            if (event == TAP_OPAQUE) {
                msg.flush.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_OPAQUE;
                tap_stats.sent.opaque++;
            } else if (event == TAP_FLUSH) {
                msg.flush.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_FLUSH;
                tap_stats.sent.flush++;
            } else if (event == TAP_VBUCKET_SET) {
                msg.flush.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET;
                msg.flush.message.body.tap.flags = htons(tap_flags);
                tap_stats.sent.vbucket_set++;
            }

            msg.flush.message.header.request.bodylen = htonl(8 + nengine);
            memcpy(c->write.curr, msg.flush.bytes, sizeof(msg.flush.bytes));
            c->addIov(c->write.curr, sizeof(msg.flush.bytes));
            c->write.curr += sizeof(msg.flush.bytes);
            c->write.bytes += sizeof(msg.flush.bytes);
            if (nengine > 0) {
                memcpy(c->write.curr, engine, nengine);
                c->addIov(c->write.curr, nengine);
                c->write.curr += nengine;
                c->write.bytes += nengine;
            }
            break;
        default:
            LOG_WARNING(c,
                        "%u: ship_tap_log: event (which is %d) is not a valid "
                            "tap_event_t - closing connection", event);
            c->setState(conn_closing);
            return;
        }
    } while (more_data);

    c->setEwouldblock(false);
    if (send_data) {
        c->setState(conn_mwrite);
        if (disconnect) {
            c->setWriteAndGo(conn_closing);
        } else {
            c->setWriteAndGo(conn_ship_log);
        }
    } else {
        if (disconnect) {
            c->setState(conn_closing);
        } else {
            /* No more items to ship to the slave at this time.. suspend.. */
            LOG_DEBUG(c, "%u: No more items in tap log.. waiting", c->getId());
            c->setEwouldblock(true);
        }
    }
}<commit_msg>Refactor: simplify logic, iov not supported<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2016 Couchbase, Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
#include <daemon/memcached.h>
#include <snappy-c.h>

void ship_mcbp_tap_log(McbpConnection* c) {
    bool more_data = true;
    bool send_data = false;
    bool disconnect = false;
    item* it;
    uint32_t bodylen;
    int ii = 0;

    c->addMsgHdr(true);
    /* @todo add check for buffer overflow of c->write.buf) */
    c->write.bytes = 0;
    c->write.curr = c->write.buf;

    auto tap_iterator = c->getTapIterator();
    do {
        /* @todo fixme! */
        void* engine;
        uint16_t nengine;
        uint8_t ttl;
        uint16_t tap_flags;
        uint32_t seqno;
        uint16_t vbucket;
        tap_event_t event;
        bool inflate = false;
        size_t inflated_length = 0;

        union {
            protocol_binary_request_tap_mutation mutation;
            protocol_binary_request_tap_delete del;
            protocol_binary_request_tap_flush flush;
            protocol_binary_request_tap_opaque opaque;
            protocol_binary_request_noop noop;
        } msg;
        item_info info;

        if (ii++ == 10) {
            break;
        }

        event = tap_iterator(c->getBucketEngineAsV0(), c->getCookie(), &it,
                             &engine, &nengine, &ttl,
                             &tap_flags, &seqno, &vbucket);
        memset(&msg, 0, sizeof(msg));
        msg.opaque.message.header.request.magic = (uint8_t)PROTOCOL_BINARY_REQ;
        msg.opaque.message.header.request.opaque = htonl(seqno);
        msg.opaque.message.body.tap.enginespecific_length = htons(nengine);
        msg.opaque.message.body.tap.ttl = ttl;
        msg.opaque.message.body.tap.flags = htons(tap_flags);
        msg.opaque.message.header.request.extlen = 8;
        msg.opaque.message.header.request.vbucket = htons(vbucket);
        info.nvalue = 1;

        switch (event) {
        case TAP_NOOP :
            send_data = true;
            msg.noop.message.header.request.opcode = PROTOCOL_BINARY_CMD_NOOP;
            msg.noop.message.header.request.extlen = 0;
            msg.noop.message.header.request.bodylen = htonl(0);
            memcpy(c->write.curr, msg.noop.bytes, sizeof(msg.noop.bytes));
            c->addIov(c->write.curr, sizeof(msg.noop.bytes));
            c->write.curr += sizeof(msg.noop.bytes);
            c->write.bytes += sizeof(msg.noop.bytes);
            break;
        case TAP_PAUSE :
            more_data = false;
            break;
        case TAP_CHECKPOINT_START:
        case TAP_CHECKPOINT_END:
        case TAP_MUTATION:
            if (!bucket_get_item_info(c, it, &info)) {
                bucket_release_item(c, it);
                LOG_WARNING(c, "%u: Failed to get item info", c->getId());
                break;
            }

            if (!c->reserveItem(it)) {
                bucket_release_item(c, it);
                LOG_WARNING(c, "%u: Failed to grow item array", c->getId());
                break;
            }
            send_data = true;

            if (event == TAP_CHECKPOINT_START) {
                msg.mutation.message.header.request.opcode =
                    PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START;
                tap_stats.sent.checkpoint_start++;
            } else if (event == TAP_CHECKPOINT_END) {
                msg.mutation.message.header.request.opcode =
                    PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END;
                tap_stats.sent.checkpoint_end++;
            } else if (event == TAP_MUTATION) {
                msg.mutation.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_MUTATION;
                tap_stats.sent.mutation++;
            }

            msg.mutation.message.header.request.cas = htonll(info.cas);
            msg.mutation.message.header.request.keylen = htons(info.nkey);
            msg.mutation.message.header.request.extlen = 16;
            if (c->isSupportsDatatype()) {
                msg.mutation.message.header.request.datatype = info.datatype;
            } else {
                inflate = mcbp::datatype::is_compressed(info.datatype);
                msg.mutation.message.header.request.datatype = 0;
            }

            bodylen = 16 + info.nkey + nengine;
            if ((tap_flags & TAP_FLAG_NO_VALUE) == 0) {
                if (inflate) {
                    if (snappy_uncompressed_length
                            (reinterpret_cast<const char*>(info.value[0].iov_base),
                             info.nbytes, &inflated_length) == SNAPPY_OK) {
                        bodylen += (uint32_t)inflated_length;
                    } else {
                        LOG_WARNING(c,
                                    "<%u Failed to determine inflated size. "
                                        "Sending as compressed",
                                    c->getId());
                        inflate = false;
                        bodylen += info.nbytes;
                    }
                } else {
                    bodylen += info.nbytes;
                }
            }
            msg.mutation.message.header.request.bodylen = htonl(bodylen);

            if ((tap_flags & TAP_FLAG_NETWORK_BYTE_ORDER) == 0) {
                msg.mutation.message.body.item.flags = htonl(info.flags);
            } else {
                msg.mutation.message.body.item.flags = info.flags;
            }
            msg.mutation.message.body.item.expiration = htonl(
                info.exptime);
            msg.mutation.message.body.tap.enginespecific_length = htons(
                nengine);
            msg.mutation.message.body.tap.ttl = ttl;
            msg.mutation.message.body.tap.flags = htons(tap_flags);
            memcpy(c->write.curr, msg.mutation.bytes,
                   sizeof(msg.mutation.bytes));

            c->addIov(c->write.curr, sizeof(msg.mutation.bytes));
            c->write.curr += sizeof(msg.mutation.bytes);
            c->write.bytes += sizeof(msg.mutation.bytes);

            if (nengine > 0) {
                memcpy(c->write.curr, engine, nengine);
                c->addIov(c->write.curr, nengine);
                c->write.curr += nengine;
                c->write.bytes += nengine;
            }

            c->addIov(info.key, info.nkey);
            if ((tap_flags & TAP_FLAG_NO_VALUE) == 0) {
                if (inflate) {
                    char* buf = reinterpret_cast<char*>(cb_malloc(
                        inflated_length));
                    if (buf == NULL) {
                        LOG_WARNING(c,
                                    "%u: FATAL: failed to allocate buffer "
                                        "of size %" PRIu64
                                        " to inflate object into. Shutting "
                                        "down connection",
                                    c->getId(), inflated_length);
                        c->setState(conn_closing);
                        return;
                    }
                    const char* body = reinterpret_cast<const char*>(info.value[0].iov_base);
                    size_t input_length = info.value[0].iov_len;
                    if (snappy_uncompress(body, input_length,
                                          buf, &inflated_length) == SNAPPY_OK) {
                        if (!c->pushTempAlloc(buf)) {
                            cb_free(buf);
                            LOG_WARNING(c,
                                        "%u: FATAL: failed to allocate space "
                                            "to keep temporary buffer",
                                        c->getId());
                            c->setState(conn_closing);
                            return;
                        }
                        c->addIov(buf, inflated_length);
                    } else {
                        cb_free(buf);
                        LOG_WARNING(c,
                                    "%u: FATAL: failed to inflate object. "
                                        "shutting down connection",
                                    c->getId());
                        c->setState(conn_closing);
                        return;
                    }
                } else {
                    c->addIov(info.value[0].iov_base, info.value[0].iov_len);
                }
            }

            break;
        case TAP_DELETION:
            /* This is a delete */
            if (!bucket_get_item_info(c, it, &info)) {
                bucket_release_item(c, it);
                LOG_WARNING(c, "%u: Failed to get item info", c->getId());
                break;
            }

            if (!c->reserveItem(it)) {
                bucket_release_item(c, it);
                LOG_WARNING(c, "%u: Failed to grow item array", c->getId());
                break;
            }
            send_data = true;
            msg.del.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_DELETE;
            msg.del.message.header.request.cas = htonll(info.cas);
            msg.del.message.header.request.keylen = htons(info.nkey);

            bodylen = 8 + info.nkey + nengine;
            if ((tap_flags & TAP_FLAG_NO_VALUE) == 0) {
                bodylen += info.nbytes;
            }
            msg.del.message.header.request.bodylen = htonl(bodylen);

            memcpy(c->write.curr, msg.del.bytes, sizeof(msg.del.bytes));
            c->addIov(c->write.curr, sizeof(msg.del.bytes));
            c->write.curr += sizeof(msg.del.bytes);
            c->write.bytes += sizeof(msg.del.bytes);

            if (nengine > 0) {
                memcpy(c->write.curr, engine, nengine);
                c->addIov(c->write.curr, nengine);
                c->write.curr += nengine;
                c->write.bytes += nengine;
            }

            c->addIov(info.key, info.nkey);
            if ((tap_flags & TAP_FLAG_NO_VALUE) == 0) {
                c->addIov(info.value[0].iov_base, info.value[0].iov_len);
            }

            tap_stats.sent.del++;
            break;

        case TAP_DISCONNECT:
            disconnect = true;
            more_data = false;
            break;
        case TAP_VBUCKET_SET:
        case TAP_FLUSH:
        case TAP_OPAQUE:
            send_data = true;

            if (event == TAP_OPAQUE) {
                msg.flush.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_OPAQUE;
                tap_stats.sent.opaque++;
            } else if (event == TAP_FLUSH) {
                msg.flush.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_FLUSH;
                tap_stats.sent.flush++;
            } else if (event == TAP_VBUCKET_SET) {
                msg.flush.message.header.request.opcode = PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET;
                msg.flush.message.body.tap.flags = htons(tap_flags);
                tap_stats.sent.vbucket_set++;
            }

            msg.flush.message.header.request.bodylen = htonl(8 + nengine);
            memcpy(c->write.curr, msg.flush.bytes, sizeof(msg.flush.bytes));
            c->addIov(c->write.curr, sizeof(msg.flush.bytes));
            c->write.curr += sizeof(msg.flush.bytes);
            c->write.bytes += sizeof(msg.flush.bytes);
            if (nengine > 0) {
                memcpy(c->write.curr, engine, nengine);
                c->addIov(c->write.curr, nengine);
                c->write.curr += nengine;
                c->write.bytes += nengine;
            }
            break;
        default:
            LOG_WARNING(c,
                        "%u: ship_tap_log: event (which is %d) is not a valid "
                            "tap_event_t - closing connection", event);
            c->setState(conn_closing);
            return;
        }
    } while (more_data);

    c->setEwouldblock(false);
    if (send_data) {
        c->setState(conn_mwrite);
        if (disconnect) {
            c->setWriteAndGo(conn_closing);
        } else {
            c->setWriteAndGo(conn_ship_log);
        }
    } else {
        if (disconnect) {
            c->setState(conn_closing);
        } else {
            /* No more items to ship to the slave at this time.. suspend.. */
            LOG_DEBUG(c, "%u: No more items in tap log.. waiting", c->getId());
            c->setEwouldblock(true);
        }
    }
}<|endoftext|>


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

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdLayerStackWidget.h"
#include "ui_mvdLayerStackWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)
#include <cassert>

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdGui.h"
#include "Gui/mvdLayerStackItemModel.h"

namespace mvd
{

/*
  TRANSLATOR mvd::LayerStackWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
LayerStackWidget
::LayerStackWidget( QWidget* parent, Qt::WindowFlags flags  ):
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::LayerStackWidget() )
{
  m_UI->setupUi( this );

  m_UI->reloadButton->setVisible( false );

  {
  QItemSelectionModel * ism = m_UI->treeView->selectionModel();

  m_UI->treeView->setModel( new LayerStackItemModel( m_UI->treeView ) );

  delete ism;
  ism = NULL;
  }

  InstallEventFilter( this );

  QObject::connect(
    m_UI->treeView->selectionModel(),
    SIGNAL( currentRowChanged( const QModelIndex &,  const QModelIndex & ) ),
    // to:
    this,
    SLOT( OnCurrentRowChanged( const QModelIndex &, const QModelIndex & ) )
    );

  QObject::connect(
    m_UI->treeView->selectionModel(),
    SIGNAL( selectionChanged( const QItemSelection &,  const QItemSelection & ) ),
    // to:
    this,
    SLOT( OnSelectionChanged( const QItemSelection &, const QItemSelection & ) )
    );

  QObject::connect(
    m_UI->topButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( TopButtonClicked() )
  );

  QObject::connect(
    m_UI->bottomButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( BottomButtonClicked() )
  );

  QObject::connect(
    m_UI->upButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( UpButtonClicked() )
  );

  QObject::connect(
    m_UI->downButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( DownButtonClicked() )
  );

  QObject::connect(
    m_UI->deleteButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( DeleteLayerRequested() )
  );

  QObject::connect(
    m_UI->projectionButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( ProjectionButtonClicked() )
  );

  QObject::connect(
    m_UI->applyButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( ApplyButtonClicked() )
  );
}

/*******************************************************************************/
LayerStackWidget
::~LayerStackWidget()
{
  delete m_UI;
  m_UI = NULL;
}

/*******************************************************************************/
bool
LayerStackWidget
::eventFilter( QObject * object, QEvent * event )
{
  assert( object==m_UI->treeView );
  assert( event!=NULL );

  if( object!=m_UI->treeView )
    return false;

  switch( event->type() )
    {
    //
    // KEY RELEASE
    case QEvent::KeyRelease :
    {
    QKeyEvent * keyEvent = dynamic_cast< QKeyEvent * >( event );
    assert( keyEvent!=NULL );

    switch( keyEvent->key() )
      {
      case Qt::Key_Delete:
	if( keyEvent->modifiers()==Qt::NoModifier )
	  {
	  emit DeleteLayerRequested();

	  return true;
	  }
	else if( keyEvent->modifiers()==Qt::ShiftModifier )
	  {
	  emit DeleteAllLayersRequested();

	  return true;
	  }
	break;
      }
    }
    break;
    //
    // MOUSE-WHEEL
    case QEvent::Wheel :
    {
    QWheelEvent * wheelEvent = dynamic_cast< QWheelEvent * >( event );
    assert( wheelEvent!=NULL );

    if( wheelEvent->modifiers()==Qt::ControlModifier )
      {
      emit RotateLayersRequested(
    	wheelEvent->delta() / (MOUSE_WHEEL_STEP_FACTOR * MOUSE_WHEEL_STEP_DEGREES)
      );

      return true;
      }
    }
    break;
    //
    // other.
    default:
      break;
    }

  return false;
}

/*******************************************************************************/
const LayerStackItemModel *
LayerStackWidget
::GetItemModel() const
{
  return const_cast< LayerStackWidget * >( this )->GetItemModel();
}

/*******************************************************************************/
LayerStackItemModel *
LayerStackWidget
::GetItemModel()
{
  assert(
    m_UI->treeView->model()==
    qobject_cast< LayerStackItemModel * >( m_UI->treeView->model() )
    );

  return qobject_cast< LayerStackItemModel * >( m_UI->treeView->model() );
}

/*******************************************************************************/
void
LayerStackWidget
::InstallEventFilter( QObject * filter )
{
  assert( m_UI!=NULL );
  assert( m_UI->treeView!=NULL );

  m_UI->treeView->installEventFilter( filter );
}

/*******************************************************************************/
// void
// LayerStackWidget
// ::SetModel( LayerStackItemModel * itemModel )
// {
//   // See http://qt-project.org/doc/qt-4.8/qabstractitemview.html#setModel .
//   QItemSelectionModel * itemSelectionModel = m_UI->treeView->selectionModel();

//   m_UI->treeView->setModel( itemModel );

//   itemModel->setParent( m_UI->treeView );

//   delete itemSelectionModel;
//   itemSelectionModel = NULL;
// }

/*******************************************************************************/
void
LayerStackWidget
::SetApplyEnabled( bool enabled )
{
  assert( m_UI->applyButton!=NULL );

  m_UI->applyButton->setEnabled( enabled );
}

/*******************************************************************************/
void
LayerStackWidget
::SetCurrent( int row )
{
  assert( m_UI->treeView->selectionModel()!=NULL );

  // if( m_UI->treeView->selectionModel()->currentIndex().row()==row )
  //   return;

  if( row<0 )
    m_UI->treeView->selectionModel()->clearSelection();

  else
    m_UI->treeView->selectionModel()->select(
      m_UI->treeView->model()->index( row, 1 ),
      QItemSelectionModel::ClearAndSelect |
      QItemSelectionModel::Rows
  );

  /*
  m_UI->treeView->selectionModel()->setCurrentIndex(
    m_UI->treeView->model()->index( row, 1 ),
    QItemSelectionModel::ClearAndSelect |
    // QItemSelectionModel::Current |
    QItemSelectionModel::Rows
  );
  */
}

/*******************************************************************************/
void
LayerStackWidget
::SetDeleteEnabled( bool enabled )
{
  assert( m_UI!=NULL );

  assert( m_UI->deleteButton!=NULL );

  m_UI->deleteButton->setEnabled( enabled );
}

/*******************************************************************************/
void
LayerStackWidget
::SetMoveEnabled( bool enabled )
{
  assert( m_UI!=NULL );

  assert( m_UI->upButton!=NULL );
  assert( m_UI->downButton!=NULL );
  assert( m_UI->topButton!=NULL );
  assert( m_UI->bottomButton!=NULL );

  m_UI->upButton->setEnabled( enabled );
  m_UI->downButton->setEnabled( enabled );
  m_UI->topButton->setEnabled( enabled );
  m_UI->bottomButton->setEnabled( enabled );
}

/*******************************************************************************/
void
LayerStackWidget
::SetProjectionEnabled( bool enabled )
{
  assert( m_UI!=NULL );

  assert( m_UI->projectionButton!=NULL );

  m_UI->projectionButton->setEnabled( enabled );
}

/*******************************************************************************/
void
LayerStackWidget
::SetReloadEnabled( bool enabled )
{
  assert( m_UI!=NULL );

  assert( m_UI->reloadButton!=NULL );

  m_UI->reloadButton->setEnabled( enabled );
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
LayerStackWidget
::OnCurrentRowChanged( const QModelIndex & current,
                       const QModelIndex & )
{
  // qDebug()
  //   << this
  //   << "::OnCurrentRowChange(" << current.row() << "," << previous.row() << ")";

  emit CurrentChanged( current.row() );
}

/*******************************************************************************/
void
LayerStackWidget
::OnSelectionChanged( const QItemSelection & selected,
                      const QItemSelection & )
{
  // qDebug()
  //   << this
  //   << "::OnSelectionChanged(" << selected << "," << deselected << ")";

  QModelIndexList indexes( selected.indexes() );
  // assert( indexes.empty() || indexes.size()==1 );

  emit SelectionChanged(
    indexes.empty()
    ? -1
    : indexes.front().row()
  );
}

} // end namespace 'mvd'
<commit_msg>ENH: Connected layer-stack delete-all layers button.<commit_after>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdLayerStackWidget.h"
#include "ui_mvdLayerStackWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)
#include <cassert>

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdGui.h"
#include "Gui/mvdLayerStackItemModel.h"

namespace mvd
{

/*
  TRANSLATOR mvd::LayerStackWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
LayerStackWidget
::LayerStackWidget( QWidget* parent, Qt::WindowFlags flags  ):
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::LayerStackWidget() )
{
  m_UI->setupUi( this );

  m_UI->reloadButton->setVisible( false );

  {
  QItemSelectionModel * ism = m_UI->treeView->selectionModel();

  m_UI->treeView->setModel( new LayerStackItemModel( m_UI->treeView ) );

  delete ism;
  ism = NULL;
  }

  InstallEventFilter( this );

  QObject::connect(
    m_UI->treeView->selectionModel(),
    SIGNAL( currentRowChanged( const QModelIndex &,  const QModelIndex & ) ),
    // to:
    this,
    SLOT( OnCurrentRowChanged( const QModelIndex &, const QModelIndex & ) )
    );

  QObject::connect(
    m_UI->treeView->selectionModel(),
    SIGNAL( selectionChanged( const QItemSelection &,  const QItemSelection & ) ),
    // to:
    this,
    SLOT( OnSelectionChanged( const QItemSelection &, const QItemSelection & ) )
    );

  QObject::connect(
    m_UI->topButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( TopButtonClicked() )
  );

  QObject::connect(
    m_UI->bottomButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( BottomButtonClicked() )
  );

  QObject::connect(
    m_UI->upButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( UpButtonClicked() )
  );

  QObject::connect(
    m_UI->downButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( DownButtonClicked() )
  );

  QObject::connect(
    m_UI->deleteButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( DeleteLayerRequested() )
  );

  QObject::connect(
    m_UI->deleteAllButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( DeleteAllLayersRequested() )
  );

  QObject::connect(
    m_UI->projectionButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( ProjectionButtonClicked() )
  );

  QObject::connect(
    m_UI->applyButton,
    SIGNAL( clicked() ),
    // to:
    this,
    SIGNAL( ApplyButtonClicked() )
  );
}

/*******************************************************************************/
LayerStackWidget
::~LayerStackWidget()
{
  delete m_UI;
  m_UI = NULL;
}

/*******************************************************************************/
bool
LayerStackWidget
::eventFilter( QObject * object, QEvent * event )
{
  assert( object==m_UI->treeView );
  assert( event!=NULL );

  if( object!=m_UI->treeView )
    return false;

  switch( event->type() )
    {
    //
    // KEY RELEASE
    case QEvent::KeyRelease :
    {
    QKeyEvent * keyEvent = dynamic_cast< QKeyEvent * >( event );
    assert( keyEvent!=NULL );

    switch( keyEvent->key() )
      {
      case Qt::Key_Delete:
	if( keyEvent->modifiers()==Qt::NoModifier )
	  {
	  emit DeleteLayerRequested();

	  return true;
	  }
	else if( keyEvent->modifiers()==Qt::ShiftModifier )
	  {
	  emit DeleteAllLayersRequested();

	  return true;
	  }
	break;
      }
    }
    break;
    //
    // MOUSE-WHEEL
    case QEvent::Wheel :
    {
    QWheelEvent * wheelEvent = dynamic_cast< QWheelEvent * >( event );
    assert( wheelEvent!=NULL );

    if( wheelEvent->modifiers()==Qt::ControlModifier )
      {
      emit RotateLayersRequested(
    	wheelEvent->delta() / (MOUSE_WHEEL_STEP_FACTOR * MOUSE_WHEEL_STEP_DEGREES)
      );

      return true;
      }
    }
    break;
    //
    // other.
    default:
      break;
    }

  return false;
}

/*******************************************************************************/
const LayerStackItemModel *
LayerStackWidget
::GetItemModel() const
{
  return const_cast< LayerStackWidget * >( this )->GetItemModel();
}

/*******************************************************************************/
LayerStackItemModel *
LayerStackWidget
::GetItemModel()
{
  assert(
    m_UI->treeView->model()==
    qobject_cast< LayerStackItemModel * >( m_UI->treeView->model() )
    );

  return qobject_cast< LayerStackItemModel * >( m_UI->treeView->model() );
}

/*******************************************************************************/
void
LayerStackWidget
::InstallEventFilter( QObject * filter )
{
  assert( m_UI!=NULL );
  assert( m_UI->treeView!=NULL );

  m_UI->treeView->installEventFilter( filter );
}

/*******************************************************************************/
// void
// LayerStackWidget
// ::SetModel( LayerStackItemModel * itemModel )
// {
//   // See http://qt-project.org/doc/qt-4.8/qabstractitemview.html#setModel .
//   QItemSelectionModel * itemSelectionModel = m_UI->treeView->selectionModel();

//   m_UI->treeView->setModel( itemModel );

//   itemModel->setParent( m_UI->treeView );

//   delete itemSelectionModel;
//   itemSelectionModel = NULL;
// }

/*******************************************************************************/
void
LayerStackWidget
::SetApplyEnabled( bool enabled )
{
  assert( m_UI->applyButton!=NULL );

  m_UI->applyButton->setEnabled( enabled );
}

/*******************************************************************************/
void
LayerStackWidget
::SetCurrent( int row )
{
  assert( m_UI->treeView->selectionModel()!=NULL );

  // if( m_UI->treeView->selectionModel()->currentIndex().row()==row )
  //   return;

  if( row<0 )
    m_UI->treeView->selectionModel()->clearSelection();

  else
    m_UI->treeView->selectionModel()->select(
      m_UI->treeView->model()->index( row, 1 ),
      QItemSelectionModel::ClearAndSelect |
      QItemSelectionModel::Rows
  );

  /*
  m_UI->treeView->selectionModel()->setCurrentIndex(
    m_UI->treeView->model()->index( row, 1 ),
    QItemSelectionModel::ClearAndSelect |
    // QItemSelectionModel::Current |
    QItemSelectionModel::Rows
  );
  */
}

/*******************************************************************************/
void
LayerStackWidget
::SetDeleteEnabled( bool enabled )
{
  assert( m_UI!=NULL );

  assert( m_UI->deleteButton!=NULL );

  m_UI->deleteButton->setEnabled( enabled );
}

/*******************************************************************************/
void
LayerStackWidget
::SetMoveEnabled( bool enabled )
{
  assert( m_UI!=NULL );

  assert( m_UI->upButton!=NULL );
  assert( m_UI->downButton!=NULL );
  assert( m_UI->topButton!=NULL );
  assert( m_UI->bottomButton!=NULL );

  m_UI->upButton->setEnabled( enabled );
  m_UI->downButton->setEnabled( enabled );
  m_UI->topButton->setEnabled( enabled );
  m_UI->bottomButton->setEnabled( enabled );
}

/*******************************************************************************/
void
LayerStackWidget
::SetProjectionEnabled( bool enabled )
{
  assert( m_UI!=NULL );

  assert( m_UI->projectionButton!=NULL );

  m_UI->projectionButton->setEnabled( enabled );
}

/*******************************************************************************/
void
LayerStackWidget
::SetReloadEnabled( bool enabled )
{
  assert( m_UI!=NULL );

  assert( m_UI->reloadButton!=NULL );

  m_UI->reloadButton->setEnabled( enabled );
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
LayerStackWidget
::OnCurrentRowChanged( const QModelIndex & current,
                       const QModelIndex & )
{
  // qDebug()
  //   << this
  //   << "::OnCurrentRowChange(" << current.row() << "," << previous.row() << ")";

  emit CurrentChanged( current.row() );
}

/*******************************************************************************/
void
LayerStackWidget
::OnSelectionChanged( const QItemSelection & selected,
                      const QItemSelection & )
{
  // qDebug()
  //   << this
  //   << "::OnSelectionChanged(" << selected << "," << deselected << ")";

  QModelIndexList indexes( selected.indexes() );
  // assert( indexes.empty() || indexes.size()==1 );

  emit SelectionChanged(
    indexes.empty()
    ? -1
    : indexes.front().row()
  );
}

} // end namespace 'mvd'
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkInformationKeyLookup.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

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

#include "vtkInformationKeyLookup.h"

#include "vtkObjectFactory.h"

vtkStandardNewMacro(vtkInformationKeyLookup)

//------------------------------------------------------------------------------
void vtkInformationKeyLookup::PrintSelf(std::ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "Registered Keys:\n";
  indent = indent.GetNextIndent();
  KeyMap &keys = Keys();
  for (KeyMap::iterator i = keys.begin(), iEnd = keys.end(); i != iEnd; ++i)
    {
    os << indent << i->first.first << "::" << i->first.second
       << " @" << i->second << "\n";
    }
}

//------------------------------------------------------------------------------
vtkInformationKey *vtkInformationKeyLookup::Find(const std::string &name,
                                                 const std::string &location)
{
  KeyMap &keys = Keys();
  KeyMap::iterator it = keys.find(std::make_pair(location, name));
  return it != keys.end() ? it->second : NULL;
}

//------------------------------------------------------------------------------
vtkInformationKeyLookup::vtkInformationKeyLookup()
{
}

//------------------------------------------------------------------------------
vtkInformationKeyLookup::~vtkInformationKeyLookup()
{
  // Keys are owned / cleaned up by the vtk*InformationKeyManagers.
}

//------------------------------------------------------------------------------
void vtkInformationKeyLookup::RegisterKey(vtkInformationKey *key,
                                          const std::string &name,
                                          const std::string &location)
{
  vtkInformationKeyLookup::Keys().insert(
        std::make_pair(std::make_pair(location, name), key));
}

//------------------------------------------------------------------------------
vtkInformationKeyLookup::KeyMap &vtkInformationKeyLookup::Keys()
{
  // Ensure that the map is initialized before using from other static
  // initializations:
  static vtkInformationKeyLookup::KeyMap keys;
  return keys;
}
<commit_msg>Print key types in vtkInformationKeyLookup::PrintSelf.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkInformationKeyLookup.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

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

#include "vtkInformationKeyLookup.h"

#include "vtkInformationKey.h"
#include "vtkObjectFactory.h"

vtkStandardNewMacro(vtkInformationKeyLookup)

//------------------------------------------------------------------------------
void vtkInformationKeyLookup::PrintSelf(std::ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "Registered Keys:\n";
  indent = indent.GetNextIndent();
  KeyMap &keys = Keys();
  for (KeyMap::iterator i = keys.begin(), iEnd = keys.end(); i != iEnd; ++i)
    {
    os << indent << i->first.first << "::" << i->first.second
       << " @" << i->second << " (" << i->second->GetClassName() << ")\n";
    }
}

//------------------------------------------------------------------------------
vtkInformationKey *vtkInformationKeyLookup::Find(const std::string &name,
                                                 const std::string &location)
{
  KeyMap &keys = Keys();
  KeyMap::iterator it = keys.find(std::make_pair(location, name));
  return it != keys.end() ? it->second : NULL;
}

//------------------------------------------------------------------------------
vtkInformationKeyLookup::vtkInformationKeyLookup()
{
}

//------------------------------------------------------------------------------
vtkInformationKeyLookup::~vtkInformationKeyLookup()
{
  // Keys are owned / cleaned up by the vtk*InformationKeyManagers.
}

//------------------------------------------------------------------------------
void vtkInformationKeyLookup::RegisterKey(vtkInformationKey *key,
                                          const std::string &name,
                                          const std::string &location)
{
  vtkInformationKeyLookup::Keys().insert(
        std::make_pair(std::make_pair(location, name), key));
}

//------------------------------------------------------------------------------
vtkInformationKeyLookup::KeyMap &vtkInformationKeyLookup::Keys()
{
  // Ensure that the map is initialized before using from other static
  // initializations:
  static vtkInformationKeyLookup::KeyMap keys;
  return keys;
}
<|endoftext|>


<commit_before>#include "mitkDICOMFileReader.h"
#include <itkImageFileReader.h>

extern "C"
{
#include "ipDicom/ipDicom.h"
}

void mitk::DICOMFileReader::GenerateOutputInformation()
{
  mitk::Image::Pointer output = this->GetOutput();

  if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
    return;

  itkDebugMacro(<<"Reading file for GenerateOutputInformation()" << m_FileName);

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_FileName == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
  }

  if( m_FileName != "")
  {
    ipUInt4_t header_size;
    ipUInt4_t image_size;
    ipUInt1_t *header = NULL;
    unsigned char *image = NULL;
    ipBool_t color=ipFalse;
    outputfile_name = m_FileName;
    dicomGetHeaderAndImage( const_cast<char *>(m_FileName.c_str()),
      &header, &header_size,
      &image, &image_size );

    if( !image )
      exit(-1);
    pic = _dicomToPic( header, header_size,
      image, image_size, color );
    pic->dim--;

    if( pic == NULL)
    {
      itk::ImageFileReaderException e(__FILE__, __LINE__);
      itk::OStringStream msg;
      msg << " Could not read file "
        << outputfile_name.c_str();
      e.SetDescription(msg.str().c_str());
      throw e;
      return;
    }

    output->Initialize(pic);
  }

  m_ReadHeaderTime.Modified();
}

//##ModelId=3E187255016C
void mitk::DICOMFileReader::GenerateData()
{
  mitk::Image::Pointer output = this->GetOutput();

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_FileName == "" && m_FilePrefix == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
  }

  if( m_FileName != "")
  {

    //left to right handed conversion
    if(pic->dim==3)
    {
      ipPicDescriptor* slice=ipPicCopyHeader(pic, NULL);
      slice->dim=2;
      int size=_ipPicSize(slice);
      slice->data=malloc(size);
      unsigned char *p_first=(unsigned char *)pic->data;
      unsigned char *p_last=(unsigned char *)pic->data;
      p_last+=size*(pic->n[2]-1);

      int i, smid=pic->n[2]/2;
      for(i=0; i<smid;++i,p_last-=size, p_first+=size)
      {
        memcpy(slice->data, p_last, size);
        memcpy(p_last, p_first, size);
        memcpy(p_first, slice->data, size);
      }
      ipPicFree(slice);
    }
    output->SetPicVolume(pic);
  }
}

//##ModelId=3E1874D202D0
mitk::DICOMFileReader::DICOMFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}

//##ModelId=3E1874E50179
mitk::DICOMFileReader::~DICOMFileReader()
{
}
<commit_msg>exception instead of exit<commit_after>#include "mitkDICOMFileReader.h"
#include <itkImageFileReader.h>

extern "C"
{
#include "ipDicom/ipDicom.h"
}

void mitk::DICOMFileReader::GenerateOutputInformation()
{
  mitk::Image::Pointer output = this->GetOutput();

  if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
    return;

  itkDebugMacro(<<"Reading file for GenerateOutputInformation()" << m_FileName);

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_FileName == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
  }

  if( m_FileName != "")
  {
    ipUInt4_t header_size;
    ipUInt4_t image_size;
    ipUInt1_t *header = NULL;
    unsigned char *image = NULL;
    ipBool_t color=ipFalse;
    outputfile_name = m_FileName;
    dicomGetHeaderAndImage( const_cast<char *>(m_FileName.c_str()),
      &header, &header_size,
      &image, &image_size );

    if( !header )
      throw itk::ImageFileReaderException(__FILE__, __LINE__, "Could not get header.");;
    if( !image )
      throw itk::ImageFileReaderException(__FILE__, __LINE__, "Could not get image.");;
    pic = _dicomToPic( header, header_size,
      image, image_size, color );
    pic->dim--;

    if( pic == NULL)
    {
      itk::ImageFileReaderException e(__FILE__, __LINE__);
      itk::OStringStream msg;
      msg << " Could not read file "
        << outputfile_name.c_str();
      e.SetDescription(msg.str().c_str());
      throw e;
      return;
    }

    output->Initialize(pic);
  }

  m_ReadHeaderTime.Modified();
}

//##ModelId=3E187255016C
void mitk::DICOMFileReader::GenerateData()
{
  mitk::Image::Pointer output = this->GetOutput();

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_FileName == "" && m_FilePrefix == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
  }

  if( m_FileName != "")
  {

    //left to right handed conversion
    if(pic->dim==3)
    {
      ipPicDescriptor* slice=ipPicCopyHeader(pic, NULL);
      slice->dim=2;
      int size=_ipPicSize(slice);
      slice->data=malloc(size);
      unsigned char *p_first=(unsigned char *)pic->data;
      unsigned char *p_last=(unsigned char *)pic->data;
      p_last+=size*(pic->n[2]-1);

      int i, smid=pic->n[2]/2;
      for(i=0; i<smid;++i,p_last-=size, p_first+=size)
      {
        memcpy(slice->data, p_last, size);
        memcpy(p_last, p_first, size);
        memcpy(p_first, slice->data, size);
      }
      ipPicFree(slice);
    }
    output->SetPicVolume(pic);
  }
}

//##ModelId=3E1874D202D0
mitk::DICOMFileReader::DICOMFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}

//##ModelId=3E1874E50179
mitk::DICOMFileReader::~DICOMFileReader()
{
}
<|endoftext|>


<commit_before>/*
 Copyright (C) 2011 by Ivan Safrin

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "PolyScreenMesh.h"
#include "PolyCoreServices.h"
#include "PolyMaterialManager.h"
#include "PolyMesh.h"
#include "PolyRenderer.h"

using namespace Polycode;

ScreenMesh::ScreenMesh(const String& fileName) : ScreenEntity(), texture(NULL) {
	mesh = new Mesh(fileName);
}

ScreenMesh::ScreenMesh(int meshType) : ScreenEntity(), texture(NULL) {
	mesh = new Mesh(meshType);
}

ScreenMesh::~ScreenMesh() {

}

Mesh *ScreenMesh::getMesh() const {
	return mesh;
}

Texture *ScreenMesh::getTexture() const {
	return texture;
}

void ScreenMesh::setTexture(Texture *texture) {
	this->texture = texture;
}

void ScreenMesh::loadTexture(const String& fileName) {
	texture = CoreServices::getInstance()->getMaterialManager()->createTextureFromFile(fileName, true, false);
}

void ScreenMesh::loadTexture(Image *image) {
	texture = CoreServices::getInstance()->getMaterialManager()->createTextureFromImage(image, true, false);
}

void ScreenMesh::Render() {
	Renderer *renderer = CoreServices::getInstance()->getRenderer();
	renderer->setTexture(texture);
	if(mesh->useVertexColors) {
		renderer->pushDataArrayForMesh(mesh, RenderDataArray::COLOR_DATA_ARRAY);
	}
	renderer->pushDataArrayForMesh(mesh, RenderDataArray::VERTEX_DATA_ARRAY);
	renderer->pushDataArrayForMesh(mesh, RenderDataArray::TEXCOORD_DATA_ARRAY);
	renderer->drawArrays(mesh->getMeshType());
}
<commit_msg>ScreenMesh wasn't deleting mesh<commit_after>/*
 Copyright (C) 2011 by Ivan Safrin

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "PolyScreenMesh.h"
#include "PolyCoreServices.h"
#include "PolyMaterialManager.h"
#include "PolyMesh.h"
#include "PolyRenderer.h"

using namespace Polycode;

ScreenMesh::ScreenMesh(const String& fileName) : ScreenEntity(), texture(NULL) {
	mesh = new Mesh(fileName);
}

ScreenMesh::ScreenMesh(int meshType) : ScreenEntity(), texture(NULL) {
	mesh = new Mesh(meshType);
}

ScreenMesh::~ScreenMesh() {
	delete mesh;
	// TODO: Should have ownsTexture field?
}

Mesh *ScreenMesh::getMesh() const {
	return mesh;
}

Texture *ScreenMesh::getTexture() const {
	return texture;
}

void ScreenMesh::setTexture(Texture *texture) {
	this->texture = texture;
}

void ScreenMesh::loadTexture(const String& fileName) {
	texture = CoreServices::getInstance()->getMaterialManager()->createTextureFromFile(fileName, true, false);
}

void ScreenMesh::loadTexture(Image *image) {
	texture = CoreServices::getInstance()->getMaterialManager()->createTextureFromImage(image, true, false);
}

void ScreenMesh::Render() {
	Renderer *renderer = CoreServices::getInstance()->getRenderer();
	renderer->setTexture(texture);
	if(mesh->useVertexColors) {
		renderer->pushDataArrayForMesh(mesh, RenderDataArray::COLOR_DATA_ARRAY);
	}
	renderer->pushDataArrayForMesh(mesh, RenderDataArray::VERTEX_DATA_ARRAY);
	renderer->pushDataArrayForMesh(mesh, RenderDataArray::TEXCOORD_DATA_ARRAY);
	renderer->drawArrays(mesh->getMeshType());
}
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/base/logging.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/objects/xthread.h"
#include "xenia/kernel/objects/xsemaphore.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xboxkrnl_private.h"
#include "xenia/kernel/xobject.h"
#include "xenia/xbox.h"

namespace xe {
namespace kernel {

SHIM_CALL ObOpenObjectByName_shim(PPCContext* ppc_context,
                                  KernelState* kernel_state) {
  // r3 = ptr to info?
  //   +0 = -4
  //   +4 = name ptr
  //   +8 = 0
  // r4 = ExEventObjectType | ExSemaphoreObjectType | ExTimerObjectType
  // r5 = 0
  // r6 = out_ptr (handle?)
  uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(0);
  uint32_t object_type_ptr = SHIM_GET_ARG_32(1);
  uint32_t unk = SHIM_GET_ARG_32(2);
  uint32_t handle_ptr = SHIM_GET_ARG_32(3);

  uint32_t name_str_ptr = SHIM_MEM_32(obj_attributes_ptr + 4);
  X_ANSI_STRING name_str(SHIM_MEM_BASE, name_str_ptr);
  auto name = name_str.to_string();

  XELOGD("ObOpenObjectByName(%.8X(name=%s), %.8X, %.8X, %.8X)",
         obj_attributes_ptr, name.c_str(), object_type_ptr, unk, handle_ptr);

  X_HANDLE handle = X_INVALID_HANDLE_VALUE;
  X_STATUS result =
      kernel_state->object_table()->GetObjectByName(name, &handle);
  if (XSUCCEEDED(result)) {
    SHIM_SET_MEM_32(handle_ptr, handle);
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* ppc_context,
                                         KernelState* kernel_state) {
  uint32_t handle = SHIM_GET_ARG_32(0);
  uint32_t object_type_ptr = SHIM_GET_ARG_32(1);
  uint32_t out_object_ptr = SHIM_GET_ARG_32(2);

  XELOGD("ObReferenceObjectByHandle(%.8X, %.8X, %.8X)", handle, object_type_ptr,
         out_object_ptr);

  X_STATUS result = X_STATUS_SUCCESS;

  auto object = kernel_state->object_table()->LookupObject<XObject>(handle);
  if (object) {
    // TODO(benvanik): verify type with object_type_ptr

    // TODO(benvanik): get native value, if supported.
    uint32_t native_ptr;
    switch (object_type_ptr) {
      case 0x00000000: {  // whatever?
        switch (object->type()) {
          // TODO(benvanik): need to track native_ptr in XObject, allocate as
          // needed?
          /*case XObject::kTypeEvent: {
            XEvent* ev = (XEvent*)object;
          } break;*/
          case XObject::kTypeThread: {
            auto thread = object.get<XThread>();
            native_ptr = thread->guest_object();
          } break;
          default: {
            assert_unhandled_case(object->type());
            native_ptr = 0xDEADF00D;
          } break;
        }
      } break;
      case 0xD017BEEF: {  // ExSemaphoreObjectType
        assert(object->type() == XObject::kTypeSemaphore);
        auto sem = object.get<XSemaphore>();

        native_ptr = sem->guest_object();

        // TODO(benvanik): implement.
        assert_unhandled_case(object_type_ptr);
        native_ptr = 0xDEADF00D;
      } break;
      case 0xD01BBEEF: {  // ExThreadObjectType
        assert(object->type() == XObject::kTypeThread);
        auto thread = object.get<XThread>();

        native_ptr = thread->guest_object();
      } break;
      default: {
        assert_unhandled_case(object_type_ptr);
        native_ptr = 0xDEADF00D;
      } break;
    }

    // Caller takes the reference.
    // It's released in ObDereferenceObject.
    object->Retain();
    if (out_object_ptr) {
      SHIM_SET_MEM_32(out_object_ptr, native_ptr);
    }
  } else {
    result = X_STATUS_INVALID_HANDLE;
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL ObDereferenceObject_shim(PPCContext* ppc_context,
                                   KernelState* kernel_state) {
  uint32_t native_ptr = SHIM_GET_ARG_32(0);

  XELOGD("ObDereferenceObject(%.8X)", native_ptr);

  // Check if a dummy value from ObReferenceObjectByHandle.
  if (native_ptr == 0xDEADF00D) {
    SHIM_SET_RETURN_32(0);
    return;
  }

  void* object_ptr = SHIM_MEM_ADDR(native_ptr);
  auto object = XObject::GetNativeObject<XObject>(kernel_state, object_ptr);
  if (object) {
    object->Release();
  }

  SHIM_SET_RETURN_32(0);
}

dword_result_t NtDuplicateObject(dword_t handle, lpdword_t new_handle_ptr,
                                 dword_t options) {
  // NOTE: new_handle_ptr can be zero to just close a handle.
  // NOTE: this function seems to be used to get the current thread handle
  //       (passed handle=-2).
  // This function actually just creates a new handle to the same object.
  // Most games use it to get real handles to the current thread or whatever.

  X_HANDLE new_handle = X_INVALID_HANDLE_VALUE;
  X_STATUS result =
      kernel_state()->object_table()->DuplicateHandle(handle, &new_handle);

  if (new_handle_ptr) {
    *new_handle_ptr = new_handle;
  }

  if (options == 1 /* DUPLICATE_CLOSE_SOURCE */) {
    // Always close the source object.
    kernel_state()->object_table()->RemoveHandle(handle);
  }

  return result;
}
DECLARE_XBOXKRNL_EXPORT(NtDuplicateObject, ExportTag::kImplemented);

dword_result_t NtClose(dword_t handle) {
  return kernel_state()->object_table()->RemoveHandle(handle);
}
DECLARE_XBOXKRNL_EXPORT(NtClose, ExportTag::kImplemented);

}  // namespace kernel
}  // namespace xe

void xe::kernel::xboxkrnl::RegisterObExports(
    xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {
  SHIM_SET_MAPPING("xboxkrnl.exe", ObOpenObjectByName, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", ObReferenceObjectByHandle, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", ObDereferenceObject, state);
}
<commit_msg>Whoops<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/base/logging.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/objects/xthread.h"
#include "xenia/kernel/objects/xsemaphore.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xboxkrnl_private.h"
#include "xenia/kernel/xobject.h"
#include "xenia/xbox.h"

namespace xe {
namespace kernel {

SHIM_CALL ObOpenObjectByName_shim(PPCContext* ppc_context,
                                  KernelState* kernel_state) {
  // r3 = ptr to info?
  //   +0 = -4
  //   +4 = name ptr
  //   +8 = 0
  // r4 = ExEventObjectType | ExSemaphoreObjectType | ExTimerObjectType
  // r5 = 0
  // r6 = out_ptr (handle?)
  uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(0);
  uint32_t object_type_ptr = SHIM_GET_ARG_32(1);
  uint32_t unk = SHIM_GET_ARG_32(2);
  uint32_t handle_ptr = SHIM_GET_ARG_32(3);

  uint32_t name_str_ptr = SHIM_MEM_32(obj_attributes_ptr + 4);
  X_ANSI_STRING name_str(SHIM_MEM_BASE, name_str_ptr);
  auto name = name_str.to_string();

  XELOGD("ObOpenObjectByName(%.8X(name=%s), %.8X, %.8X, %.8X)",
         obj_attributes_ptr, name.c_str(), object_type_ptr, unk, handle_ptr);

  X_HANDLE handle = X_INVALID_HANDLE_VALUE;
  X_STATUS result =
      kernel_state->object_table()->GetObjectByName(name, &handle);
  if (XSUCCEEDED(result)) {
    SHIM_SET_MEM_32(handle_ptr, handle);
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* ppc_context,
                                         KernelState* kernel_state) {
  uint32_t handle = SHIM_GET_ARG_32(0);
  uint32_t object_type_ptr = SHIM_GET_ARG_32(1);
  uint32_t out_object_ptr = SHIM_GET_ARG_32(2);

  XELOGD("ObReferenceObjectByHandle(%.8X, %.8X, %.8X)", handle, object_type_ptr,
         out_object_ptr);

  X_STATUS result = X_STATUS_SUCCESS;

  auto object = kernel_state->object_table()->LookupObject<XObject>(handle);
  if (object) {
    // TODO(benvanik): verify type with object_type_ptr

    // TODO(benvanik): get native value, if supported.
    uint32_t native_ptr;
    switch (object_type_ptr) {
      case 0x00000000: {  // whatever?
        switch (object->type()) {
          // TODO(benvanik): need to track native_ptr in XObject, allocate as
          // needed?
          /*case XObject::kTypeEvent: {
            XEvent* ev = (XEvent*)object;
          } break;*/
          case XObject::kTypeThread: {
            auto thread = object.get<XThread>();
            native_ptr = thread->guest_object();
          } break;
          default: {
            assert_unhandled_case(object->type());
            native_ptr = 0xDEADF00D;
          } break;
        }
      } break;
      case 0xD017BEEF: {  // ExSemaphoreObjectType
        assert(object->type() == XObject::kTypeSemaphore);
        auto sem = object.get<XSemaphore>();

        native_ptr = sem->guest_object();
      } break;
      case 0xD01BBEEF: {  // ExThreadObjectType
        assert(object->type() == XObject::kTypeThread);
        auto thread = object.get<XThread>();

        native_ptr = thread->guest_object();
      } break;
      default: {
        assert_unhandled_case(object_type_ptr);
        native_ptr = 0xDEADF00D;
      } break;
    }

    // Caller takes the reference.
    // It's released in ObDereferenceObject.
    object->Retain();
    if (out_object_ptr) {
      SHIM_SET_MEM_32(out_object_ptr, native_ptr);
    }
  } else {
    result = X_STATUS_INVALID_HANDLE;
  }

  SHIM_SET_RETURN_32(result);
}

SHIM_CALL ObDereferenceObject_shim(PPCContext* ppc_context,
                                   KernelState* kernel_state) {
  uint32_t native_ptr = SHIM_GET_ARG_32(0);

  XELOGD("ObDereferenceObject(%.8X)", native_ptr);

  // Check if a dummy value from ObReferenceObjectByHandle.
  if (native_ptr == 0xDEADF00D) {
    SHIM_SET_RETURN_32(0);
    return;
  }

  void* object_ptr = SHIM_MEM_ADDR(native_ptr);
  auto object = XObject::GetNativeObject<XObject>(kernel_state, object_ptr);
  if (object) {
    object->Release();
  }

  SHIM_SET_RETURN_32(0);
}

dword_result_t NtDuplicateObject(dword_t handle, lpdword_t new_handle_ptr,
                                 dword_t options) {
  // NOTE: new_handle_ptr can be zero to just close a handle.
  // NOTE: this function seems to be used to get the current thread handle
  //       (passed handle=-2).
  // This function actually just creates a new handle to the same object.
  // Most games use it to get real handles to the current thread or whatever.

  X_HANDLE new_handle = X_INVALID_HANDLE_VALUE;
  X_STATUS result =
      kernel_state()->object_table()->DuplicateHandle(handle, &new_handle);

  if (new_handle_ptr) {
    *new_handle_ptr = new_handle;
  }

  if (options == 1 /* DUPLICATE_CLOSE_SOURCE */) {
    // Always close the source object.
    kernel_state()->object_table()->RemoveHandle(handle);
  }

  return result;
}
DECLARE_XBOXKRNL_EXPORT(NtDuplicateObject, ExportTag::kImplemented);

dword_result_t NtClose(dword_t handle) {
  return kernel_state()->object_table()->RemoveHandle(handle);
}
DECLARE_XBOXKRNL_EXPORT(NtClose, ExportTag::kImplemented);

}  // namespace kernel
}  // namespace xe

void xe::kernel::xboxkrnl::RegisterObExports(
    xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {
  SHIM_SET_MAPPING("xboxkrnl.exe", ObOpenObjectByName, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", ObReferenceObjectByHandle, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", ObDereferenceObject, state);
}
<|endoftext|>


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

#include "opengl/x11/X11DeviceInfo.hxx"

#include <vcl/opengl/glxtest.hxx>
#include <rtl/ustring.hxx>

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/utsname.h>

namespace glx {

static int glxtest_pipe = 0;

static pid_t glxtest_pid = 0;

}

pid_t* getGlxPid()
{
    return &glx::glxtest_pid;
}

int* getGlxPipe()
{
    return &glx::glxtest_pipe;
}

namespace {

const char*
strspnp_wrapper(const char* aDelims, const char* aStr)
{
  const char* d;
  do {
    for (d = aDelims; *d != '\0'; ++d) {
      if (*aStr == *d) {
        ++aStr;
        break;
      }
    }
  } while (*d);

  return aStr;
}

char* strtok_wrapper(const char* aDelims, char** aStr)
{
    if (!*aStr) {
        return nullptr;
    }

    char* ret = (char*)strspnp_wrapper(aDelims, *aStr);

    if (!*ret) {
        *aStr = ret;
        return nullptr;
    }

    char* i = ret;
    do {
        for (const char* d = aDelims; *d != '\0'; ++d) {
            if (*i == *d) {
                *i = '\0';
                *aStr = ++i;
                return ret;
            }
        }
        ++i;
    } while (*i);

    *aStr = nullptr;
    return ret;
}

uint64_t version(uint32_t major, uint32_t minor, uint32_t revision = 0)
{
    return (uint64_t(major) << 32) + (uint64_t(minor) << 16) + uint64_t(revision);
}

}

X11OpenGLDeviceInfo::X11OpenGLDeviceInfo():
    mbIsMesa(false),
    mbIsNVIDIA(false),
    mbIsFGLRX(false),
    mbIsNouveau(false),
    mbIsIntel(false),
    mbIsOldSwrast(false),
    mbIsLlvmpipe(false),
    mbHasTextureFromPixmap(false),
    mnGLMajorVersion(0),
    mnMajorVersion(0),
    mnMinorVersion(0),
    mnRevisionVersion(0)
{
    GetData();
}

X11OpenGLDeviceInfo::~X11OpenGLDeviceInfo()
{
}

void X11OpenGLDeviceInfo::GetData()
{
    if (!glx::glxtest_pipe)
       return;

    // to understand this function, see bug 639842. We retrieve the OpenGL driver information in a
    // separate process to protect against bad drivers.

    enum { buf_size = 1024 };
    char buf[buf_size];
    ssize_t bytesread = read(glx::glxtest_pipe,
            &buf,
            buf_size-1); // -1 because we'll append a zero
    close(glx::glxtest_pipe);
    glx::glxtest_pipe = 0;

    // bytesread < 0 would mean that the above read() call failed.
    // This should never happen. If it did, the outcome would be to blacklist anyway.
    if (bytesread < 0)
        bytesread = 0;

    // let buf be a zero-terminated string
    buf[bytesread] = 0;

    // Wait for the glxtest process to finish. This serves 2 purposes:
    // * avoid having a zombie glxtest process laying around
    // * get the glxtest process status info.
    int glxtest_status = 0;
    bool wait_for_glxtest_process = true;
    bool waiting_for_glxtest_process_failed = false;
    int waitpid_errno = 0;
    while(wait_for_glxtest_process) {
        wait_for_glxtest_process = false;
        if (waitpid(glx::glxtest_pid, &glxtest_status, 0) == -1) {
            waitpid_errno = errno;
            if (waitpid_errno == EINTR) {
                wait_for_glxtest_process = true;
            } else {
                // Bug 718629
                // ECHILD happens when the glxtest process got reaped got reaped after a PR_CreateProcess
                // as per bug 227246. This shouldn't matter, as we still seem to get the data
                // from the pipe, and if we didn't, the outcome would be to blacklist anyway.
                waiting_for_glxtest_process_failed = (waitpid_errno != ECHILD);
            }
        }
    }

    bool exited_with_error_code = !waiting_for_glxtest_process_failed &&
        WIFEXITED(glxtest_status) &&
        WEXITSTATUS(glxtest_status) != EXIT_SUCCESS;
    bool received_signal = !waiting_for_glxtest_process_failed &&
        WIFSIGNALED(glxtest_status);

    bool error = waiting_for_glxtest_process_failed || exited_with_error_code || received_signal;

    OString textureFromPixmap;
    OString *stringToFill = nullptr;
    char *bufptr = buf;
    if (!error) {
        while(true) {
            char *line = strtok_wrapper("\n", &bufptr);
            if (!line)
                break;
            if (stringToFill) {
                *stringToFill = OString(line);
                stringToFill = nullptr;
            }
            else if(!strcmp(line, "VENDOR"))
                stringToFill = &maVendor;
            else if(!strcmp(line, "RENDERER"))
                stringToFill = &maRenderer;
            else if(!strcmp(line, "VERSION"))
                stringToFill = &maVersion;
            else if(!strcmp(line, "TFP"))
                stringToFill = &textureFromPixmap;
        }
    }

    if (!strcmp(textureFromPixmap.getStr(), "TRUE"))
        mbHasTextureFromPixmap = true;

    // only useful for Linux kernel version check for FGLRX driver.
    // assumes X client == X server, which is sad.
    struct utsname unameobj;
    if (!uname(&unameobj))
    {
        maOS = OString(unameobj.sysname);
        maOSRelease = OString(unameobj.release);
    }

    // determine the major OpenGL version. That's the first integer in the version string.
    mnGLMajorVersion = strtol(maVersion.getStr(), 0, 10);

    // determine driver type (vendor) and where in the version string
    // the actual driver version numbers should be expected to be found (whereToReadVersionNumbers)
    const char *whereToReadVersionNumbers = nullptr;
    const char *Mesa_in_version_string = strstr(maVersion.getStr(), "Mesa");
    if (Mesa_in_version_string) {
        mbIsMesa = true;
        // with Mesa, the version string contains "Mesa major.minor" and that's all the version information we get:
        // there is no actual driver version info.
        whereToReadVersionNumbers = Mesa_in_version_string + strlen("Mesa");
        if (strcasestr(maVendor.getStr(), "nouveau"))
            mbIsNouveau = true;
        if (strcasestr(maRenderer.getStr(), "intel")) // yes, intel is in the renderer string
            mbIsIntel = true;
        if (strcasestr(maRenderer.getStr(), "llvmpipe"))
            mbIsLlvmpipe = true;
        if (strcasestr(maRenderer.getStr(), "software rasterizer"))
            mbIsOldSwrast = true;
    } else if (strstr(maVendor.getStr(), "NVIDIA Corporation")) {
        mbIsNVIDIA = true;
        // with the NVIDIA driver, the version string contains "NVIDIA major.minor"
        // note that here the vendor and version strings behave differently, that's why we don't put this above
        // alongside Mesa_in_version_string.
        const char *NVIDIA_in_version_string = strstr(maVersion.getStr(), "NVIDIA");
        if (NVIDIA_in_version_string)
            whereToReadVersionNumbers = NVIDIA_in_version_string + strlen("NVIDIA");
    } else if (strstr(maVendor.getStr(), "ATI Technologies Inc")) {
        mbIsFGLRX = true;
        // with the FGLRX driver, the version string only gives a OpenGL version :/ so let's return that.
        // that can at least give a rough idea of how old the driver is.
        whereToReadVersionNumbers = maVersion.getStr();
    }

    // read major.minor version numbers of the driver (not to be confused with the OpenGL version)
    if (whereToReadVersionNumbers) {
        // copy into writable buffer, for tokenization
        strncpy(buf, whereToReadVersionNumbers, buf_size);
        bufptr = buf;

        // now try to read major.minor version numbers. In case of failure, gracefully exit: these numbers have
        // been initialized as 0 anyways
        char *token = strtok_wrapper(".", &bufptr);
        if (token) {
            mnMajorVersion = strtol(token, 0, 10);
            token = strtok_wrapper(".", &bufptr);
            if (token) {
                mnMinorVersion = strtol(token, 0, 10);
                token = strtok_wrapper(".", &bufptr);
                if (token)
                    mnRevisionVersion = strtol(token, 0, 10);
            }
        }
    }
}

bool X11OpenGLDeviceInfo::isDeviceBlocked()
{
    // don't even try to use OpenGL 1.x
    if (mnGLMajorVersion == 1)
        return true;

    SAL_INFO("vcl.opengl", "Vendor: " << maVendor);
    SAL_INFO("vcl.opengl", "Renderer: " << maRenderer);
    SAL_INFO("vcl.opengl", "Version: " << maVersion);
    SAL_INFO("vcl.opengl", "OS: " << maOS);
    SAL_INFO("vcl.opengl", "OSRelease: " << maOSRelease);

    if (mbIsMesa) {
        if (mbIsNouveau && version(mnMajorVersion, mnMinorVersion) < version(8,0)) {
            SAL_WARN("vcl.opengl", "blocked driver version: old nouveau driver (requires mesa 8.0+)");
            return true;
        }
        else if (version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) < version(7,10,3)) {
            SAL_WARN("vcl.opengl", "blocked driver version: requires at least mesa 7.10.3");
            return true;
        }
        else if (mbIsOldSwrast) {
            SAL_WARN("vcl.opengl", "blocked driver version: software rasterizer");
            return true;
        }
        else if (mbIsLlvmpipe && version(mnMajorVersion, mnMinorVersion) < version(9, 1)) {
            // bug 791905, Mesa bug 57733, fixed in Mesa 9.1 according to
            // https://bugs.freedesktop.org/show_bug.cgi?id=57733#c3
            SAL_WARN("vcl.opengl", "blocked driver version: fdo#57733");
            return true;
        }

    } else if (mbIsNVIDIA) {
        if (version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) < version(257,21)) {
            SAL_WARN("vcl.opengl", "blocked driver version: nvidia requires at least 257.21");
            return true;
        }
    } else if (mbIsFGLRX) {
        // FGLRX does not report a driver version number, so we have the OpenGL version instead.
        // by requiring OpenGL 3, we effectively require recent drivers.
        if (version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) < version(3, 0)) {
            SAL_WARN("vcl.opengl", "blocked driver version: require at least OpenGL 3 for fglrx");
            return true;
        }
        // Bug 724640: FGLRX + Linux 2.6.32 is a crashy combo
        bool unknownOS = maOS.isEmpty() || maOSRelease.isEmpty();
        OUString aOS = rtl::OStringToOUString(maOS, RTL_TEXTENCODING_UTF8);
        OUString aOSRelease = rtl::OStringToOUString(maOSRelease, RTL_TEXTENCODING_UTF8);
        bool badOS = aOS.indexOf("Linux") != -1 &&
            maOSRelease.indexOf("2.6.32") != -1;
        if (unknownOS || badOS) {
            SAL_WARN("vcl.opengl", "blocked OS version with fglrx");
            return true;
        }
    } else {
        // like on windows, let's block unknown vendors. Think of virtual machines.
        // Also, this case is hit whenever the GLXtest probe failed to get driver info or crashed.
        SAL_WARN("vcl.opengl", "unknown vendor => blocked");
        return true;
    }

    return false;
}

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

#include "opengl/x11/X11DeviceInfo.hxx"

#include <vcl/opengl/glxtest.hxx>
#include <rtl/ustring.hxx>

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/utsname.h>

namespace glx {

static int glxtest_pipe = 0;

static pid_t glxtest_pid = 0;

}

pid_t* getGlxPid()
{
    return &glx::glxtest_pid;
}

int* getGlxPipe()
{
    return &glx::glxtest_pipe;
}

namespace {

const char*
strspnp_wrapper(const char* aDelims, const char* aStr)
{
  const char* d;
  do {
    for (d = aDelims; *d != '\0'; ++d) {
      if (*aStr == *d) {
        ++aStr;
        break;
      }
    }
  } while (*d);

  return aStr;
}

char* strtok_wrapper(const char* aDelims, char** aStr)
{
    if (!*aStr) {
        return nullptr;
    }

    char* ret = (char*)strspnp_wrapper(aDelims, *aStr);

    if (!*ret) {
        *aStr = ret;
        return nullptr;
    }

    char* i = ret;
    do {
        for (const char* d = aDelims; *d != '\0'; ++d) {
            if (*i == *d) {
                *i = '\0';
                *aStr = ++i;
                return ret;
            }
        }
        ++i;
    } while (*i);

    *aStr = nullptr;
    return ret;
}

uint64_t version(uint32_t major, uint32_t minor, uint32_t revision = 0)
{
    return (uint64_t(major) << 32) + (uint64_t(minor) << 16) + uint64_t(revision);
}

}

X11OpenGLDeviceInfo::X11OpenGLDeviceInfo():
    mbIsMesa(false),
    mbIsNVIDIA(false),
    mbIsFGLRX(false),
    mbIsNouveau(false),
    mbIsIntel(false),
    mbIsOldSwrast(false),
    mbIsLlvmpipe(false),
    mbHasTextureFromPixmap(false),
    mnGLMajorVersion(0),
    mnMajorVersion(0),
    mnMinorVersion(0),
    mnRevisionVersion(0)
{
    GetData();
}

X11OpenGLDeviceInfo::~X11OpenGLDeviceInfo()
{
}

void X11OpenGLDeviceInfo::GetData()
{
    if (!glx::glxtest_pipe)
       return;

    // to understand this function, see bug 639842. We retrieve the OpenGL driver information in a
    // separate process to protect against bad drivers.

    enum { buf_size = 1024 };
    char buf[buf_size];
    ssize_t bytesread = read(glx::glxtest_pipe,
            &buf,
            buf_size-1); // -1 because we'll append a zero
    close(glx::glxtest_pipe);
    glx::glxtest_pipe = 0;

    // bytesread < 0 would mean that the above read() call failed.
    // This should never happen. If it did, the outcome would be to blacklist anyway.
    if (bytesread < 0)
        bytesread = 0;

    // let buf be a zero-terminated string
    buf[bytesread] = 0;

    // Wait for the glxtest process to finish. This serves 2 purposes:
    // * avoid having a zombie glxtest process laying around
    // * get the glxtest process status info.
    int glxtest_status = 0;
    bool wait_for_glxtest_process = true;
    bool waiting_for_glxtest_process_failed = false;
    int waitpid_errno = 0;
    while(wait_for_glxtest_process) {
        wait_for_glxtest_process = false;
        if (waitpid(glx::glxtest_pid, &glxtest_status, 0) == -1) {
            waitpid_errno = errno;
            if (waitpid_errno == EINTR) {
                wait_for_glxtest_process = true;
            } else {
                // Bug 718629
                // ECHILD happens when the glxtest process got reaped got reaped after a PR_CreateProcess
                // as per bug 227246. This shouldn't matter, as we still seem to get the data
                // from the pipe, and if we didn't, the outcome would be to blacklist anyway.
                waiting_for_glxtest_process_failed = (waitpid_errno != ECHILD);
            }
        }
    }

    bool exited_with_error_code = !waiting_for_glxtest_process_failed &&
        WIFEXITED(glxtest_status) &&
        WEXITSTATUS(glxtest_status) != EXIT_SUCCESS;
    bool received_signal = !waiting_for_glxtest_process_failed &&
        WIFSIGNALED(glxtest_status);

    bool error = waiting_for_glxtest_process_failed || exited_with_error_code || received_signal;

    OString textureFromPixmap;
    OString *stringToFill = nullptr;
    char *bufptr = buf;
    if (!error) {
        while(true) {
            char *line = strtok_wrapper("\n", &bufptr);
            if (!line)
                break;
            if (stringToFill) {
                *stringToFill = OString(line);
                stringToFill = nullptr;
            }
            else if(!strcmp(line, "VENDOR"))
                stringToFill = &maVendor;
            else if(!strcmp(line, "RENDERER"))
                stringToFill = &maRenderer;
            else if(!strcmp(line, "VERSION"))
                stringToFill = &maVersion;
            else if(!strcmp(line, "TFP"))
                stringToFill = &textureFromPixmap;
        }
    }

    if (!strcmp(textureFromPixmap.getStr(), "TRUE"))
        mbHasTextureFromPixmap = true;

    // only useful for Linux kernel version check for FGLRX driver.
    // assumes X client == X server, which is sad.
    struct utsname unameobj;
    if (!uname(&unameobj))
    {
        maOS = OString(unameobj.sysname);
        maOSRelease = OString(unameobj.release);
    }

    // determine the major OpenGL version. That's the first integer in the version string.
    mnGLMajorVersion = strtol(maVersion.getStr(), 0, 10);

    // determine driver type (vendor) and where in the version string
    // the actual driver version numbers should be expected to be found (whereToReadVersionNumbers)
    const char *whereToReadVersionNumbers = nullptr;
    const char *Mesa_in_version_string = strstr(maVersion.getStr(), "Mesa");
    if (Mesa_in_version_string) {
        mbIsMesa = true;
        // with Mesa, the version string contains "Mesa major.minor" and that's all the version information we get:
        // there is no actual driver version info.
        whereToReadVersionNumbers = Mesa_in_version_string + strlen("Mesa");
        if (strcasestr(maVendor.getStr(), "nouveau"))
            mbIsNouveau = true;
        if (strcasestr(maRenderer.getStr(), "intel")) // yes, intel is in the renderer string
            mbIsIntel = true;
        if (strcasestr(maRenderer.getStr(), "llvmpipe"))
            mbIsLlvmpipe = true;
        if (strcasestr(maRenderer.getStr(), "software rasterizer"))
            mbIsOldSwrast = true;
    } else if (strstr(maVendor.getStr(), "NVIDIA Corporation")) {
        mbIsNVIDIA = true;
        // with the NVIDIA driver, the version string contains "NVIDIA major.minor"
        // note that here the vendor and version strings behave differently, that's why we don't put this above
        // alongside Mesa_in_version_string.
        const char *NVIDIA_in_version_string = strstr(maVersion.getStr(), "NVIDIA");
        if (NVIDIA_in_version_string)
            whereToReadVersionNumbers = NVIDIA_in_version_string + strlen("NVIDIA");
    } else if (strstr(maVendor.getStr(), "ATI Technologies Inc")) {
        mbIsFGLRX = true;
        // with the FGLRX driver, the version string only gives a OpenGL version :/ so let's return that.
        // that can at least give a rough idea of how old the driver is.
        whereToReadVersionNumbers = maVersion.getStr();
    }

    // read major.minor version numbers of the driver (not to be confused with the OpenGL version)
    if (whereToReadVersionNumbers) {
        // copy into writable buffer, for tokenization
        strncpy(buf, whereToReadVersionNumbers, buf_size);
        bufptr = buf;

        // now try to read major.minor version numbers. In case of failure, gracefully exit: these numbers have
        // been initialized as 0 anyways
        char *token = strtok_wrapper(".", &bufptr);
        if (token) {
            mnMajorVersion = strtol(token, 0, 10);
            token = strtok_wrapper(".", &bufptr);
            if (token) {
                mnMinorVersion = strtol(token, 0, 10);
                token = strtok_wrapper(".", &bufptr);
                if (token)
                    mnRevisionVersion = strtol(token, 0, 10);
            }
        }
    }
}

bool X11OpenGLDeviceInfo::isDeviceBlocked()
{
    // don't even try to use OpenGL 1.x
    if (mnGLMajorVersion == 1)
        return true;

    SAL_INFO("vcl.opengl", "Vendor: " << maVendor);
    SAL_INFO("vcl.opengl", "Renderer: " << maRenderer);
    SAL_INFO("vcl.opengl", "Version: " << maVersion);
    SAL_INFO("vcl.opengl", "OS: " << maOS);
    SAL_INFO("vcl.opengl", "OSRelease: " << maOSRelease);

    if (mbIsMesa) {
        if (mbIsNouveau && version(mnMajorVersion, mnMinorVersion) < version(8,0)) {
            SAL_WARN("vcl.opengl", "blocked driver version: old nouveau driver (requires mesa 8.0+)");
            return true;
        }
        else if (version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) < version(7,10,3)) {
            SAL_WARN("vcl.opengl", "blocked driver version: requires at least mesa 7.10.3");
            return true;
        }
        else if (mbIsOldSwrast) {
            SAL_WARN("vcl.opengl", "blocked driver version: software rasterizer");
            return true;
        }
        else if (mbIsLlvmpipe && version(mnMajorVersion, mnMinorVersion) < version(9, 1)) {
            // bug 791905, Mesa bug 57733, fixed in Mesa 9.1 according to
            // https://bugs.freedesktop.org/show_bug.cgi?id=57733#c3
            SAL_WARN("vcl.opengl", "blocked driver version: fdo#57733");
            return true;
        }

    } else if (mbIsNVIDIA) {
        if (version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) < version(257,21)) {
            SAL_WARN("vcl.opengl", "blocked driver version: nvidia requires at least 257.21");
            return true;
        }
    } else if (mbIsFGLRX) {
        // FGLRX does not report a driver version number, so we have the OpenGL version instead.
        // by requiring OpenGL 3, we effectively require recent drivers.
        if (version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) < version(3, 0)) {
            SAL_WARN("vcl.opengl", "blocked driver version: require at least OpenGL 3 for fglrx");
            return true;
        }
        // Bug 724640: FGLRX + Linux 2.6.32 is a crashy combo
        bool unknownOS = maOS.isEmpty() || maOSRelease.isEmpty();
        bool badOS = maOS.indexOf("Linux") != -1 &&
            maOSRelease.indexOf("2.6.32") != -1;
        if (unknownOS || badOS) {
            SAL_WARN("vcl.opengl", "blocked OS version with fglrx");
            return true;
        }
    } else {
        // like on windows, let's block unknown vendors. Think of virtual machines.
        // Also, this case is hit whenever the GLXtest probe failed to get driver info or crashed.
        SAL_WARN("vcl.opengl", "unknown vendor => blocked");
        return true;
    }

    return false;
}

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