<commit_before>/*************************************************************************
 *
 * Copyright 2019 Realm 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.
 *
 **************************************************************************/

#ifndef REALM_ARRAY_FIXED_BYTES_HPP
#define REALM_ARRAY_FIXED_BYTES_HPP

#include <realm/array.hpp>
#include <realm/object_id.hpp>
#include <realm/uuid.hpp>

namespace realm {

template <class ObjectType, int ElementSize>
class ArrayFixedBytes : public ArrayPayload, protected Array {
public:
    using value_type = ObjectType;
    using self_type = ArrayFixedBytes<ObjectType, ElementSize>;

    using Array::Array;
    using Array::destroy;
    using Array::get_ref;
    using Array::init_from_mem;
    using Array::init_from_parent;
    using Array::update_parent;
    using Array::verify;

    static ObjectType default_value(bool nullable)
    {
        REALM_ASSERT(!nullable);
        return ObjectType();
    }

    void create()
    {
        auto mem = Array::create(type_Normal, false, wtype_Multiply, 0, 0, m_alloc); // Throws
        Array::init_from_mem(mem);
    }

    void init_from_ref(ref_type ref) noexcept override
    {
        Array::init_from_ref(ref);
    }

    void set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept override
    {
        Array::set_parent(parent, ndx_in_parent);
    }

    size_t size() const
    {
        auto data_bytes = m_size - div_round_up<s_block_size>(m_size); // remove one byte per block.
        return data_bytes / s_width;
    }

    bool is_null(size_t ndx) const
    {
        return this->get_width() == 0 || get_pos(ndx).is_null(this);
    }

    ObjectType get(size_t ndx) const
    {
        REALM_ASSERT(is_valid_ndx(ndx));
        REALM_ASSERT(!is_null(ndx));
        return get_pos(ndx).get_value(this);
    }

    void add(const ObjectType& value)
    {
        insert(size(), value);
    }

    void set(size_t ndx, const ObjectType& value);
    void insert(size_t ndx, const ObjectType& value);
    void erase(size_t ndx);
    void move(ArrayFixedBytes<ObjectType, ElementSize>& dst, size_t ndx);
    void clear()
    {
        truncate(0);
    }
    void truncate(size_t ndx)
    {
        Array::truncate(calc_required_bytes(ndx));
    }

    size_t find_first(const ObjectType& value, size_t begin = 0, size_t end = npos) const noexcept;

protected:
    static constexpr size_t s_width = ElementSize; // Size of each element

    // A block is a byte bitvector indicating null entries and 8 ObjectIds.
    static constexpr size_t s_block_size = s_width * 8 + 1; // 97

    template <size_t div>
    static size_t div_round_up(size_t num)
    {
        return (num + div - 1) / div;
    }

    // An accessor for the data at a given index. All casting and offset calculation should be kept here.
    struct Pos {
        size_t base_byte;
        size_t offset;

        void set_value(self_type* arr, const ObjectType& val) const
        {
            reinterpret_cast<ObjectType*>(arr->m_data + base_byte + 1 /*null bit byte*/)[offset] = val;
        }
        const ObjectType& get_value(const self_type* arr) const
        {
            return reinterpret_cast<const ObjectType*>(arr->m_data + base_byte + 1 /*null bit byte*/)[offset];
        }

        void set_null(self_type* arr, bool new_is_null) const
        {
            auto& bitvec = arr->m_data[base_byte];
            if (new_is_null) {
                bitvec |= 1 << offset;
            }
            else {
                bitvec &= ~(1 << offset);
            }
        }
        bool is_null(const self_type* arr) const
        {
            return arr->m_data[base_byte] & (1 << offset);
        }
    };

    static Pos get_pos(size_t ndx)
    {

        return Pos{(ndx / 8) * s_block_size, ndx % 8};
    }

    static size_t calc_required_bytes(size_t num_items)
    {
        return (num_items * s_width) +       // ObjectId data
               (div_round_up<8>(num_items)); // null bitvectors (1 byte per 8 oids, rounded up)
    }

    size_t calc_byte_len(size_t num_items, size_t /*unused width*/ = 0) const override
    {
        return num_items + Node::header_size;
    }

    bool is_valid_ndx(size_t ndx) const
    {
        return calc_byte_len(ndx) <= m_size;
    }
};

// The nullable ObjectId array uses the same layout and is compatible with the non-nullable one. It adds support for
// operations on null. Because the base class maintains null markers, we are able to defer to it for many operations.
template <class ObjectType, int ElementSize>
class ArrayFixedBytesNull : public ArrayFixedBytes<ObjectType, ElementSize> {
public:
    using Parent = ArrayFixedBytes<ObjectType, ElementSize>;
    using ArrayFixedBytes<ObjectType, ElementSize>::ArrayFixedBytes;
    static util::Optional<ObjectType> default_value(bool nullable)
    {
        if (nullable)
            return util::none;
        return ObjectType();
    }

    void set(size_t ndx, const util::Optional<ObjectType>& value)
    {
        if (value) {
            Parent::set(ndx, *value);
        }
        else {
            set_null(ndx);
        }
    }
    void add(const util::Optional<ObjectType>& value)
    {
        insert(this->size(), value);
    }
    void insert(size_t ndx, const util::Optional<ObjectType>& value);
    void set_null(size_t ndx);
    util::Optional<ObjectType> get(size_t ndx) const noexcept
    {
        auto pos = this->get_pos(ndx);
        if (pos.is_null(this)) {
            return util::none;
        }
        return pos.get_value(this);
    }
    size_t find_first(const util::Optional<ObjectType>& value, size_t begin = 0, size_t end = npos) const
    {
        if (value) {
            return Parent::find_first(*value, begin, end);
        }
        else {
            return find_first_null(begin, end);
        }
    }
    size_t find_first_null(size_t begin = 0, size_t end = npos) const;

private:
    static const ObjectType null_oid;
};

using ArrayObjectId = ArrayFixedBytes<ObjectId, sizeof(ObjectId)>;
using ArrayObjectIdNull = ArrayFixedBytesNull<ObjectId, sizeof(ObjectId)>;

using ArrayUUID = ArrayFixedBytes<UUID, sizeof(UUID::UUIDBytes)>;
using ArrayUUIDNull = ArrayFixedBytesNull<UUID, sizeof(UUID::UUIDBytes)>;

} // namespace realm

#endif /* REALM_ARRAY_FIXED_BYTES_HPP */
<commit_msg>fix vs error getting confused about which ctr to use<commit_after>/*************************************************************************
 *
 * Copyright 2019 Realm 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.
 *
 **************************************************************************/

#ifndef REALM_ARRAY_FIXED_BYTES_HPP
#define REALM_ARRAY_FIXED_BYTES_HPP

#include <realm/array.hpp>
#include <realm/object_id.hpp>
#include <realm/uuid.hpp>

namespace realm {

template <class ObjectType, int ElementSize>
class ArrayFixedBytes : public ArrayPayload, protected Array {
public:
    using value_type = ObjectType;
    using self_type = ArrayFixedBytes<ObjectType, ElementSize>;

    using Array::Array;
    using Array::destroy;
    using Array::get_ref;
    using Array::init_from_mem;
    using Array::init_from_parent;
    using Array::update_parent;
    using Array::verify;

    static ObjectType default_value(bool nullable)
    {
        REALM_ASSERT(!nullable);
        return ObjectType();
    }

    void create()
    {
        auto mem = Array::create(type_Normal, false, wtype_Multiply, 0, 0, m_alloc); // Throws
        Array::init_from_mem(mem);
    }

    void init_from_ref(ref_type ref) noexcept override
    {
        Array::init_from_ref(ref);
    }

    void set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept override
    {
        Array::set_parent(parent, ndx_in_parent);
    }

    size_t size() const
    {
        auto data_bytes = m_size - div_round_up<s_block_size>(m_size); // remove one byte per block.
        return data_bytes / s_width;
    }

    bool is_null(size_t ndx) const
    {
        return this->get_width() == 0 || get_pos(ndx).is_null(this);
    }

    ObjectType get(size_t ndx) const
    {
        REALM_ASSERT(is_valid_ndx(ndx));
        REALM_ASSERT(!is_null(ndx));
        return get_pos(ndx).get_value(this);
    }

    void add(const ObjectType& value)
    {
        insert(size(), value);
    }

    void set(size_t ndx, const ObjectType& value);
    void insert(size_t ndx, const ObjectType& value);
    void erase(size_t ndx);
    void move(ArrayFixedBytes<ObjectType, ElementSize>& dst, size_t ndx);
    void clear()
    {
        truncate(0);
    }
    void truncate(size_t ndx)
    {
        Array::truncate(calc_required_bytes(ndx));
    }

    size_t find_first(const ObjectType& value, size_t begin = 0, size_t end = npos) const noexcept;

protected:
    static constexpr size_t s_width = ElementSize; // Size of each element

    // A block is a byte bitvector indicating null entries and 8 ObjectIds.
    static constexpr size_t s_block_size = s_width * 8 + 1; // 97

    template <size_t div>
    static size_t div_round_up(size_t num)
    {
        return (num + div - 1) / div;
    }

    // An accessor for the data at a given index. All casting and offset calculation should be kept here.
    struct Pos {
        size_t base_byte;
        size_t offset;

        void set_value(self_type* arr, const ObjectType& val) const
        {
            reinterpret_cast<ObjectType*>(arr->m_data + base_byte + 1 /*null bit byte*/)[offset] = val;
        }
        const ObjectType& get_value(const self_type* arr) const
        {
            return reinterpret_cast<const ObjectType*>(arr->m_data + base_byte + 1 /*null bit byte*/)[offset];
        }

        void set_null(self_type* arr, bool new_is_null) const
        {
            auto& bitvec = arr->m_data[base_byte];
            if (new_is_null) {
                bitvec |= 1 << offset;
            }
            else {
                bitvec &= ~(1 << offset);
            }
        }
        bool is_null(const self_type* arr) const
        {
            return arr->m_data[base_byte] & (1 << offset);
        }
    };

    static Pos get_pos(size_t ndx)
    {

        return Pos{(ndx / 8) * s_block_size, ndx % 8};
    }

    static size_t calc_required_bytes(size_t num_items)
    {
        return (num_items * s_width) +       // ObjectId data
               (div_round_up<8>(num_items)); // null bitvectors (1 byte per 8 oids, rounded up)
    }

    size_t calc_byte_len(size_t num_items, size_t /*unused width*/ = 0) const override
    {
        return num_items + Node::header_size;
    }

    bool is_valid_ndx(size_t ndx) const
    {
        return calc_byte_len(ndx) <= m_size;
    }
};

// The nullable ObjectId array uses the same layout and is compatible with the non-nullable one. It adds support for
// operations on null. Because the base class maintains null markers, we are able to defer to it for many operations.
template <class ObjectType, int ElementSize>
class ArrayFixedBytesNull : public ArrayFixedBytes<ObjectType, ElementSize> {
public:
    using Parent = ArrayFixedBytes<ObjectType, ElementSize>;
    ArrayFixedBytesNull(Allocator& alloc) noexcept
        : ArrayFixedBytes<ObjectType, ElementSize>(alloc)
    {
    }
    static util::Optional<ObjectType> default_value(bool nullable)
    {
        if (nullable)
            return util::none;
        return ObjectType();
    }

    void set(size_t ndx, const util::Optional<ObjectType>& value)
    {
        if (value) {
            Parent::set(ndx, *value);
        }
        else {
            set_null(ndx);
        }
    }
    void add(const util::Optional<ObjectType>& value)
    {
        insert(this->size(), value);
    }
    void insert(size_t ndx, const util::Optional<ObjectType>& value);
    void set_null(size_t ndx);
    util::Optional<ObjectType> get(size_t ndx) const noexcept
    {
        auto pos = this->get_pos(ndx);
        if (pos.is_null(this)) {
            return util::none;
        }
        return pos.get_value(this);
    }
    size_t find_first(const util::Optional<ObjectType>& value, size_t begin = 0, size_t end = npos) const
    {
        if (value) {
            return Parent::find_first(*value, begin, end);
        }
        else {
            return find_first_null(begin, end);
        }
    }
    size_t find_first_null(size_t begin = 0, size_t end = npos) const;

private:
    static const ObjectType null_oid;
};

using ArrayObjectId = ArrayFixedBytes<ObjectId, sizeof(ObjectId)>;
using ArrayObjectIdNull = ArrayFixedBytesNull<ObjectId, sizeof(ObjectId)>;

using ArrayUUID = ArrayFixedBytes<UUID, sizeof(UUID::UUIDBytes)>;
using ArrayUUIDNull = ArrayFixedBytesNull<UUID, sizeof(UUID::UUIDBytes)>;

} // namespace realm

#endif /* REALM_ARRAY_FIXED_BYTES_HPP */
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2015] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/

#ifndef REALM_IMPL_INPUT_STREAM_HPP
#define REALM_IMPL_INPUT_STREAM_HPP

#include <algorithm>

#include <realm/binary_data.hpp>
#include <realm/impl/continuous_transactions_history.hpp>

namespace realm {
namespace _impl {

class InputStream {
public:
    /// Read bytes from this input stream and place them in the specified
    /// buffer. The returned value is the actual number of bytes that were read,
    /// and this is some number `n` such that `n <= min(size, m)` where `m` is
    /// the number of bytes that could have been read from this stream before
    /// reaching its end. Also, `n` cannot be zero unless `m` or `size` is
    /// zero. The intention is that `size` should be non-zero, a the return
    /// value used as the end-of-input indicator.
    ///
    /// Implementations are only allowed to block (put the calling thread to
    /// sleep) up until the point in time where the first byte can be made
    /// availble.
    virtual size_t read(char* buffer, size_t size) = 0;

    virtual ~InputStream() noexcept {}
};

class SimpleInputStream: public InputStream {
public:
    SimpleInputStream(const char* data, size_t size) noexcept:
        m_ptr(data),
        m_end(data + size)
    {
    }
    size_t read(char* buffer, size_t size) override
    {
        size_t n = std::min(size, size_t(m_end-m_ptr));
        const char* begin = m_ptr;
        m_ptr += n;
        const char* end = m_ptr;
        std::copy(begin, end, buffer);
        return n;
    }
private:
    const char* m_ptr;
    const char* const m_end;
};

class NoCopyInputStream {
public:
    /// \return the number of accessible bytes.
    /// A value of zero indicates end-of-input.
    /// For non-zero return value, \a begin and \a end are
    /// updated to reflect the start and limit of a
    /// contiguous memory chunk.
    virtual size_t next_block(const char*& begin, const char*& end) = 0;

    virtual ~NoCopyInputStream() noexcept {}
};

class NoCopyInputStreamAdaptor: public NoCopyInputStream {
public:
    NoCopyInputStreamAdaptor(InputStream& in, char* buffer, size_t buffer_size) noexcept:
        m_in(in),
        m_buffer(buffer),
        m_buffer_size(buffer_size)
    {
    }
    size_t next_block(const char*& begin, const char*& end) override
    {
        size_t n = m_in.read(m_buffer, m_buffer_size);
        begin = m_buffer;
        end = m_buffer + n;
        return n;
    }
private:
    InputStream& m_in;
    char* m_buffer;
    size_t m_buffer_size;
};

class SimpleNoCopyInputStream: public NoCopyInputStream {
public:
    SimpleNoCopyInputStream(const char* data, size_t size):
        m_data(data),
        m_size(size)
    {
    }

    size_t next_block(const char*& begin, const char*& end) override
    {
        if (m_size == 0)
            return 0;
        size_t size = m_size;
        begin = m_data;
        end = m_data + size;
        m_size = 0;
        return size;
    }

private:
    const char* m_data;
    size_t m_size;
};

class MultiLogNoCopyInputStream: public NoCopyInputStream {
public:
    MultiLogNoCopyInputStream(const BinaryData* logs_begin, const BinaryData* logs_end):
        m_logs_begin(logs_begin), m_logs_end(logs_end)
    {
        if (m_logs_begin != m_logs_end)
            m_curr_buf_remaining_size = m_logs_begin->size();
    }

    size_t read(char* buffer, size_t size)
    {
        if (m_logs_begin == m_logs_end)
            return 0;
        for (;;) {
            if (m_curr_buf_remaining_size > 0) {
                size_t offset = m_logs_begin->size() - m_curr_buf_remaining_size;
                const char* data = m_logs_begin->data() + offset;
                size_t size_2 = std::min(m_curr_buf_remaining_size, size);
                m_curr_buf_remaining_size -= size_2;
                // FIXME: Eliminate the need for copying by changing the API of
                // Replication::InputStream such that blocks can be handed over
                // without copying. This is a straight forward change, but the
                // result is going to be more complicated and less conventional.
                std::copy(data, data + size_2, buffer);
                return size_2;
            }

            ++m_logs_begin;
            if (m_logs_begin == m_logs_end)
                return 0;
            m_curr_buf_remaining_size = m_logs_begin->size();
        }
    }

    size_t next_block(const char*& begin, const char*& end) override
    {
        while (m_logs_begin < m_logs_end) {
            size_t result = m_logs_begin->size();
            const char* data = m_logs_begin->data();
            m_logs_begin++;
            if (result == 0)
                continue; // skip empty blocks
            begin = data;
            end = data + result;
            return result;
        }
        return 0;
    }

private:
    const BinaryData* m_logs_begin;
    const BinaryData* m_logs_end;
    size_t m_curr_buf_remaining_size;
};

class ChangesetInputStream: public NoCopyInputStream {
public:
    using version_type = History::version_type;
    ChangesetInputStream(History&, version_type begin_version, version_type end_version);
    size_t next_block(const char*& begin, const char*& end) override;
private:
    History& m_history;
    version_type m_begin_version, m_end_version;
    BinaryData m_changesets[8]; // Buffer
    BinaryData* m_changesets_begin = 0;
    BinaryData* m_changesets_end = 0;
};

inline ChangesetInputStream::ChangesetInputStream(History& hist, version_type begin_version,
                                                  version_type end_version):
    m_history(hist),
    m_begin_version(begin_version),
    m_end_version(end_version)
{
}

inline size_t ChangesetInputStream::next_block(const char*& begin, const char*& end)
{
    for (;;) {
        if (REALM_UNLIKELY(m_changesets_begin == m_changesets_end)) {
            if (m_begin_version == m_end_version)
                return 0; // End of input
            uint_fast64_t n = sizeof m_changesets / sizeof m_changesets[0];
            uint_fast64_t avail = m_end_version - m_begin_version;
            if (n > avail)
                n = avail;
            version_type end_version = m_begin_version + n;
            m_history.get_changesets(m_begin_version, end_version, m_changesets);
            m_begin_version = end_version;
            m_changesets_begin = m_changesets;
            m_changesets_end = m_changesets_begin + n;
        }

        BinaryData changeset = *m_changesets_begin++;
        if (changeset.size() > 0) {
            begin = changeset.data();
            end   = changeset.data() + changeset.size();
            return changeset.size();
        }
    }
}

} // namespace _impl
} // namespace realm

#endif // REALM_IMPL_INPUT_STREAM_HPP
<commit_msg>Adjust the fix as suggested by @kspangsege.<commit_after>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2015] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/

#ifndef REALM_IMPL_INPUT_STREAM_HPP
#define REALM_IMPL_INPUT_STREAM_HPP

#include <algorithm>

#include <realm/binary_data.hpp>
#include <realm/impl/continuous_transactions_history.hpp>

namespace realm {
namespace _impl {

class InputStream {
public:
    /// Read bytes from this input stream and place them in the specified
    /// buffer. The returned value is the actual number of bytes that were read,
    /// and this is some number `n` such that `n <= min(size, m)` where `m` is
    /// the number of bytes that could have been read from this stream before
    /// reaching its end. Also, `n` cannot be zero unless `m` or `size` is
    /// zero. The intention is that `size` should be non-zero, a the return
    /// value used as the end-of-input indicator.
    ///
    /// Implementations are only allowed to block (put the calling thread to
    /// sleep) up until the point in time where the first byte can be made
    /// availble.
    virtual size_t read(char* buffer, size_t size) = 0;

    virtual ~InputStream() noexcept {}
};

class SimpleInputStream: public InputStream {
public:
    SimpleInputStream(const char* data, size_t size) noexcept:
        m_ptr(data),
        m_end(data + size)
    {
    }
    size_t read(char* buffer, size_t size) override
    {
        size_t n = std::min(size, size_t(m_end-m_ptr));
        const char* begin = m_ptr;
        m_ptr += n;
        const char* end = m_ptr;
        std::copy(begin, end, buffer);
        return n;
    }
private:
    const char* m_ptr;
    const char* const m_end;
};

class NoCopyInputStream {
public:
    /// \return the number of accessible bytes.
    /// A value of zero indicates end-of-input.
    /// For non-zero return value, \a begin and \a end are
    /// updated to reflect the start and limit of a
    /// contiguous memory chunk.
    virtual size_t next_block(const char*& begin, const char*& end) = 0;

    virtual ~NoCopyInputStream() noexcept {}
};

class NoCopyInputStreamAdaptor: public NoCopyInputStream {
public:
    NoCopyInputStreamAdaptor(InputStream& in, char* buffer, size_t buffer_size) noexcept:
        m_in(in),
        m_buffer(buffer),
        m_buffer_size(buffer_size)
    {
    }
    size_t next_block(const char*& begin, const char*& end) override
    {
        size_t n = m_in.read(m_buffer, m_buffer_size);
        begin = m_buffer;
        end = m_buffer + n;
        return n;
    }
private:
    InputStream& m_in;
    char* m_buffer;
    size_t m_buffer_size;
};

class SimpleNoCopyInputStream: public NoCopyInputStream {
public:
    SimpleNoCopyInputStream(const char* data, size_t size):
        m_data(data),
        m_size(size)
    {
    }

    size_t next_block(const char*& begin, const char*& end) override
    {
        if (m_size == 0)
            return 0;
        size_t size = m_size;
        begin = m_data;
        end = m_data + size;
        m_size = 0;
        return size;
    }

private:
    const char* m_data;
    size_t m_size;
};

class MultiLogNoCopyInputStream: public NoCopyInputStream {
public:
    MultiLogNoCopyInputStream(const BinaryData* logs_begin, const BinaryData* logs_end):
        m_logs_begin(logs_begin), m_logs_end(logs_end)
    {
        if (m_logs_begin != m_logs_end)
            m_curr_buf_remaining_size = m_logs_begin->size();
    }

    size_t read(char* buffer, size_t size)
    {
        if (m_logs_begin == m_logs_end)
            return 0;
        for (;;) {
            if (m_curr_buf_remaining_size > 0) {
                size_t offset = m_logs_begin->size() - m_curr_buf_remaining_size;
                const char* data = m_logs_begin->data() + offset;
                size_t size_2 = std::min(m_curr_buf_remaining_size, size);
                m_curr_buf_remaining_size -= size_2;
                // FIXME: Eliminate the need for copying by changing the API of
                // Replication::InputStream such that blocks can be handed over
                // without copying. This is a straight forward change, but the
                // result is going to be more complicated and less conventional.
                std::copy(data, data + size_2, buffer);
                return size_2;
            }

            ++m_logs_begin;
            if (m_logs_begin == m_logs_end)
                return 0;
            m_curr_buf_remaining_size = m_logs_begin->size();
        }
    }

    size_t next_block(const char*& begin, const char*& end) override
    {
        while (m_logs_begin < m_logs_end) {
            size_t result = m_logs_begin->size();
            const char* data = m_logs_begin->data();
            m_logs_begin++;
            if (result == 0)
                continue; // skip empty blocks
            begin = data;
            end = data + result;
            return result;
        }
        return 0;
    }

private:
    const BinaryData* m_logs_begin;
    const BinaryData* m_logs_end;
    size_t m_curr_buf_remaining_size;
};

class ChangesetInputStream: public NoCopyInputStream {
public:
    using version_type = History::version_type;
    ChangesetInputStream(History&, version_type begin_version, version_type end_version);
    size_t next_block(const char*& begin, const char*& end) override;
private:
    History& m_history;
    version_type m_begin_version, m_end_version;
    BinaryData m_changesets[8]; // Buffer
    BinaryData* m_changesets_begin = 0;
    BinaryData* m_changesets_end = 0;
};

inline ChangesetInputStream::ChangesetInputStream(History& hist, version_type begin_version,
                                                  version_type end_version):
    m_history(hist),
    m_begin_version(begin_version),
    m_end_version(end_version)
{
}

inline size_t ChangesetInputStream::next_block(const char*& begin, const char*& end)
{
    for (;;) {
        if (REALM_UNLIKELY(m_changesets_begin == m_changesets_end)) {
            if (m_begin_version == m_end_version)
                return 0; // End of input
            size_t n = sizeof m_changesets / sizeof m_changesets[0];
            version_type avail = m_end_version - m_begin_version;
            if (n > avail)
                n = size_t(avail);
            version_type end_version = m_begin_version + n;
            m_history.get_changesets(m_begin_version, end_version, m_changesets);
            m_begin_version = end_version;
            m_changesets_begin = m_changesets;
            m_changesets_end = m_changesets_begin + n;
        }

        BinaryData changeset = *m_changesets_begin++;
        if (changeset.size() > 0) {
            begin = changeset.data();
            end   = changeset.data() + changeset.size();
            return changeset.size();
        }
    }
}

} // namespace _impl
} // namespace realm

#endif // REALM_IMPL_INPUT_STREAM_HPP
<|endoftext|>


<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_HoveringText.cpp
 *  @brief  Shows a hovering text attached to an entity.
 */

#define OGRE_INTEROP

#include "DebugOperatorNew.h"

#include "EC_HoveringText.h"
#include "Renderer.h"
#include "EC_Placeable.h"
#include "Entity.h"
#include "LoggingFunctions.h"
#include "Scene.h"
#include "Framework.h"
#include "OgreRenderingModule.h"
#include "OgreWorld.h"
#include "OgreMaterialUtils.h"
#include "AssetAPI.h"
#include "TextureAsset.h"

#include <Ogre.h>
#include <QFile>
#include <QPainter>
#include <QTimer>
#include <QTimeLine>

#include "MemoryLeakCheck.h"

EC_HoveringText::EC_HoveringText(Scene* scene) :
    IComponent(scene),
    font_(QFont("Arial", 100)),
    textColor_(Qt::black),
    billboardSet_(0),
    billboard_(0),
    usingGrad(this, "Use Gradient", false),
    text(this, "Text"),
    font(this, "Font", "Arial"),
    fontColor(this, "Font Color"),
    fontSize(this, "Font Size", 100),
    backgroundColor(this, "Background Color", Color(1.0f,1.0f,1.0f,0.0f)),
    position(this, "Position", float3(0.0f, 0.0f, 0.0f)),
    gradStart(this, "Gradient Start", Color(0.0f,0.0f,0.0f,1.0f)),
    gradEnd(this, "Gradient End", Color(1.0f,1.0f,1.0f,1.0f)),
    borderColor(this, "Border Color", Color(0.0f,0.0f,0.0f,0.0f)),
    borderThickness(this, "Border Thickness", 0.0),
    overlayAlpha(this, "Overlay Alpha", 1.0),
    width(this, "Width", 1.0),
    height(this, "Height", 1.0),
    texWidth(this, "Texture Width", 256),
    texHeight(this, "Texture Height", 256),
    cornerRadius(this, "Corner radius", float2(20.0, 20.0))
{
    if (scene)
        world_ = scene->GetWorld<OgreWorld>();
}

EC_HoveringText::~EC_HoveringText()
{
    if (texture_.get() != 0)
    {
        AssetAPI* asset = framework->Asset();
        asset->ForgetAsset(texture_,false);
    }
    Destroy();
}

void EC_HoveringText::Destroy()
{
    if (!ViewEnabled())
        return;

    if (!world_.expired())
    {
        Ogre::SceneManager* sceneMgr = world_.lock()->GetSceneManager();

        try{
        Ogre::MaterialManager::getSingleton().remove(materialName_);
        } catch(...)
        {
        }
        try{
        if (billboardSet_ && billboard_)
            billboardSet_->removeBillboard(billboard_);
        } catch(...)
        {
        }
        try{

        if (billboardSet_)
        {
            sceneMgr->destroyBillboardSet(billboardSet_);
        }

        } catch(...)
        {
        }
    }

    billboard_ = 0;
    billboardSet_ = 0;
    textureName_ = "";
    materialName_ = "";
}

void EC_HoveringText::SetPosition(const float3& position)
{
    if (!ViewEnabled())
        return;

    if (billboard_)
        billboard_->setPosition(position);
}

void EC_HoveringText::SetFont(const QFont &font)
{
    font_ = font;
    Redraw();
}

void EC_HoveringText::SetTextColor(const QColor &color)
{
    textColor_ = color;
    Redraw();
}

void EC_HoveringText::SetBackgroundGradient(const QColor &start_color, const QColor &end_color)
{
    bg_grad_.setColorAt(0.0, start_color);
    bg_grad_.setColorAt(1.0, end_color);
}

void EC_HoveringText::Show()
{
    if (!ViewEnabled())
        return;

    if (billboardSet_)
        billboardSet_->setVisible(true);
}

void EC_HoveringText::Hide()
{
    if (!ViewEnabled())
        return;

    if (billboardSet_)
        billboardSet_->setVisible(false);
}

void EC_HoveringText::SetOverlayAlpha(float alpha)
{
    Ogre::MaterialManager &mgr = Ogre::MaterialManager::getSingleton();
    Ogre::MaterialPtr material = mgr.getByName(materialName_);
    if (!material.get() || material->getNumTechniques() < 1 || material->getTechnique(0)->getNumPasses() < 1 || material->getTechnique(0)->getPass(0)->getNumTextureUnitStates() < 1)
        return;

    material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setAlphaOperation(
        Ogre::LBX_BLEND_MANUAL, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, 1.0, 0.0, alpha);
}

void EC_HoveringText::SetBillboardSize(float width, float height)
{
    if (billboard_)
        billboard_->setDimensions(width, height);
}

bool EC_HoveringText::IsVisible() const
{
    if (!ViewEnabled())
        return false;

    if (billboardSet_)
        return billboardSet_->isVisible();
    else
        return false;
}

void EC_HoveringText::ShowMessage(const QString &text)
{
    if (!ViewEnabled())
        return;
    if (world_.expired())
        return;

    OgreWorldPtr world = world_.lock();
    Ogre::SceneManager *scene = world->GetSceneManager();
    assert(scene);
    if (!scene)
        return;

    //Scene::Entity *entity = ParentEntity();
    Entity* entity = ParentEntity();
    assert(entity);
    if (!entity)
        return;

    EC_Placeable *node = entity->GetComponent<EC_Placeable>().get();
    if (!node)
        return;

    Ogre::SceneNode *sceneNode = node->GetSceneNode();
    assert(sceneNode);
    if (!sceneNode)
        return;

    // Create billboard if it doesn't exist.
    if (!billboardSet_)
    {
        billboardSet_ = scene->createBillboardSet(world->GetUniqueObjectName("EC_HoveringText"), 1);
        assert(billboardSet_);

        materialName_ = world->GetUniqueObjectName("EC_HoveringText_material");
        OgreRenderer::CloneMaterial("HoveringText", materialName_);
        billboardSet_->setMaterialName(materialName_);
        billboardSet_->setCastShadows(false);

        sceneNode->attachObject(billboardSet_);
    }

    if (billboardSet_ && !billboard_)
    {
        billboard_ = billboardSet_->createBillboard(Ogre::Vector3(0, 0, 0.7f));

        SetBillboardSize(width.Get(), height.Get());
        SetPosition(position.Get());
    }

    Redraw();
}

void EC_HoveringText::Redraw()
{
    if (!ViewEnabled())
        return;

    if (world_.expired() || !billboardSet_ || !billboard_)
        return;

    bool textEmpty = text.Get().isEmpty();

    try
    {
        if (texture_.get() == 0)
        {
            AssetAPI* asset = framework->Asset();

            textureName_ = asset->GenerateUniqueAssetName("tex", "EC_HoveringText_").toStdString();
            QString name(textureName_.c_str());
            texture_  = boost::dynamic_pointer_cast<TextureAsset>(asset->CreateNewAsset("Texture", name));

            assert(texture_);

            if (texture_ == 0)
            {
                LogError("Failed to create texture " + textureName_);
                return;
            }
        }

        QBrush brush(backgroundColor.Get());

        if (usingGrad.Get())
        {
            QRect rect(0,0,texWidth.Get(), texHeight.Get());
            bg_grad_.setStart(QPointF(0,rect.top()));
            bg_grad_.setFinalStop(QPointF(0,rect.bottom()));
            brush = QBrush(bg_grad_);
        }

        QColor borderCol;
        Color col = borderColor.Get();
        borderCol.setRgbF(col.r, col.g, col.b, col.a);

        QPen borderPen;
        borderPen.setColor(borderCol);
        borderPen.setWidthF(borderThickness.Get());

        float2 corners =  cornerRadius.Get();

        if (!textEmpty)
        {
            // Disable mipmapping, as Ogre seems to bug with it
            texture_->SetContentsDrawText(texWidth.Get(),
                                    texHeight.Get(),
                                    text.Get(),
                                    textColor_,
                                    font_,
                                    brush,
                                    borderPen, Qt::AlignCenter | Qt::TextWordWrap, false, false, corners.x, corners.y);
        }
        else
            texture_->SetContentsDrawText(texWidth.Get(), texHeight.Get(), text.Get(), textColor_, font_, QBrush(), QPen(), Qt::AlignCenter | Qt::TextWordWrap, false, false, 0.0f, 0.0f);
    }
    catch(Ogre::Exception &e)
    {
        LogError("Failed to create texture " + textureName_  + ": " + std::string(e.what()));
        return;
    }

    // Set new texture for the material
    assert(!materialName_.empty());
    if (!materialName_.empty())
    {
        Ogre::MaterialManager &mgr = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mgr.getByName(materialName_);
        assert(material.get());
        OgreRenderer::SetTextureUnitOnMaterial(material, textureName_);
    }
}

void EC_HoveringText::AttributesChanged()
{
    if (font.ValueChanged() || fontSize.ValueChanged())
    {
        SetFont(QFont(font.Get(), fontSize.Get()));
    }
    if (fontColor.ValueChanged())
    {
        Color col = fontColor.Get();
        textColor_.setRgbF(col.r, col.g, col.b, col.a);
    }
    if (position.ValueChanged())
    {
        SetPosition(position.Get());
    }
    if (gradStart.ValueChanged() || gradEnd.ValueChanged())
    {
        QColor colStart;
        QColor colEnd;
        Color col = gradStart.Get();
        colStart.setRgbF(col.r, col.g, col.b);
        col = gradEnd.Get();
        colEnd.setRgbF(col.r, col.g, col.b);
        SetBackgroundGradient(colStart, colEnd);
    }
    if (overlayAlpha.ValueChanged())
        SetOverlayAlpha(overlayAlpha.Get());
    if (width.ValueChanged() || height.ValueChanged())
        SetBillboardSize(width.Get(), height.Get());

    // Changes to the following attributes require a (expensive) repaint of the texture on the CPU side.
    bool repaint = text.ValueChanged() || font.ValueChanged() || fontSize.ValueChanged() || fontColor.ValueChanged()
        || backgroundColor.ValueChanged() || borderColor.ValueChanged() || borderThickness.ValueChanged() || usingGrad.ValueChanged()
        || gradStart.ValueChanged() || gradEnd.ValueChanged() || texWidth.ValueChanged() || texHeight.ValueChanged()
        || cornerRadius.ValueChanged();

    // Changes to the following attributes do not alter the texture contents, and don't require a repaint:
    // position, overlayAlpha, width, height.

    // Repaint the new text with new appearance.
    if (repaint)
        ShowMessage(text.Get());
}<commit_msg>Fix build for EC_HoveringText.cpp.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_HoveringText.cpp
 *  @brief  Shows a hovering text attached to an entity.
 */

#define MATH_OGRE_INTEROP

#include "DebugOperatorNew.h"

#include "EC_HoveringText.h"
#include "Renderer.h"
#include "EC_Placeable.h"
#include "Entity.h"
#include "LoggingFunctions.h"
#include "Scene.h"
#include "Framework.h"
#include "OgreRenderingModule.h"
#include "OgreWorld.h"
#include "OgreMaterialUtils.h"
#include "AssetAPI.h"
#include "TextureAsset.h"

#include <Ogre.h>
#include <QFile>
#include <QPainter>
#include <QTimer>
#include <QTimeLine>

#include "MemoryLeakCheck.h"

EC_HoveringText::EC_HoveringText(Scene* scene) :
    IComponent(scene),
    font_(QFont("Arial", 100)),
    textColor_(Qt::black),
    billboardSet_(0),
    billboard_(0),
    usingGrad(this, "Use Gradient", false),
    text(this, "Text"),
    font(this, "Font", "Arial"),
    fontColor(this, "Font Color"),
    fontSize(this, "Font Size", 100),
    backgroundColor(this, "Background Color", Color(1.0f,1.0f,1.0f,0.0f)),
    position(this, "Position", float3(0.0f, 0.0f, 0.0f)),
    gradStart(this, "Gradient Start", Color(0.0f,0.0f,0.0f,1.0f)),
    gradEnd(this, "Gradient End", Color(1.0f,1.0f,1.0f,1.0f)),
    borderColor(this, "Border Color", Color(0.0f,0.0f,0.0f,0.0f)),
    borderThickness(this, "Border Thickness", 0.0),
    overlayAlpha(this, "Overlay Alpha", 1.0),
    width(this, "Width", 1.0),
    height(this, "Height", 1.0),
    texWidth(this, "Texture Width", 256),
    texHeight(this, "Texture Height", 256),
    cornerRadius(this, "Corner radius", float2(20.0, 20.0))
{
    if (scene)
        world_ = scene->GetWorld<OgreWorld>();
}

EC_HoveringText::~EC_HoveringText()
{
    if (texture_.get() != 0)
    {
        AssetAPI* asset = framework->Asset();
        asset->ForgetAsset(texture_,false);
    }
    Destroy();
}

void EC_HoveringText::Destroy()
{
    if (!ViewEnabled())
        return;

    if (!world_.expired())
    {
        Ogre::SceneManager* sceneMgr = world_.lock()->GetSceneManager();

        try{
        Ogre::MaterialManager::getSingleton().remove(materialName_);
        } catch(...)
        {
        }
        try{
        if (billboardSet_ && billboard_)
            billboardSet_->removeBillboard(billboard_);
        } catch(...)
        {
        }
        try{

        if (billboardSet_)
        {
            sceneMgr->destroyBillboardSet(billboardSet_);
        }

        } catch(...)
        {
        }
    }

    billboard_ = 0;
    billboardSet_ = 0;
    textureName_ = "";
    materialName_ = "";
}

void EC_HoveringText::SetPosition(const float3& position)
{
    if (!ViewEnabled())
        return;

    if (billboard_)
        billboard_->setPosition(position);
}

void EC_HoveringText::SetFont(const QFont &font)
{
    font_ = font;
    Redraw();
}

void EC_HoveringText::SetTextColor(const QColor &color)
{
    textColor_ = color;
    Redraw();
}

void EC_HoveringText::SetBackgroundGradient(const QColor &start_color, const QColor &end_color)
{
    bg_grad_.setColorAt(0.0, start_color);
    bg_grad_.setColorAt(1.0, end_color);
}

void EC_HoveringText::Show()
{
    if (!ViewEnabled())
        return;

    if (billboardSet_)
        billboardSet_->setVisible(true);
}

void EC_HoveringText::Hide()
{
    if (!ViewEnabled())
        return;

    if (billboardSet_)
        billboardSet_->setVisible(false);
}

void EC_HoveringText::SetOverlayAlpha(float alpha)
{
    Ogre::MaterialManager &mgr = Ogre::MaterialManager::getSingleton();
    Ogre::MaterialPtr material = mgr.getByName(materialName_);
    if (!material.get() || material->getNumTechniques() < 1 || material->getTechnique(0)->getNumPasses() < 1 || material->getTechnique(0)->getPass(0)->getNumTextureUnitStates() < 1)
        return;

    material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setAlphaOperation(
        Ogre::LBX_BLEND_MANUAL, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, 1.0, 0.0, alpha);
}

void EC_HoveringText::SetBillboardSize(float width, float height)
{
    if (billboard_)
        billboard_->setDimensions(width, height);
}

bool EC_HoveringText::IsVisible() const
{
    if (!ViewEnabled())
        return false;

    if (billboardSet_)
        return billboardSet_->isVisible();
    else
        return false;
}

void EC_HoveringText::ShowMessage(const QString &text)
{
    if (!ViewEnabled())
        return;
    if (world_.expired())
        return;

    OgreWorldPtr world = world_.lock();
    Ogre::SceneManager *scene = world->GetSceneManager();
    assert(scene);
    if (!scene)
        return;

    //Scene::Entity *entity = ParentEntity();
    Entity* entity = ParentEntity();
    assert(entity);
    if (!entity)
        return;

    EC_Placeable *node = entity->GetComponent<EC_Placeable>().get();
    if (!node)
        return;

    Ogre::SceneNode *sceneNode = node->GetSceneNode();
    assert(sceneNode);
    if (!sceneNode)
        return;

    // Create billboard if it doesn't exist.
    if (!billboardSet_)
    {
        billboardSet_ = scene->createBillboardSet(world->GetUniqueObjectName("EC_HoveringText"), 1);
        assert(billboardSet_);

        materialName_ = world->GetUniqueObjectName("EC_HoveringText_material");
        OgreRenderer::CloneMaterial("HoveringText", materialName_);
        billboardSet_->setMaterialName(materialName_);
        billboardSet_->setCastShadows(false);

        sceneNode->attachObject(billboardSet_);
    }

    if (billboardSet_ && !billboard_)
    {
        billboard_ = billboardSet_->createBillboard(Ogre::Vector3(0, 0, 0.7f));

        SetBillboardSize(width.Get(), height.Get());
        SetPosition(position.Get());
    }

    Redraw();
}

void EC_HoveringText::Redraw()
{
    if (!ViewEnabled())
        return;

    if (world_.expired() || !billboardSet_ || !billboard_)
        return;

    bool textEmpty = text.Get().isEmpty();

    try
    {
        if (texture_.get() == 0)
        {
            AssetAPI* asset = framework->Asset();

            textureName_ = asset->GenerateUniqueAssetName("tex", "EC_HoveringText_").toStdString();
            QString name(textureName_.c_str());
            texture_  = boost::dynamic_pointer_cast<TextureAsset>(asset->CreateNewAsset("Texture", name));

            assert(texture_);

            if (texture_ == 0)
            {
                LogError("Failed to create texture " + textureName_);
                return;
            }
        }

        QBrush brush(backgroundColor.Get());

        if (usingGrad.Get())
        {
            QRect rect(0,0,texWidth.Get(), texHeight.Get());
            bg_grad_.setStart(QPointF(0,rect.top()));
            bg_grad_.setFinalStop(QPointF(0,rect.bottom()));
            brush = QBrush(bg_grad_);
        }

        QColor borderCol;
        Color col = borderColor.Get();
        borderCol.setRgbF(col.r, col.g, col.b, col.a);

        QPen borderPen;
        borderPen.setColor(borderCol);
        borderPen.setWidthF(borderThickness.Get());

        float2 corners =  cornerRadius.Get();

        if (!textEmpty)
        {
            // Disable mipmapping, as Ogre seems to bug with it
            texture_->SetContentsDrawText(texWidth.Get(),
                                    texHeight.Get(),
                                    text.Get(),
                                    textColor_,
                                    font_,
                                    brush,
                                    borderPen, Qt::AlignCenter | Qt::TextWordWrap, false, false, corners.x, corners.y);
        }
        else
            texture_->SetContentsDrawText(texWidth.Get(), texHeight.Get(), text.Get(), textColor_, font_, QBrush(), QPen(), Qt::AlignCenter | Qt::TextWordWrap, false, false, 0.0f, 0.0f);
    }
    catch(Ogre::Exception &e)
    {
        LogError("Failed to create texture " + textureName_  + ": " + std::string(e.what()));
        return;
    }

    // Set new texture for the material
    assert(!materialName_.empty());
    if (!materialName_.empty())
    {
        Ogre::MaterialManager &mgr = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mgr.getByName(materialName_);
        assert(material.get());
        OgreRenderer::SetTextureUnitOnMaterial(material, textureName_);
    }
}

void EC_HoveringText::AttributesChanged()
{
    if (font.ValueChanged() || fontSize.ValueChanged())
    {
        SetFont(QFont(font.Get(), fontSize.Get()));
    }
    if (fontColor.ValueChanged())
    {
        Color col = fontColor.Get();
        textColor_.setRgbF(col.r, col.g, col.b, col.a);
    }
    if (position.ValueChanged())
    {
        SetPosition(position.Get());
    }
    if (gradStart.ValueChanged() || gradEnd.ValueChanged())
    {
        QColor colStart;
        QColor colEnd;
        Color col = gradStart.Get();
        colStart.setRgbF(col.r, col.g, col.b);
        col = gradEnd.Get();
        colEnd.setRgbF(col.r, col.g, col.b);
        SetBackgroundGradient(colStart, colEnd);
    }
    if (overlayAlpha.ValueChanged())
        SetOverlayAlpha(overlayAlpha.Get());
    if (width.ValueChanged() || height.ValueChanged())
        SetBillboardSize(width.Get(), height.Get());

    // Changes to the following attributes require a (expensive) repaint of the texture on the CPU side.
    bool repaint = text.ValueChanged() || font.ValueChanged() || fontSize.ValueChanged() || fontColor.ValueChanged()
        || backgroundColor.ValueChanged() || borderColor.ValueChanged() || borderThickness.ValueChanged() || usingGrad.ValueChanged()
        || gradStart.ValueChanged() || gradEnd.ValueChanged() || texWidth.ValueChanged() || texHeight.ValueChanged()
        || cornerRadius.ValueChanged();

    // Changes to the following attributes do not alter the texture contents, and don't require a repaint:
    // position, overlayAlpha, width, height.

    // Repaint the new text with new appearance.
    if (repaint)
        ShowMessage(text.Get());
}<|endoftext|>


<commit_before>/*
 *  ScoreData.cpp
 *  mert - Minimum Error Rate Training
 *
 *  Created by Nicola Bertoldi on 13/05/08.
 *
 */

#include "ScoreData.h"
#include "Scorer.h"
#include "Util.h"
#include "FileStream.h"

ScoreData::ScoreData(Scorer& ptr):
  theScorer(&ptr)
{
  score_type = theScorer->getName();
  // This is not dangerous: we don't use the this pointer in SetScoreData.
  theScorer->setScoreData(this);
  number_of_scores = theScorer->NumberOfScores();
  // TRACE_ERR("ScoreData: number_of_scores: " << number_of_scores << std::endl);
}

void ScoreData::save(std::ofstream& outFile, bool bin)
{
  for (scoredata_t::iterator i = array_.begin(); i !=array_.end(); i++) {
    i->save(outFile, score_type, bin);
  }
}

void ScoreData::save(const std::string &file, bool bin)
{
  if (file.empty()) return;
  TRACE_ERR("saving the array into " << file << std::endl);

  // matches a stream with a file. Opens the file.
  std::ofstream outFile(file.c_str(), std::ios::out);

  ScoreStats entry;

  save(outFile, bin);

  outFile.close();
}

void ScoreData::load(ifstream& inFile)
{
  ScoreArray entry;

  while (!inFile.eof()) {

    if (!inFile.good()) {
      std::cerr << "ERROR ScoreData::load inFile.good()" << std::endl;
    }

    entry.clear();
    entry.load(inFile);

    if (entry.size() == 0) {
      break;
    }
    add(entry);
  }
}

void ScoreData::load(const std::string &file)
{
  TRACE_ERR("loading score data from " << file << std::endl);

  inputfilestream inFile(file); // matches a stream with a file. Opens the file

  if (!inFile) {
    throw runtime_error("Unable to open score file: " + file);
  }

  load((ifstream&) inFile);

  inFile.close();
}

void ScoreData::add(ScoreArray& e)
{
  if (exists(e.getIndex())) { // array at position e.getIndex() already exists
    //enlarge array at position e.getIndex()
    size_t pos = getIndex(e.getIndex());
    array_.at(pos).merge(e);
  } else {
    array_.push_back(e);
    setIndex();
  }
}

void ScoreData::add(const ScoreStats& e, const std::string& sent_idx)
{
  if (exists(sent_idx)) { // array at position e.getIndex() already exists
    // Enlarge array at position e.getIndex()
    size_t pos = getIndex(sent_idx);
    //          TRACE_ERR("Inserting in array " << sent_idx << std::endl);
    array_.at(pos).add(e);
    //          TRACE_ERR("size: " << size() << " -> " << a.size() << std::endl);
  } else {
    //          TRACE_ERR("Creating a new entry in the array" << std::endl);
    ScoreArray a;
    a.NumberOfScores(number_of_scores);
    a.add(e);
    a.setIndex(sent_idx);
    add(a);
    //          TRACE_ERR("size: " << size() << " -> " << a.size() << std::endl);
  }
}

bool ScoreData::check_consistency() const
{
  if (array_.size() == 0)
    return true;

  for (scoredata_t::const_iterator i = array_.begin(); i != array_.end(); ++i)
    if (!i->check_consistency()) return false;

  return true;
}

void ScoreData::setIndex()
{
  size_t j=0;
  for (scoredata_t::iterator i = array_.begin(); i !=array_.end(); i++) {
    idx2arrayname_[j]=i->getIndex();
    arrayname2idx_[i->getIndex()]=j;
    j++;
  }
}
<commit_msg>Fixed quadratic time when adding ScoreStats to ScoreData<commit_after>/*
 *  ScoreData.cpp
 *  mert - Minimum Error Rate Training
 *
 *  Created by Nicola Bertoldi on 13/05/08.
 *
 */

#include "ScoreData.h"
#include "Scorer.h"
#include "Util.h"
#include "FileStream.h"

ScoreData::ScoreData(Scorer& ptr):
  theScorer(&ptr)
{
  score_type = theScorer->getName();
  // This is not dangerous: we don't use the this pointer in SetScoreData.
  theScorer->setScoreData(this);
  number_of_scores = theScorer->NumberOfScores();
  // TRACE_ERR("ScoreData: number_of_scores: " << number_of_scores << std::endl);
}

void ScoreData::save(std::ofstream& outFile, bool bin)
{
  for (scoredata_t::iterator i = array_.begin(); i !=array_.end(); i++) {
    i->save(outFile, score_type, bin);
  }
}

void ScoreData::save(const std::string &file, bool bin)
{
  if (file.empty()) return;
  TRACE_ERR("saving the array into " << file << std::endl);

  // matches a stream with a file. Opens the file.
  std::ofstream outFile(file.c_str(), std::ios::out);

  ScoreStats entry;

  save(outFile, bin);

  outFile.close();
}

void ScoreData::load(ifstream& inFile)
{
  ScoreArray entry;

  while (!inFile.eof()) {

    if (!inFile.good()) {
      std::cerr << "ERROR ScoreData::load inFile.good()" << std::endl;
    }

    entry.clear();
    entry.load(inFile);

    if (entry.size() == 0) {
      break;
    }
    add(entry);
  }
}

void ScoreData::load(const std::string &file)
{
  TRACE_ERR("loading score data from " << file << std::endl);

  inputfilestream inFile(file); // matches a stream with a file. Opens the file

  if (!inFile) {
    throw runtime_error("Unable to open score file: " + file);
  }

  load((ifstream&) inFile);

  inFile.close();
}

void ScoreData::add(ScoreArray& e)
{
  if (exists(e.getIndex())) { // array at position e.getIndex() already exists
    //enlarge array at position e.getIndex()
    size_t pos = getIndex(e.getIndex());
    array_.at(pos).merge(e);
  } else {
    array_.push_back(e);
    setIndex();
  }
}

void ScoreData::add(const ScoreStats& e, const std::string& sent_idx)
{
  if (exists(sent_idx)) { // array at position e.getIndex() already exists
    // Enlarge array at position e.getIndex()
    size_t pos = getIndex(sent_idx);
    //          TRACE_ERR("Inserting in array " << sent_idx << std::endl);
    array_.at(pos).add(e);
    //          TRACE_ERR("size: " << size() << " -> " << a.size() << std::endl);
  } else {
    //          TRACE_ERR("Creating a new entry in the array" << std::endl);
    ScoreArray a;
    a.NumberOfScores(number_of_scores);
    a.add(e);
    a.setIndex(sent_idx);
    size_t idx = array_.size();
    array_.push_back(a);
    idx2arrayname_[idx] = sent_idx;
    arrayname2idx_[sent_idx]=idx;
    //          TRACE_ERR("size: " << size() << " -> " << a.size() << std::endl);
  }
}

bool ScoreData::check_consistency() const
{
  if (array_.size() == 0)
    return true;

  for (scoredata_t::const_iterator i = array_.begin(); i != array_.end(); ++i)
    if (!i->check_consistency()) return false;

  return true;
}

void ScoreData::setIndex()
{
  size_t j=0;
  for (scoredata_t::iterator i = array_.begin(); i !=array_.end(); i++) {
    idx2arrayname_[j]=i->getIndex();
    arrayname2idx_[i->getIndex()]=j;
    j++;
  }
}
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;

int main(){
	int x = 4;
	int y = 5;
	int *a = &x;
	int *b = &y;

	cout << "*a = " << *a << endl
		 << "*b = " << *b << endl;

	*a = *a + *b;
	*b = *b**b;

	cout << "*a now = " << *a << endl
		 << "*b now = " << *b << endl;

	return 0;
}

<commit_msg>Update S7_Pointer_Operations.cpp<commit_after>//
//  Program Name - S7_Pointer_Operations.cpp
//  Series: GetOnToC++ Step: 7
//
//  Purpose: This program illustrates how to use arithmetic operations on pointers
//
//  Compile: g++ S7_Pointer_Operations.cpp -o S7_Pointer_Operations
//  Execute: ./S7_Pointer_Operations
//
//  Created by Narayan Mahadevan on 18/08/13.
//
#include <iostream>
using namespace std;

int main(){
	int x = 4;
	int y = 5;
	int *a = &x;
	int *b = &y;

	cout << "*a = " << *a << endl
		 << "*b = " << *b << endl;

	*a = *a + *b;
	*b = *b**b;

	cout << "*a now = " << *a << endl
		 << "*b now = " << *b << endl;

	return 0;
}

<|endoftext|>


<commit_before>//===--- LLVMOpt.cpp ------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// This is a simple reimplementation of opt that includes support for Swift-
/// specific LLVM passes. It is meant to make it easier to handle issues related
/// to transitioning to the new LLVM pass manager (which lacks the dynamism of
/// the old pass manager) and also problems during the code base transition to
/// that pass manager. Additionally it will enable a user to exactly simulate
/// Swift's LLVM pass pipeline by using the same pass pipeline building
/// machinery in IRGen, something not possible with opt.
///
//===----------------------------------------------------------------------===//

#include "swift/Subsystems.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/LLVMPasses/PassesFwd.h"
#include "swift/LLVMPasses/Passes.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/RegionPass.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/InitializePasses.h"
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"

using namespace swift;

static llvm::codegen::RegisterCodeGenFlags CGF;

//===----------------------------------------------------------------------===//
//                            Option Declarations
//===----------------------------------------------------------------------===//

// The OptimizationList is automatically populated with registered passes by the
// PassNameParser.
//
static llvm::cl::list<const llvm::PassInfo *, bool, llvm::PassNameParser>
    PassList(llvm::cl::desc("Optimizations available:"));

static llvm::cl::opt<bool>
    Optimized("O", llvm::cl::desc("Optimization level O. Similar to swift -O"));

// TODO: I wanted to call this 'verify', but some other pass is using this
// option.
static llvm::cl::opt<bool> VerifyEach(
    "verify-each",
    llvm::cl::desc("Should we spend time verifying that the IR is well "
                   "formed"));

static llvm::cl::opt<std::string>
    TargetTriple("mtriple",
                 llvm::cl::desc("Override target triple for module"));

static llvm::cl::opt<bool>
    PrintStats("print-stats",
               llvm::cl::desc("Should LLVM Statistics be printed"));

static llvm::cl::opt<std::string> InputFilename(llvm::cl::Positional,
                                          llvm::cl::desc("<input file>"),
                                          llvm::cl::init("-"),
                                          llvm::cl::value_desc("filename"));

static llvm::cl::opt<std::string>
    OutputFilename("o", llvm::cl::desc("Override output filename"),
                   llvm::cl::value_desc("filename"));

static llvm::cl::opt<std::string> DefaultDataLayout(
    "default-data-layout",
    llvm::cl::desc("data layout string to use if not specified by module"),
    llvm::cl::value_desc("layout-string"), llvm::cl::init(""));

//===----------------------------------------------------------------------===//
//                               Helper Methods
//===----------------------------------------------------------------------===//

static llvm::CodeGenOpt::Level GetCodeGenOptLevel() {
  // TODO: Is this the right thing to do here?
  if (Optimized)
    return llvm::CodeGenOpt::Default;
  return llvm::CodeGenOpt::None;
}

// Returns the TargetMachine instance or zero if no triple is provided.
static llvm::TargetMachine *
getTargetMachine(llvm::Triple TheTriple, StringRef CPUStr,
                 StringRef FeaturesStr, const llvm::TargetOptions &Options) {
  std::string Error;
  const auto *TheTarget = llvm::TargetRegistry::lookupTarget(
      llvm::codegen::getMArch(), TheTriple, Error);
  // Some modules don't specify a triple, and this is okay.
  if (!TheTarget) {
    return nullptr;
  }

  return TheTarget->createTargetMachine(
      TheTriple.getTriple(), CPUStr, FeaturesStr, Options,
      Optional<llvm::Reloc::Model>(llvm::codegen::getExplicitRelocModel()),
      llvm::codegen::getExplicitCodeModel(), GetCodeGenOptLevel());
}

static void dumpOutput(llvm::Module &M, llvm::raw_ostream &os) {
  // For now just always dump assembly.
  llvm::legacy::PassManager EmitPasses;
  EmitPasses.add(createPrintModulePass(os));
  EmitPasses.run(M);
}

// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// getMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement getMainExecutable
// without being given the address of a function in the main executable).
void anchorForGetMainExecutable() {}

static inline void addPass(llvm::legacy::PassManagerBase &PM, llvm::Pass *P) {
  // Add the pass to the pass manager...
  PM.add(P);
  if (P->getPassID() == &SwiftAAWrapperPass::ID) {
    PM.add(llvm::createExternalAAWrapperPass([](llvm::Pass &P, llvm::Function &,
                                                llvm::AAResults &AAR) {
      if (auto *WrapperPass = P.getAnalysisIfAvailable<SwiftAAWrapperPass>())
        AAR.addAAResult(WrapperPass->getResult());
    }));
  }

  // If we are verifying all of the intermediate steps, add the verifier...
  if (VerifyEach)
    PM.add(llvm::createVerifierPass());
}

static void runSpecificPasses(StringRef Binary, llvm::Module *M,
                              llvm::TargetMachine *TM,
                              llvm::Triple &ModuleTriple) {
  llvm::legacy::PassManager Passes;
  llvm::TargetLibraryInfoImpl TLII(ModuleTriple);
  Passes.add(new llvm::TargetLibraryInfoWrapperPass(TLII));

  const llvm::DataLayout &DL = M->getDataLayout();
  if (DL.isDefault() && !DefaultDataLayout.empty()) {
    M->setDataLayout(DefaultDataLayout);
  }

  // Add internal analysis passes from the target machine.
  Passes.add(createTargetTransformInfoWrapperPass(
      TM ? TM->getTargetIRAnalysis() : llvm::TargetIRAnalysis()));

  if (TM) {
    // FIXME: We should dyn_cast this when supported.
    auto &LTM = static_cast<llvm::LLVMTargetMachine &>(*TM);
    llvm::Pass *TPC = LTM.createPassConfig(Passes);
    Passes.add(TPC);
  }

  for (const llvm::PassInfo *PassInfo : PassList) {
    llvm::Pass *P = nullptr;
    if (PassInfo->getNormalCtor())
      P = PassInfo->getNormalCtor()();
    else
      llvm::errs() << Binary
                   << ": cannot create pass: " << PassInfo->getPassName()
                   << "\n";
    if (P) {
      addPass(Passes, P);
    }
  }

  // Do it.
  Passes.run(*M);
}

//===----------------------------------------------------------------------===//
//                            Main Implementation
//===----------------------------------------------------------------------===//

int main(int argc, char **argv) {
  PROGRAM_START(argc, argv);
  INITIALIZE_LLVM();

  // Initialize passes
  llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
  initializeCore(Registry);
  initializeScalarOpts(Registry);
  initializeObjCARCOpts(Registry);
  initializeVectorization(Registry);
  initializeIPO(Registry);
  initializeAnalysis(Registry);
  initializeTransformUtils(Registry);
  initializeInstCombine(Registry);
  initializeInstrumentation(Registry);
  initializeTarget(Registry);
  // For codegen passes, only passes that do IR to IR transformation are
  // supported.
  initializeCodeGenPreparePass(Registry);
  initializeAtomicExpandPass(Registry);
  initializeRewriteSymbolsLegacyPassPass(Registry);
  initializeWinEHPreparePass(Registry);
  initializeDwarfEHPreparePass(Registry);
  initializeSjLjEHPreparePass(Registry);

  // Register Swift Only Passes.
  initializeSwiftAAWrapperPassPass(Registry);
  initializeSwiftRCIdentityPass(Registry);
  initializeSwiftARCOptPass(Registry);
  initializeSwiftARCContractPass(Registry);
  initializeInlineTreePrinterPass(Registry);
  initializeSwiftMergeFunctionsPass(Registry);

  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift LLVM optimizer\n");

  if (PrintStats)
    llvm::EnableStatistics();

  llvm::SMDiagnostic Err;

  // Load the input module...
  auto LLVMContext = std::make_unique<llvm::LLVMContext>();
  std::unique_ptr<llvm::Module> M =
      parseIRFile(InputFilename, Err, *LLVMContext.get());

  if (!M) {
    Err.print(argv[0], llvm::errs());
    return 1;
  }

  if (verifyModule(*M, &llvm::errs())) {
    llvm::errs() << argv[0] << ": " << InputFilename
           << ": error: input module is broken!\n";
    return 1;
  }

  // If we are supposed to override the target triple, do so now.
  if (!TargetTriple.empty())
    M->setTargetTriple(llvm::Triple::normalize(TargetTriple));

  // Figure out what stream we are supposed to write to...
  std::unique_ptr<llvm::ToolOutputFile> Out;
  // Default to standard output.
  if (OutputFilename.empty())
    OutputFilename = "-";

  std::error_code EC;
  Out.reset(
      new llvm::ToolOutputFile(OutputFilename, EC, llvm::sys::fs::F_None));
  if (EC) {
    llvm::errs() << EC.message() << '\n';
    return 1;
  }

  llvm::Triple ModuleTriple(M->getTargetTriple());
  std::string CPUStr, FeaturesStr;
  llvm::TargetMachine *Machine = nullptr;
  const llvm::TargetOptions Options =
      llvm::codegen::InitTargetOptionsFromCodeGenFlags(ModuleTriple);

  if (ModuleTriple.getArch()) {
    CPUStr = llvm::codegen::getCPUStr();
    FeaturesStr = llvm::codegen::getFeaturesStr();
    Machine = getTargetMachine(ModuleTriple, CPUStr, FeaturesStr, Options);
  }

  std::unique_ptr<llvm::TargetMachine> TM(Machine);

  // Override function attributes based on CPUStr, FeaturesStr, and command line
  // flags.
  llvm::codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M);

  if (Optimized) {
    IRGenOptions Opts;
    Opts.OptMode = OptimizationMode::ForSpeed;

    // Then perform the optimizations.
    performLLVMOptimizations(Opts, M.get(), TM.get());
  } else {
    runSpecificPasses(argv[0], M.get(), TM.get(), ModuleTriple);
  }

  // Finally dump the output.
  dumpOutput(*M, Out->os());

  return 0;
}
<commit_msg>[next] Update reference to initializeDwarfEHPreparePass<commit_after>//===--- LLVMOpt.cpp ------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// This is a simple reimplementation of opt that includes support for Swift-
/// specific LLVM passes. It is meant to make it easier to handle issues related
/// to transitioning to the new LLVM pass manager (which lacks the dynamism of
/// the old pass manager) and also problems during the code base transition to
/// that pass manager. Additionally it will enable a user to exactly simulate
/// Swift's LLVM pass pipeline by using the same pass pipeline building
/// machinery in IRGen, something not possible with opt.
///
//===----------------------------------------------------------------------===//

#include "swift/Subsystems.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/LLVMPasses/PassesFwd.h"
#include "swift/LLVMPasses/Passes.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/RegionPass.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/InitializePasses.h"
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"

using namespace swift;

static llvm::codegen::RegisterCodeGenFlags CGF;

//===----------------------------------------------------------------------===//
//                            Option Declarations
//===----------------------------------------------------------------------===//

// The OptimizationList is automatically populated with registered passes by the
// PassNameParser.
//
static llvm::cl::list<const llvm::PassInfo *, bool, llvm::PassNameParser>
    PassList(llvm::cl::desc("Optimizations available:"));

static llvm::cl::opt<bool>
    Optimized("O", llvm::cl::desc("Optimization level O. Similar to swift -O"));

// TODO: I wanted to call this 'verify', but some other pass is using this
// option.
static llvm::cl::opt<bool> VerifyEach(
    "verify-each",
    llvm::cl::desc("Should we spend time verifying that the IR is well "
                   "formed"));

static llvm::cl::opt<std::string>
    TargetTriple("mtriple",
                 llvm::cl::desc("Override target triple for module"));

static llvm::cl::opt<bool>
    PrintStats("print-stats",
               llvm::cl::desc("Should LLVM Statistics be printed"));

static llvm::cl::opt<std::string> InputFilename(llvm::cl::Positional,
                                          llvm::cl::desc("<input file>"),
                                          llvm::cl::init("-"),
                                          llvm::cl::value_desc("filename"));

static llvm::cl::opt<std::string>
    OutputFilename("o", llvm::cl::desc("Override output filename"),
                   llvm::cl::value_desc("filename"));

static llvm::cl::opt<std::string> DefaultDataLayout(
    "default-data-layout",
    llvm::cl::desc("data layout string to use if not specified by module"),
    llvm::cl::value_desc("layout-string"), llvm::cl::init(""));

//===----------------------------------------------------------------------===//
//                               Helper Methods
//===----------------------------------------------------------------------===//

static llvm::CodeGenOpt::Level GetCodeGenOptLevel() {
  // TODO: Is this the right thing to do here?
  if (Optimized)
    return llvm::CodeGenOpt::Default;
  return llvm::CodeGenOpt::None;
}

// Returns the TargetMachine instance or zero if no triple is provided.
static llvm::TargetMachine *
getTargetMachine(llvm::Triple TheTriple, StringRef CPUStr,
                 StringRef FeaturesStr, const llvm::TargetOptions &Options) {
  std::string Error;
  const auto *TheTarget = llvm::TargetRegistry::lookupTarget(
      llvm::codegen::getMArch(), TheTriple, Error);
  // Some modules don't specify a triple, and this is okay.
  if (!TheTarget) {
    return nullptr;
  }

  return TheTarget->createTargetMachine(
      TheTriple.getTriple(), CPUStr, FeaturesStr, Options,
      Optional<llvm::Reloc::Model>(llvm::codegen::getExplicitRelocModel()),
      llvm::codegen::getExplicitCodeModel(), GetCodeGenOptLevel());
}

static void dumpOutput(llvm::Module &M, llvm::raw_ostream &os) {
  // For now just always dump assembly.
  llvm::legacy::PassManager EmitPasses;
  EmitPasses.add(createPrintModulePass(os));
  EmitPasses.run(M);
}

// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// getMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement getMainExecutable
// without being given the address of a function in the main executable).
void anchorForGetMainExecutable() {}

static inline void addPass(llvm::legacy::PassManagerBase &PM, llvm::Pass *P) {
  // Add the pass to the pass manager...
  PM.add(P);
  if (P->getPassID() == &SwiftAAWrapperPass::ID) {
    PM.add(llvm::createExternalAAWrapperPass([](llvm::Pass &P, llvm::Function &,
                                                llvm::AAResults &AAR) {
      if (auto *WrapperPass = P.getAnalysisIfAvailable<SwiftAAWrapperPass>())
        AAR.addAAResult(WrapperPass->getResult());
    }));
  }

  // If we are verifying all of the intermediate steps, add the verifier...
  if (VerifyEach)
    PM.add(llvm::createVerifierPass());
}

static void runSpecificPasses(StringRef Binary, llvm::Module *M,
                              llvm::TargetMachine *TM,
                              llvm::Triple &ModuleTriple) {
  llvm::legacy::PassManager Passes;
  llvm::TargetLibraryInfoImpl TLII(ModuleTriple);
  Passes.add(new llvm::TargetLibraryInfoWrapperPass(TLII));

  const llvm::DataLayout &DL = M->getDataLayout();
  if (DL.isDefault() && !DefaultDataLayout.empty()) {
    M->setDataLayout(DefaultDataLayout);
  }

  // Add internal analysis passes from the target machine.
  Passes.add(createTargetTransformInfoWrapperPass(
      TM ? TM->getTargetIRAnalysis() : llvm::TargetIRAnalysis()));

  if (TM) {
    // FIXME: We should dyn_cast this when supported.
    auto &LTM = static_cast<llvm::LLVMTargetMachine &>(*TM);
    llvm::Pass *TPC = LTM.createPassConfig(Passes);
    Passes.add(TPC);
  }

  for (const llvm::PassInfo *PassInfo : PassList) {
    llvm::Pass *P = nullptr;
    if (PassInfo->getNormalCtor())
      P = PassInfo->getNormalCtor()();
    else
      llvm::errs() << Binary
                   << ": cannot create pass: " << PassInfo->getPassName()
                   << "\n";
    if (P) {
      addPass(Passes, P);
    }
  }

  // Do it.
  Passes.run(*M);
}

//===----------------------------------------------------------------------===//
//                            Main Implementation
//===----------------------------------------------------------------------===//

int main(int argc, char **argv) {
  PROGRAM_START(argc, argv);
  INITIALIZE_LLVM();

  // Initialize passes
  llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
  initializeCore(Registry);
  initializeScalarOpts(Registry);
  initializeObjCARCOpts(Registry);
  initializeVectorization(Registry);
  initializeIPO(Registry);
  initializeAnalysis(Registry);
  initializeTransformUtils(Registry);
  initializeInstCombine(Registry);
  initializeInstrumentation(Registry);
  initializeTarget(Registry);
  // For codegen passes, only passes that do IR to IR transformation are
  // supported.
  initializeCodeGenPreparePass(Registry);
  initializeAtomicExpandPass(Registry);
  initializeRewriteSymbolsLegacyPassPass(Registry);
  initializeWinEHPreparePass(Registry);
  initializeDwarfEHPrepareLegacyPassPass(Registry);
  initializeSjLjEHPreparePass(Registry);

  // Register Swift Only Passes.
  initializeSwiftAAWrapperPassPass(Registry);
  initializeSwiftRCIdentityPass(Registry);
  initializeSwiftARCOptPass(Registry);
  initializeSwiftARCContractPass(Registry);
  initializeInlineTreePrinterPass(Registry);
  initializeSwiftMergeFunctionsPass(Registry);

  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift LLVM optimizer\n");

  if (PrintStats)
    llvm::EnableStatistics();

  llvm::SMDiagnostic Err;

  // Load the input module...
  auto LLVMContext = std::make_unique<llvm::LLVMContext>();
  std::unique_ptr<llvm::Module> M =
      parseIRFile(InputFilename, Err, *LLVMContext.get());

  if (!M) {
    Err.print(argv[0], llvm::errs());
    return 1;
  }

  if (verifyModule(*M, &llvm::errs())) {
    llvm::errs() << argv[0] << ": " << InputFilename
           << ": error: input module is broken!\n";
    return 1;
  }

  // If we are supposed to override the target triple, do so now.
  if (!TargetTriple.empty())
    M->setTargetTriple(llvm::Triple::normalize(TargetTriple));

  // Figure out what stream we are supposed to write to...
  std::unique_ptr<llvm::ToolOutputFile> Out;
  // Default to standard output.
  if (OutputFilename.empty())
    OutputFilename = "-";

  std::error_code EC;
  Out.reset(
      new llvm::ToolOutputFile(OutputFilename, EC, llvm::sys::fs::F_None));
  if (EC) {
    llvm::errs() << EC.message() << '\n';
    return 1;
  }

  llvm::Triple ModuleTriple(M->getTargetTriple());
  std::string CPUStr, FeaturesStr;
  llvm::TargetMachine *Machine = nullptr;
  const llvm::TargetOptions Options =
      llvm::codegen::InitTargetOptionsFromCodeGenFlags(ModuleTriple);

  if (ModuleTriple.getArch()) {
    CPUStr = llvm::codegen::getCPUStr();
    FeaturesStr = llvm::codegen::getFeaturesStr();
    Machine = getTargetMachine(ModuleTriple, CPUStr, FeaturesStr, Options);
  }

  std::unique_ptr<llvm::TargetMachine> TM(Machine);

  // Override function attributes based on CPUStr, FeaturesStr, and command line
  // flags.
  llvm::codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M);

  if (Optimized) {
    IRGenOptions Opts;
    Opts.OptMode = OptimizationMode::ForSpeed;

    // Then perform the optimizations.
    performLLVMOptimizations(Opts, M.get(), TM.get());
  } else {
    runSpecificPasses(argv[0], M.get(), TM.get(), ModuleTriple);
  }

  // Finally dump the output.
  dumpOutput(*M, Out->os());

  return 0;
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * usbpro-firmware.cpp
 * Copyright (C) 2005 Simon Newton
 */

#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <sysexits.h>
#include <termios.h>
#include <ola/Logging.h>
#include <ola/Callback.h>
#include <ola/io/SelectServer.h>

#include <iostream>
#include <fstream>
#include <string>

#include "plugins/usbpro/BaseUsbProWidget.h"

using std::cout;
using std::endl;
using std::ifstream;
using std::string;
using ola::plugin::usbpro::DispatchingUsbProWidget;
using ola::io::SelectServer;

static const char DEFAULT_DEVICE[] = "/dev/ttyUSB0";
static const char DEFAULT_FIRMWARE[] = "main.bin";
static const int PAUSE_DELAY = 1000;  // ms before starting upload
static const int ABORT_TIMEOUT = 10 * 1000;  // ms seconds before aborting

typedef struct {
  bool help;
  ola::log_level log_level;
  string firmware;
  string device;
} options;

class FirmwareTransferer {
  public:
    FirmwareTransferer(ifstream *file,
                       DispatchingUsbProWidget *widget,
                       SelectServer *ss):
        m_sucessful(false),
        m_firmware(file),
        m_widget(widget),
        m_ss(ss) {
    }

    bool SendReprogram();

    void HandleMessage(uint8_t label,
                       const uint8_t *data,
                       unsigned int length);
    bool SendNextChunk();
    void AbortTransfer() {
      m_ss->Terminate();
    }
    void StartTransfer() {
      SendNextChunk();
    }
    bool WasSucessfull() const { return m_sucessful; }

  private:
    enum { FLASH_STATUS_LENGTH = 4 };
    enum { FLASH_PAGE_LENGTH = 64 };

    bool m_sucessful;
    ifstream *m_firmware;
    DispatchingUsbProWidget *m_widget;
    SelectServer *m_ss;

    static const uint8_t REPROGRAM_LABEL = 1;
    static const uint8_t FLASH_PAGE_LABEL = 2;
    static const char REPLY_SUCCESS[];
};

const char FirmwareTransferer::REPLY_SUCCESS[] = "TRUE";

/*
 * Send the re-program request
 */
bool FirmwareTransferer::SendReprogram() {
  return m_widget->SendMessage(REPROGRAM_LABEL, NULL, 0);
}

/*
 * Handle the flash page replies
 */
void FirmwareTransferer::HandleMessage(uint8_t label,
                                       const uint8_t *data,
                                       unsigned int length) {
  if (label != FLASH_PAGE_LABEL || length != FLASH_STATUS_LENGTH)
    return;

  if (0 == memcmp(data, REPLY_SUCCESS, sizeof(FLASH_STATUS_LENGTH))) {
    if (!SendNextChunk() || m_sucessful)
      m_ss->Terminate();
  } else {
    OLA_FATAL << "Bad response from widget:" << string((const char*) data, 4);
    m_ss->Terminate();
  }
}

/*
 * Send the next chunk of the firmware file
 */
bool FirmwareTransferer::SendNextChunk() {
  uint8_t page[FLASH_PAGE_LENGTH];
  m_firmware->read(reinterpret_cast<char*>(page),
                   FLASH_PAGE_LENGTH);
  std::streamsize size = m_firmware->gcount();

  if (!size) {
    m_sucessful = true;
    cout << endl;
    return true;
  }
  cout << ".";
  fflush(stdout);
  return m_widget->SendMessage(FLASH_PAGE_LABEL, page, size);
}

/*
 * Parse our command line options
 */
void ParseOptions(int argc, char *argv[], options *opts) {
  static struct option long_options[] = {
      {"device", required_argument, 0, 'd'},
      {"firmware", required_argument, 0, 'f'},
      {"help", no_argument, 0, 'h'},
      {"log-level", required_argument, 0, 'l'},
      {0, 0, 0, 0}
    };

  int option_index = 0;

  while (1) {
    int c = getopt_long(argc, argv, "d:f:hl:", long_options, &option_index);

    if (c == -1)
      break;

    switch (c) {
      case 0:
        break;

      case 'd':
        opts->device = optarg;
        break;

      case 'f':
        opts->firmware = optarg;
        break;

      case 'h':
        opts->help = true;
        break;

      case 'l':
        switch (atoi(optarg)) {
          case 0:
            // nothing is written at this level
            // so this turns logging off
            opts->log_level = ola::OLA_LOG_NONE;
            break;
          case 1:
            opts->log_level = ola::OLA_LOG_FATAL;
            break;
          case 2:
            opts->log_level = ola::OLA_LOG_WARN;
            break;
          case 3:
            opts->log_level = ola::OLA_LOG_INFO;
            break;
          case 4:
            opts->log_level = ola::OLA_LOG_DEBUG;
            break;
          default :
            break;
        }
        break;
      case '?':
        break;
      default:
       break;
    }
  }
  return;
}

/*
 * Display the help message
 */
void DisplayHelpAndExit(char *argv[]) {
  cout << "Usage: " << argv[0] <<
  " -d <device> -f <firmware_file>\n"
  "\n"
  "Flash the firmware on an Enttec USB Pro device.\n"
  "\n"
  "  -d <device_path>   The path to the device.\n"
  "  -f <firmware_file> The path to the firmware to use.\n"
  "  -h, --help         Display this help message and exit.\n"
  "  -l, --log-level <level>  Set the logging level 0 .. 4.\n"
  << endl;
  exit(0);
}

void Stop(SelectServer *ss) {
  ss->Terminate();
}

/*
 * Flashes the device
 */
int main(int argc, char *argv[]) {
  options opts;
  opts.log_level = ola::OLA_LOG_WARN;
  opts.help = false;
  opts.firmware = DEFAULT_FIRMWARE;
  opts.device = DEFAULT_DEVICE;
  ParseOptions(argc, argv, &opts);

  if (opts.help)
    DisplayHelpAndExit(argv);
  ola::InitLogging(opts.log_level, ola::OLA_LOG_STDERR);

  ifstream firmware_file(opts.firmware.data());

  if (!firmware_file.is_open()) {
    OLA_FATAL << "Can't open the firmware file " << opts.firmware << ": " <<
      strerror(errno);
    exit(1);
  }

  SelectServer ss;

  ola::io::ConnectedDescriptor *descriptor =
     ola::plugin::usbpro::BaseUsbProWidget::OpenDevice(opts.device);
  if (!descriptor)
    exit(EX_UNAVAILABLE);

  descriptor->SetOnClose(ola::NewSingleCallback(&Stop, &ss));
  ss.AddReadDescriptor(descriptor);
  DispatchingUsbProWidget widget(descriptor, NULL);
  FirmwareTransferer transferer(&firmware_file, &widget, &ss);
  widget.SetHandler(
      ola::NewCallback(&transferer, &FirmwareTransferer::HandleMessage));

  if (!transferer.SendReprogram()) {
    OLA_FATAL << "Send message failed";
    exit(1);
  }

  ss.RegisterSingleTimeout(
      PAUSE_DELAY,
      ola::NewSingleCallback(&transferer, &FirmwareTransferer::StartTransfer));
  widget.GetDescriptor()->SetOnClose(
      ola::NewSingleCallback(&transferer, &FirmwareTransferer::AbortTransfer));
  ss.RegisterSingleTimeout(
      ABORT_TIMEOUT,
      ola::NewSingleCallback(&transferer, &FirmwareTransferer::AbortTransfer));
  ss.Run();

  firmware_file.close();
  return !transferer.WasSucessfull();
}
<commit_msg>Show long options<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * usbpro-firmware.cpp
 * Copyright (C) 2005 Simon Newton
 */

#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <sysexits.h>
#include <termios.h>
#include <ola/Logging.h>
#include <ola/Callback.h>
#include <ola/io/SelectServer.h>

#include <iostream>
#include <fstream>
#include <string>

#include "plugins/usbpro/BaseUsbProWidget.h"

using std::cout;
using std::endl;
using std::ifstream;
using std::string;
using ola::plugin::usbpro::DispatchingUsbProWidget;
using ola::io::SelectServer;

static const char DEFAULT_DEVICE[] = "/dev/ttyUSB0";
static const char DEFAULT_FIRMWARE[] = "main.bin";
static const int PAUSE_DELAY = 1000;  // ms before starting upload
static const int ABORT_TIMEOUT = 10 * 1000;  // ms seconds before aborting

typedef struct {
  bool help;
  ola::log_level log_level;
  string firmware;
  string device;
} options;

class FirmwareTransferer {
  public:
    FirmwareTransferer(ifstream *file,
                       DispatchingUsbProWidget *widget,
                       SelectServer *ss):
        m_sucessful(false),
        m_firmware(file),
        m_widget(widget),
        m_ss(ss) {
    }

    bool SendReprogram();

    void HandleMessage(uint8_t label,
                       const uint8_t *data,
                       unsigned int length);
    bool SendNextChunk();
    void AbortTransfer() {
      m_ss->Terminate();
    }
    void StartTransfer() {
      SendNextChunk();
    }
    bool WasSucessfull() const { return m_sucessful; }

  private:
    enum { FLASH_STATUS_LENGTH = 4 };
    enum { FLASH_PAGE_LENGTH = 64 };

    bool m_sucessful;
    ifstream *m_firmware;
    DispatchingUsbProWidget *m_widget;
    SelectServer *m_ss;

    static const uint8_t REPROGRAM_LABEL = 1;
    static const uint8_t FLASH_PAGE_LABEL = 2;
    static const char REPLY_SUCCESS[];
};

const char FirmwareTransferer::REPLY_SUCCESS[] = "TRUE";

/*
 * Send the re-program request
 */
bool FirmwareTransferer::SendReprogram() {
  return m_widget->SendMessage(REPROGRAM_LABEL, NULL, 0);
}

/*
 * Handle the flash page replies
 */
void FirmwareTransferer::HandleMessage(uint8_t label,
                                       const uint8_t *data,
                                       unsigned int length) {
  if (label != FLASH_PAGE_LABEL || length != FLASH_STATUS_LENGTH)
    return;

  if (0 == memcmp(data, REPLY_SUCCESS, sizeof(FLASH_STATUS_LENGTH))) {
    if (!SendNextChunk() || m_sucessful)
      m_ss->Terminate();
  } else {
    OLA_FATAL << "Bad response from widget:" << string((const char*) data, 4);
    m_ss->Terminate();
  }
}

/*
 * Send the next chunk of the firmware file
 */
bool FirmwareTransferer::SendNextChunk() {
  uint8_t page[FLASH_PAGE_LENGTH];
  m_firmware->read(reinterpret_cast<char*>(page),
                   FLASH_PAGE_LENGTH);
  std::streamsize size = m_firmware->gcount();

  if (!size) {
    m_sucessful = true;
    cout << endl;
    return true;
  }
  cout << ".";
  fflush(stdout);
  return m_widget->SendMessage(FLASH_PAGE_LABEL, page, size);
}

/*
 * Parse our command line options
 */
void ParseOptions(int argc, char *argv[], options *opts) {
  static struct option long_options[] = {
      {"device", required_argument, 0, 'd'},
      {"firmware", required_argument, 0, 'f'},
      {"help", no_argument, 0, 'h'},
      {"log-level", required_argument, 0, 'l'},
      {0, 0, 0, 0}
    };

  int option_index = 0;

  while (1) {
    int c = getopt_long(argc, argv, "d:f:hl:", long_options, &option_index);

    if (c == -1)
      break;

    switch (c) {
      case 0:
        break;

      case 'd':
        opts->device = optarg;
        break;

      case 'f':
        opts->firmware = optarg;
        break;

      case 'h':
        opts->help = true;
        break;

      case 'l':
        switch (atoi(optarg)) {
          case 0:
            // nothing is written at this level
            // so this turns logging off
            opts->log_level = ola::OLA_LOG_NONE;
            break;
          case 1:
            opts->log_level = ola::OLA_LOG_FATAL;
            break;
          case 2:
            opts->log_level = ola::OLA_LOG_WARN;
            break;
          case 3:
            opts->log_level = ola::OLA_LOG_INFO;
            break;
          case 4:
            opts->log_level = ola::OLA_LOG_DEBUG;
            break;
          default :
            break;
        }
        break;
      case '?':
        break;
      default:
       break;
    }
  }
  return;
}

/*
 * Display the help message
 */
void DisplayHelpAndExit(char *argv[]) {
  cout << "Usage: " << argv[0] <<
  " -d <device> -f <firmware_file>\n"
  "\n"
  "Flash the firmware on an Enttec USB Pro device.\n"
  "\n"
  "  -d, --device <device_path>   The path to the device.\n"
  "  -f, --firmware <firmware_file> The path to the firmware to use.\n"
  "  -h, --help         Display this help message and exit.\n"
  "  -l, --log-level <level>  Set the logging level 0 .. 4.\n"
  << endl;
  exit(0);
}

void Stop(SelectServer *ss) {
  ss->Terminate();
}

/*
 * Flashes the device
 */
int main(int argc, char *argv[]) {
  options opts;
  opts.log_level = ola::OLA_LOG_WARN;
  opts.help = false;
  opts.firmware = DEFAULT_FIRMWARE;
  opts.device = DEFAULT_DEVICE;
  ParseOptions(argc, argv, &opts);

  if (opts.help)
    DisplayHelpAndExit(argv);
  ola::InitLogging(opts.log_level, ola::OLA_LOG_STDERR);

  ifstream firmware_file(opts.firmware.data());

  if (!firmware_file.is_open()) {
    OLA_FATAL << "Can't open the firmware file " << opts.firmware << ": " <<
      strerror(errno);
    exit(1);
  }

  SelectServer ss;

  ola::io::ConnectedDescriptor *descriptor =
     ola::plugin::usbpro::BaseUsbProWidget::OpenDevice(opts.device);
  if (!descriptor)
    exit(EX_UNAVAILABLE);

  descriptor->SetOnClose(ola::NewSingleCallback(&Stop, &ss));
  ss.AddReadDescriptor(descriptor);
  DispatchingUsbProWidget widget(descriptor, NULL);
  FirmwareTransferer transferer(&firmware_file, &widget, &ss);
  widget.SetHandler(
      ola::NewCallback(&transferer, &FirmwareTransferer::HandleMessage));

  if (!transferer.SendReprogram()) {
    OLA_FATAL << "Send message failed";
    exit(1);
  }

  ss.RegisterSingleTimeout(
      PAUSE_DELAY,
      ola::NewSingleCallback(&transferer, &FirmwareTransferer::StartTransfer));
  widget.GetDescriptor()->SetOnClose(
      ola::NewSingleCallback(&transferer, &FirmwareTransferer::AbortTransfer));
  ss.RegisterSingleTimeout(
      ABORT_TIMEOUT,
      ola::NewSingleCallback(&transferer, &FirmwareTransferer::AbortTransfer));
  ss.Run();

  firmware_file.close();
  return !transferer.WasSucessfull();
}
<|endoftext|>


<commit_before># include <QuadProg++.hh>
# include <exception>
# include <string.h>

extern "C" double hs_solve_quadprog(
  int n_vars, int n_ce, int n_ci,
  const double *G_,
  const double *g0_,
  const double *CE_,
  const double *ce0_,
  const double *CI_,
  const double *ci0_,
  double *x_,
  const char **p_errorstr) try
{
  using namespace QuadProgPP;
  Matrix<double> G(G_, n_vars, n_vars);
  Vector<double> g0(g0_, n_vars);
  Matrix<double> CE(CE_, n_vars, n_ce);
  Vector<double> ce0(ce0_, n_ce);
  Matrix<double> CI(CI_, n_vars, n_ci);
  Vector<double> ci0(ci0_, n_ci);
  Vector<double> x;
  double r = solve_quadprog(G, g0, CE, ce0, CI, ci0, x);
  for(int i = 0; i < n_vars; i++)
    x_[i] = x[i];
  *p_errorstr = 0;
  return r;
} catch(const std::exception &e) {
  *p_errorstr = strdup(e.what());
  return 0;
} catch(...) {
  *p_errorstr = strdup("unknown C++ error");
  return 0;
}
<commit_msg>Support the quadprogpp namespace<commit_after># include <QuadProg++.hh>
# include <exception>
# include <string.h>

/* These namespaces may or may not be defined, depending on the version of
 * QuadProg++. Here we make sure the are all defined, so that we can be `using`
 * them later.
 */

namespace QuadProgPP{}
namespace quadprogpp{}

extern "C" double hs_solve_quadprog(
  int n_vars, int n_ce, int n_ci,
  const double *G_,
  const double *g0_,
  const double *CE_,
  const double *ce0_,
  const double *CI_,
  const double *ci0_,
  double *x_,
  const char **p_errorstr) try
{
  /* Depending on the version, the names may be in the global namespace, the
   * QuadProgPP namespace or the quadprogpp namespace.
   */
  using namespace QuadProgPP;
  using namespace quadprogpp;
  Matrix<double> G(G_, n_vars, n_vars);
  Vector<double> g0(g0_, n_vars);
  Matrix<double> CE(CE_, n_vars, n_ce);
  Vector<double> ce0(ce0_, n_ce);
  Matrix<double> CI(CI_, n_vars, n_ci);
  Vector<double> ci0(ci0_, n_ci);
  Vector<double> x;
  double r = solve_quadprog(G, g0, CE, ce0, CI, ci0, x);
  for(int i = 0; i < n_vars; i++)
    x_[i] = x[i];
  *p_errorstr = 0;
  return r;
} catch(const std::exception &e) {
  *p_errorstr = strdup(e.what());
  return 0;
} catch(...) {
  *p_errorstr = strdup("unknown C++ error");
  return 0;
}
<|endoftext|>