<commit_before>// Copyright 2014 MongoDB Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cstdint>

#include "bson/builder.hpp"

#include "driver/libmongoc.hpp"

#include "driver/base/private/client.hpp"
#include "driver/base/private/collection.hpp"
#include "driver/base/private/database.hpp"
#include "driver/base/private/pipeline.hpp"
#include "driver/model/private/bulk_write.hpp"
#include "driver/base/collection.hpp"
#include "driver/base/client.hpp"
#include "driver/model/aggregate.hpp"
#include "driver/model/find.hpp"
#include "driver/model/find_one_and_replace.hpp"
#include "driver/model/find_one_and_delete.hpp"
#include "driver/model/find_one_and_update.hpp"
#include "driver/model/insert_one.hpp"
#include "driver/model/update_one.hpp"
#include "driver/result/bulk_write.hpp"
#include "driver/result/insert_many.hpp"
#include "driver/result/insert_one.hpp"
#include "driver/result/delete.hpp"
#include "driver/result/replace_one.hpp"
#include "driver/result/update.hpp"
#include "driver/result/write.hpp"
#include "driver/result/bulk_write.hpp"
#include "driver/request/insert.hpp"
#include "driver/util/libbson.hpp"
#include "driver/model/bulk_write.hpp"
#include "driver/model/write.hpp"

#include "driver/base/private/write_concern.hpp"
#include "driver/base/private/read_preference.hpp"

namespace mongo {
namespace driver {

using namespace bson::libbson;

collection::collection(collection&&) = default;
collection& collection::operator=(collection&&) = default;
collection::~collection() = default;

collection::collection(const database& database, const std::string& collection_name)
    : _impl(new impl{
          mongoc_database_get_collection(database._impl->database_t, collection_name.c_str()),
          &database, database._impl->client, collection_name.c_str()}) {}

result::bulk_write collection::bulk_write(const model::bulk_write& model) {
    using namespace model;

    mongoc_bulk_operation_t* b = model._impl->operation_t;
    mongoc_bulk_operation_set_database(b, _impl->database->_impl->name.c_str());
    mongoc_bulk_operation_set_collection(b, _impl->name.c_str());
    mongoc_bulk_operation_set_client(b, _impl->client->_impl->client_t);

    if (model.write_concern()) {
        priv::write_concern wc(*model.write_concern());

        mongoc_bulk_operation_set_write_concern(b, wc.get_write_concern());
    } else {
        mongoc_bulk_operation_set_write_concern(
            b, mongoc_collection_get_write_concern(_impl->collection_t));
    }

    result::bulk_write result;

    scoped_bson_t reply;
    reply.flag_init();

    bson_error_t error;

    if (!mongoc_bulk_operation_execute(b, reply.bson(), &error)) {
        throw std::runtime_error(error.message);
    }

    bson::document::view reply_view = reply.view();

    result.is_acknowledged = true;
    result.inserted_count = reply_view["nInserted"].get_int32();
    result.matched_count = reply_view["nMatched"].get_int32();
    result.modified_count = reply_view["nModified"].get_int32();
    result.deleted_count = reply_view["nRemoved"].get_int32();
    result.upserted_count = reply_view["nUpserted"].get_int32();

    return result;
}

cursor collection::find(const model::find& model) const {
    using namespace bson;

    builder::document filter_builder;

    scoped_bson_t filter;
    scoped_bson_t projection(model.projection());

    if (model.modifiers()) {
        filter_builder << "$query" << types::b_document{model.criteria()}
                       << builder::helpers::concat{model.modifiers().value_or(document::view{})};

        filter.init_from_static(filter_builder.view());
    } else {
        filter.init_from_static(model.criteria());
    }

    optional<priv::read_preference> read_prefs;
    const mongoc_read_prefs_t* rp_ptr;

    if (model.read_preference()) {
        read_prefs = priv::read_preference{*model.read_preference()};
        rp_ptr = read_prefs->get_read_preference();
    } else {
        rp_ptr = mongoc_collection_get_read_prefs(_impl->collection_t);
    }

    return cursor(mongoc_collection_find(
        _impl->collection_t, (mongoc_query_flags_t)model.cursor_flags().value_or(0),
        model.skip().value_or(0), model.limit().value_or(0), model.batch_size().value_or(0),
        filter.bson(), projection.bson(), rp_ptr));
}

optional<bson::document::value> collection::find_one(const model::find& model) const {
    model::find copy(model);
    copy.limit(1);
    return bson::document::value{*find(copy).begin()};
}

cursor collection::aggregate(const model::aggregate& model) {
    using namespace bson::builder::helpers;

    scoped_bson_t pipeline(model.stages()._impl->view());

    bson::builder::document b;

    if (model.allow_disk_use()) {
        /* TODO */
    }
    if (model.use_cursor()) {
        auto inner = b << "cursor" << open_doc;

        if (model.batch_size()) {
            inner << "batchSize" << *model.batch_size();
        }

        inner << close_doc;
    }

    if (model.max_time_ms()) {
        /* TODO */
    }

    scoped_bson_t options(b.view());

    optional<priv::read_preference> read_prefs;
    const mongoc_read_prefs_t* rp_ptr;

    if (model.read_preference()) {
        read_prefs = priv::read_preference{*model.read_preference()};
        rp_ptr = read_prefs->get_read_preference();
    } else {
        rp_ptr = mongoc_collection_get_read_prefs(_impl->collection_t);
    }

    return cursor(mongoc_collection_aggregate(_impl->collection_t,
                                              static_cast<mongoc_query_flags_t>(0), pipeline.bson(),
                                              options.bson(), rp_ptr));
}

result::insert_one collection::insert_one(const model::insert_one& model) {
    result::bulk_write res(bulk_write(model::bulk_write(false).append(model)));

    result::insert_one result;
    result.is_acknowledged = true;
    return result;
}

result::insert_many collection::insert_many(const model::insert_many& model) {
    result::bulk_write res(bulk_write(model::bulk_write(false).append(model)));
    result::insert_many result;
    result.is_acknowledged = true;
    return result;
}

result::replace_one collection::replace_one(const model::replace_one& /* model */) {
    return result::replace_one();
}

result::update collection::update_many(const model::update_many& /* model */) {
    return result::update();
}

result::delete_result collection::delete_many(const model::delete_many& model) {
    result::bulk_write res(bulk_write(model::bulk_write(false).append(model)));
    result::delete_result result;
    result.is_acknowledged = true;
    return result;
}

result::update collection::update_one(const model::update_one& model) {
    result::bulk_write res(bulk_write(model::bulk_write(false).append(model)));
    result::update result;
    result.is_acknowledged = true;
    return result;
}

result::delete_result collection::delete_one(const model::delete_one& model) {
    result::bulk_write res(bulk_write(model::bulk_write(false).append(model)));
    result::delete_result result;
    result.is_acknowledged = true;
    return result;
}

optional<bson::document::value> collection::find_one_and_replace(
    const model::find_one_and_replace& model) {
    scoped_bson_t criteria{model.criteria()};
    scoped_bson_t sort{model.sort()};
    scoped_bson_t replacement{model.replacement()};
    scoped_bson_t projection{model.projection()};
    scoped_bson_t reply;
    reply.flag_init();

    bson_error_t error;

    bool r = mongoc_collection_find_and_modify(
        _impl->collection_t, criteria.bson(), sort.bson(), replacement.bson(), projection.bson(),
        false, model.upsert().value_or(false), model.return_replacement().value_or(false),
        reply.bson(), &error);

    if (!r) {
        throw std::runtime_error("shits fucked");
    }

    bson::document::view result = reply.view();

    if (result["value"].type() == bson::type::k_null) {
        return optional<bson::document::value>{};
    } else {
        using namespace bson::builder::helpers;

        bson::builder::document b;

        b << concat{result["value"].get_document()};

        return b.extract();
    }
}

optional<bson::document::value> collection::find_one_and_update(
    const model::find_one_and_update& model) {
    scoped_bson_t criteria{model.criteria()};
    scoped_bson_t sort{model.sort()};
    scoped_bson_t update{model.update()};
    scoped_bson_t projection{model.projection()};
    scoped_bson_t reply;
    reply.flag_init();

    bson_error_t error;

    bool r = mongoc_collection_find_and_modify(
        _impl->collection_t, criteria.bson(), sort.bson(), update.bson(), projection.bson(), false,
        model.upsert().value_or(false), model.return_replacement().value_or(false), reply.bson(),
        &error);

    if (!r) {
        throw std::runtime_error("shits fucked");
    }

    bson::document::view result = reply.view();

    if (result["value"].type() == bson::type::k_null) {
        return optional<bson::document::value>{};
    } else {
        using namespace bson::builder::helpers;

        bson::builder::document b;

        b << concat{result["value"].get_document()};

        return b.extract();
    }
}

optional<bson::document::value> collection::find_one_and_delete(
    const model::find_one_and_delete& model) {
    scoped_bson_t criteria{model.criteria()};
    scoped_bson_t sort{model.sort()};
    scoped_bson_t projection{model.projection()};
    scoped_bson_t reply;
    reply.flag_init();

    bson_error_t error;

    bool r = mongoc_collection_find_and_modify(_impl->collection_t, criteria.bson(), sort.bson(),
                                               nullptr, projection.bson(), true, false, false,
                                               reply.bson(), &error);

    if (!r) {
        throw std::runtime_error("shits fucked");
    }

    bson::document::view result = reply.view();

    if (result["value"].type() == bson::type::k_null) {
        return optional<bson::document::value>{};
    } else {
        using namespace bson::builder::helpers;

        bson::builder::document b;

        b << concat{result["value"].get_document()};

        return b.extract();
    }
}

bson::document::value collection::explain(const model::explain& /*model*/) const {
    return bson::document::value((const std::uint8_t*)nullptr, 0);
}

std::int64_t collection::count(const model::count& model) const {
    scoped_bson_t criteria{model.criteria()};
    bson_error_t error;

    optional<priv::read_preference> read_prefs;
    const mongoc_read_prefs_t* rp_ptr;

    if (model.read_preference()) {
        read_prefs = priv::read_preference{*model.read_preference()};
        rp_ptr = read_prefs->get_read_preference();
    } else {
        rp_ptr = mongoc_collection_get_read_prefs(_impl->collection_t);
    }

    auto result = mongoc_collection_count(_impl->collection_t, static_cast<mongoc_query_flags_t>(0),
                                          criteria.bson(), model.skip().value_or(0),
                                          model.limit().value_or(0), rp_ptr, &error);

    /* TODO throw an exception if error
    if (result < 0)
    */

    return result;
}

void collection::drop() {
    bson_error_t error;

    if (mongoc_collection_drop(_impl->collection_t, &error)) {
        /* TODO handle errors */
    }
}

void collection::read_preference(class read_preference rp) {
    _impl->read_preference(std::move(rp));
}
const class read_preference& collection::read_preference() const {
    return _impl->read_preference();
}

void collection::write_concern(class write_concern wc) { _impl->write_concern(std::move(wc)); }

const class write_concern& collection::write_concern() const { return _impl->write_concern(); }

}  // namespace driver
}  // namespace mongo
<commit_msg>use provided write concern for writes<commit_after>// Copyright 2014 MongoDB Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cstdint>

#include "bson/builder.hpp"

#include "driver/libmongoc.hpp"

#include "driver/base/private/client.hpp"
#include "driver/base/private/collection.hpp"
#include "driver/base/private/database.hpp"
#include "driver/base/private/pipeline.hpp"
#include "driver/model/private/bulk_write.hpp"
#include "driver/base/collection.hpp"
#include "driver/base/client.hpp"
#include "driver/model/aggregate.hpp"
#include "driver/model/find.hpp"
#include "driver/model/find_one_and_replace.hpp"
#include "driver/model/find_one_and_delete.hpp"
#include "driver/model/find_one_and_update.hpp"
#include "driver/model/insert_one.hpp"
#include "driver/model/update_one.hpp"
#include "driver/result/bulk_write.hpp"
#include "driver/result/insert_many.hpp"
#include "driver/result/insert_one.hpp"
#include "driver/result/delete.hpp"
#include "driver/result/replace_one.hpp"
#include "driver/result/update.hpp"
#include "driver/result/write.hpp"
#include "driver/result/bulk_write.hpp"
#include "driver/request/insert.hpp"
#include "driver/util/libbson.hpp"
#include "driver/model/bulk_write.hpp"
#include "driver/model/write.hpp"

#include "driver/base/private/write_concern.hpp"
#include "driver/base/private/read_preference.hpp"

namespace mongo {
namespace driver {

using namespace bson::libbson;

collection::collection(collection&&) = default;
collection& collection::operator=(collection&&) = default;
collection::~collection() = default;

collection::collection(const database& database, const std::string& collection_name)
    : _impl(new impl{
          mongoc_database_get_collection(database._impl->database_t, collection_name.c_str()),
          &database, database._impl->client, collection_name.c_str()}) {}

result::bulk_write collection::bulk_write(const model::bulk_write& model) {
    using namespace model;

    mongoc_bulk_operation_t* b = model._impl->operation_t;
    mongoc_bulk_operation_set_database(b, _impl->database->_impl->name.c_str());
    mongoc_bulk_operation_set_collection(b, _impl->name.c_str());
    mongoc_bulk_operation_set_client(b, _impl->client->_impl->client_t);

    if (model.write_concern()) {
        priv::write_concern wc(*model.write_concern());

        mongoc_bulk_operation_set_write_concern(b, wc.get_write_concern());
    } else {
        mongoc_bulk_operation_set_write_concern(
            b, mongoc_collection_get_write_concern(_impl->collection_t));
    }

    result::bulk_write result;

    scoped_bson_t reply;
    reply.flag_init();

    bson_error_t error;

    if (!mongoc_bulk_operation_execute(b, reply.bson(), &error)) {
        throw std::runtime_error(error.message);
    }

    bson::document::view reply_view = reply.view();

    result.is_acknowledged = true;
    result.inserted_count = reply_view["nInserted"].get_int32();
    result.matched_count = reply_view["nMatched"].get_int32();
    result.modified_count = reply_view["nModified"].get_int32();
    result.deleted_count = reply_view["nRemoved"].get_int32();
    result.upserted_count = reply_view["nUpserted"].get_int32();

    return result;
}

cursor collection::find(const model::find& model) const {
    using namespace bson;

    builder::document filter_builder;

    scoped_bson_t filter;
    scoped_bson_t projection(model.projection());

    if (model.modifiers()) {
        filter_builder << "$query" << types::b_document{model.criteria()}
                       << builder::helpers::concat{model.modifiers().value_or(document::view{})};

        filter.init_from_static(filter_builder.view());
    } else {
        filter.init_from_static(model.criteria());
    }

    optional<priv::read_preference> read_prefs;
    const mongoc_read_prefs_t* rp_ptr;

    if (model.read_preference()) {
        read_prefs = priv::read_preference{*model.read_preference()};
        rp_ptr = read_prefs->get_read_preference();
    } else {
        rp_ptr = mongoc_collection_get_read_prefs(_impl->collection_t);
    }

    return cursor(mongoc_collection_find(
        _impl->collection_t, (mongoc_query_flags_t)model.cursor_flags().value_or(0),
        model.skip().value_or(0), model.limit().value_or(0), model.batch_size().value_or(0),
        filter.bson(), projection.bson(), rp_ptr));
}

optional<bson::document::value> collection::find_one(const model::find& model) const {
    model::find copy(model);
    copy.limit(1);
    return bson::document::value{*find(copy).begin()};
}

cursor collection::aggregate(const model::aggregate& model) {
    using namespace bson::builder::helpers;

    scoped_bson_t pipeline(model.stages()._impl->view());

    bson::builder::document b;

    if (model.allow_disk_use()) {
        /* TODO */
    }
    if (model.use_cursor()) {
        auto inner = b << "cursor" << open_doc;

        if (model.batch_size()) {
            inner << "batchSize" << *model.batch_size();
        }

        inner << close_doc;
    }

    if (model.max_time_ms()) {
        /* TODO */
    }

    scoped_bson_t options(b.view());

    optional<priv::read_preference> read_prefs;
    const mongoc_read_prefs_t* rp_ptr;

    if (model.read_preference()) {
        read_prefs = priv::read_preference{*model.read_preference()};
        rp_ptr = read_prefs->get_read_preference();
    } else {
        rp_ptr = mongoc_collection_get_read_prefs(_impl->collection_t);
    }

    return cursor(mongoc_collection_aggregate(_impl->collection_t,
                                              static_cast<mongoc_query_flags_t>(0), pipeline.bson(),
                                              options.bson(), rp_ptr));
}

result::insert_one collection::insert_one(const model::insert_one& model) {
    model::bulk_write bulk_op(false);
    bulk_op.append(model);

    if (model.write_concern())
        bulk_op.write_concern(*model.write_concern());

    result::bulk_write res(bulk_write(bulk_op));

    result::insert_one result;
    result.is_acknowledged = true;
    return result;
}

result::insert_many collection::insert_many(const model::insert_many& model) {
    model::bulk_write bulk_op(false);
    bulk_op.append(model);

    if (model.write_concern())
        bulk_op.write_concern(*model.write_concern());

    result::bulk_write res(bulk_write(bulk_op));

    result::insert_many result;
    result.is_acknowledged = true;
    return result;
}

result::replace_one collection::replace_one(const model::replace_one& /* model */) {
    return result::replace_one();
}

result::update collection::update_many(const model::update_many& /* model */) {
    return result::update();
}

result::delete_result collection::delete_many(const model::delete_many& model) {
    model::bulk_write bulk_op(false);
    bulk_op.append(model);

    if (model.write_concern())
        bulk_op.write_concern(*model.write_concern());

    result::bulk_write res(bulk_write(bulk_op));

    result::delete_result result;
    result.is_acknowledged = true;
    return result;
}

result::update collection::update_one(const model::update_one& model) {
    model::bulk_write bulk_op(false);
    bulk_op.append(model);

    if (model.write_concern())
        bulk_op.write_concern(*model.write_concern());

    result::bulk_write res(bulk_write(bulk_op));

    result::update result;
    result.is_acknowledged = true;
    return result;
}

result::delete_result collection::delete_one(const model::delete_one& model) {
    model::bulk_write bulk_op(false);
    bulk_op.append(model);

    if (model.write_concern())
        bulk_op.write_concern(*model.write_concern());

    result::bulk_write res(bulk_write(bulk_op));

    result::delete_result result;
    result.is_acknowledged = true;
    return result;
}

optional<bson::document::value> collection::find_one_and_replace(
    const model::find_one_and_replace& model) {
    scoped_bson_t criteria{model.criteria()};
    scoped_bson_t sort{model.sort()};
    scoped_bson_t replacement{model.replacement()};
    scoped_bson_t projection{model.projection()};
    scoped_bson_t reply;
    reply.flag_init();

    bson_error_t error;

    bool r = mongoc_collection_find_and_modify(
        _impl->collection_t, criteria.bson(), sort.bson(), replacement.bson(), projection.bson(),
        false, model.upsert().value_or(false), model.return_replacement().value_or(false),
        reply.bson(), &error);

    if (!r) {
        throw std::runtime_error("shits fucked");
    }

    bson::document::view result = reply.view();

    if (result["value"].type() == bson::type::k_null) {
        return optional<bson::document::value>{};
    } else {
        using namespace bson::builder::helpers;

        bson::builder::document b;

        b << concat{result["value"].get_document()};

        return b.extract();
    }
}

optional<bson::document::value> collection::find_one_and_update(
    const model::find_one_and_update& model) {
    scoped_bson_t criteria{model.criteria()};
    scoped_bson_t sort{model.sort()};
    scoped_bson_t update{model.update()};
    scoped_bson_t projection{model.projection()};
    scoped_bson_t reply;
    reply.flag_init();

    bson_error_t error;

    bool r = mongoc_collection_find_and_modify(
        _impl->collection_t, criteria.bson(), sort.bson(), update.bson(), projection.bson(), false,
        model.upsert().value_or(false), model.return_replacement().value_or(false), reply.bson(),
        &error);

    if (!r) {
        throw std::runtime_error("shits fucked");
    }

    bson::document::view result = reply.view();

    if (result["value"].type() == bson::type::k_null) {
        return optional<bson::document::value>{};
    } else {
        using namespace bson::builder::helpers;

        bson::builder::document b;

        b << concat{result["value"].get_document()};

        return b.extract();
    }
}

optional<bson::document::value> collection::find_one_and_delete(
    const model::find_one_and_delete& model) {
    scoped_bson_t criteria{model.criteria()};
    scoped_bson_t sort{model.sort()};
    scoped_bson_t projection{model.projection()};
    scoped_bson_t reply;
    reply.flag_init();

    bson_error_t error;

    bool r = mongoc_collection_find_and_modify(_impl->collection_t, criteria.bson(), sort.bson(),
                                               nullptr, projection.bson(), true, false, false,
                                               reply.bson(), &error);

    if (!r) {
        throw std::runtime_error("shits fucked");
    }

    bson::document::view result = reply.view();

    if (result["value"].type() == bson::type::k_null) {
        return optional<bson::document::value>{};
    } else {
        using namespace bson::builder::helpers;

        bson::builder::document b;

        b << concat{result["value"].get_document()};

        return b.extract();
    }
}

bson::document::value collection::explain(const model::explain& /*model*/) const {
    return bson::document::value((const std::uint8_t*)nullptr, 0);
}

std::int64_t collection::count(const model::count& model) const {
    scoped_bson_t criteria{model.criteria()};
    bson_error_t error;

    optional<priv::read_preference> read_prefs;
    const mongoc_read_prefs_t* rp_ptr;

    if (model.read_preference()) {
        read_prefs = priv::read_preference{*model.read_preference()};
        rp_ptr = read_prefs->get_read_preference();
    } else {
        rp_ptr = mongoc_collection_get_read_prefs(_impl->collection_t);
    }

    auto result = mongoc_collection_count(_impl->collection_t, static_cast<mongoc_query_flags_t>(0),
                                          criteria.bson(), model.skip().value_or(0),
                                          model.limit().value_or(0), rp_ptr, &error);

    /* TODO throw an exception if error
    if (result < 0)
    */

    return result;
}

void collection::drop() {
    bson_error_t error;

    if (mongoc_collection_drop(_impl->collection_t, &error)) {
        /* TODO handle errors */
    }
}

void collection::read_preference(class read_preference rp) {
    _impl->read_preference(std::move(rp));
}
const class read_preference& collection::read_preference() const {
    return _impl->read_preference();
}

void collection::write_concern(class write_concern wc) { _impl->write_concern(std::move(wc)); }

const class write_concern& collection::write_concern() const { return _impl->write_concern(); }

}  // namespace driver
}  // namespace mongo
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtFeedback module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtQml/QQmlExtensionPlugin>

#include "qdeclarativehapticseffect_p.h"
#include "qdeclarativefileeffect_p.h"
#include "qdeclarativethemeeffect_p.h"
#include "qdeclarativefeedbackeffect_p.h"
#include "qdeclarativefeedbackactuator_p.h"

QT_USE_NAMESPACE

static QObject *createDeclarativeThemeEfect(QDeclarativeEngine *engine, QJSEngine *jsengine)
{
    Q_UNUSED(engine)
    Q_UNUSED(jsengine)

    return new QDeclarativeThemeEffect;
}

class QDeclarativeFeedbackPlugin : public QDeclarativeExtensionPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "plugin.json")

public:
    virtual void registerTypes(const char *uri)
    {
        Q_ASSERT(QLatin1String(uri) == QLatin1String("QtFeedback"));

        int major = 5;
        int minor = 0;
        qmlRegisterUncreatableType<QDeclarativeFeedbackEffect>(uri, major, minor, "Feedback", "this is the feedback namespace");
        qmlRegisterUncreatableType<QDeclarativeFeedbackEffect>(uri, major, minor, "FeedbackEffect", "this is the base feedback effect class");
        qmlRegisterType<QDeclarativeFeedbackActuator>(uri, major, minor, "Actuator");
        qmlRegisterType<QDeclarativeFileEffect>(uri, major, minor, "FileEffect");
        qmlRegisterType<QDeclarativeHapticsEffect>(uri, major, minor, "HapticsEffect");
        qmlRegisterType<QDeclarativeThemeEffect>(uri, major, minor, "ThemeEffect");
        qmlRegisterModuleApi("QtFeedback.ThemeEffect", major, minor, createDeclarativeThemeEfect);
    }
};

#include "plugin.moc"
<commit_msg>Use templated qmlRegisterModuleApi()<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtFeedback module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtQml/QQmlExtensionPlugin>

#include "qdeclarativehapticseffect_p.h"
#include "qdeclarativefileeffect_p.h"
#include "qdeclarativethemeeffect_p.h"
#include "qdeclarativefeedbackeffect_p.h"
#include "qdeclarativefeedbackactuator_p.h"

QT_USE_NAMESPACE

static QObject *createDeclarativeThemeEfect(QDeclarativeEngine *engine, QJSEngine *jsengine)
{
    Q_UNUSED(engine)
    Q_UNUSED(jsengine)

    return new QDeclarativeThemeEffect;
}

class QDeclarativeFeedbackPlugin : public QDeclarativeExtensionPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "plugin.json")

public:
    virtual void registerTypes(const char *uri)
    {
        Q_ASSERT(QLatin1String(uri) == QLatin1String("QtFeedback"));

        int major = 5;
        int minor = 0;
        qmlRegisterUncreatableType<QDeclarativeFeedbackEffect>(uri, major, minor, "Feedback", "this is the feedback namespace");
        qmlRegisterUncreatableType<QDeclarativeFeedbackEffect>(uri, major, minor, "FeedbackEffect", "this is the base feedback effect class");
        qmlRegisterType<QDeclarativeFeedbackActuator>(uri, major, minor, "Actuator");
        qmlRegisterType<QDeclarativeFileEffect>(uri, major, minor, "FileEffect");
        qmlRegisterType<QDeclarativeHapticsEffect>(uri, major, minor, "HapticsEffect");
        qmlRegisterType<QDeclarativeThemeEffect>(uri, major, minor, "ThemeEffect");
        qmlRegisterModuleApi<QDeclarativeThemeEffect>("QtFeedback.ThemeEffect", major, minor, createDeclarativeThemeEfect);
    }
};

#include "plugin.moc"
<|endoftext|>


<commit_before>#ifndef BEAM_DUPLEX_UNORDERED_MIXED_HPP
#define BEAM_DUPLEX_UNORDERED_MIXED_HPP

#include <chrono>
#include <functional>
#include <memory>
#include <tuple>
#include <unordered_map>
#include <asio/strand.hpp>
#include <beam/duplex/common.hpp>
#include <beam/internet/endpoint.hpp>
#include <beam/message/buffer_pool.hpp>
#include <beam/message/capnproto.hpp>
#include <enet/enet.h>
#include <kj/array.h>

namespace beam {
namespace duplex {
namespace unordered_mixed {

namespace channel_id
{
    enum type
    {
	unreliable = 0,
	reliable = 1
    };
}

struct key;

template <class unreliable_msg_t, class reliable_msg_t>
class in_connection
{
public:
    typedef unreliable_msg_t unreliable_msg_type;
    typedef reliable_msg_t reliable_msg_type;
    struct event_handlers
    {
        std::function<void(const event_handlers& current)> on_timeout;
        std::function<void(const in_connection& connection)> on_connect;
        std::function<void(const in_connection& connection)> on_disconnect;
        std::function<void(const in_connection& connection, beam::message::capnproto::payload<unreliable_msg_t>&& payload)> on_receive_unreliable_msg;
        std::function<void(const in_connection& connection, beam::message::capnproto::payload<reliable_msg_t>&& payload)> on_receive_reliable_msg;
    };
    in_connection(const key&, asio::io_service::strand& strand, beam::message::buffer_pool& pool, ENetHost& host, ENetPeer& peer);
    beam::internet::endpoint_id get_source_id() const;
private:
    in_connection() = delete;
    asio::io_service::strand& strand_;
    beam::message::buffer_pool& pool_;
    ENetHost& host_;
    ENetPeer& peer_;
};

template <class unreliable_msg_t, class reliable_msg_t>
class out_connection
{
public:
    struct delivery_metadata
    {
	inline delivery_metadata(
		beam::message::buffer_pool* p,
		std::unordered_map<beam::message::buffer_pool::capacity_type, delivery_metadata>* m)
	    :
		pool(p),
		metadata_map(m)
	{ }
	beam::message::buffer_pool* pool;
	std::unordered_map<beam::message::buffer_pool::capacity_type, delivery_metadata>* metadata_map;
    };
    typedef std::unordered_map<beam::message::buffer_pool::capacity_type, delivery_metadata> metadata_map_type;
    typedef unreliable_msg_t unreliable_msg_type;
    typedef reliable_msg_t reliable_msg_type;
    out_connection(
	    const key&,
	    asio::io_service::strand& strand,
	    beam::message::buffer_pool& pool,
	    metadata_map_type& metadata,
	    ENetHost& host,
	    ENetPeer& peer);
    beam::internet::endpoint_id get_destination_id() const;
    void send_unreliable(beam::message::capnproto::payload<unreliable_msg_t>& message);
    void send_reliable(beam::message::capnproto::payload<reliable_msg_t>& message);
private:
    out_connection() = delete;
    static uint32_t get_packet_flags(channel_id::type channel);
    static void return_message(ENetPacket* packet);
    void send(beam::message::buffer& message, channel_id::type channel);
    asio::io_service::strand& strand_;
    beam::message::buffer_pool& pool_;
    metadata_map_type& metadata_;
    ENetHost& host_;
    ENetPeer& peer_;
};

struct perf_params
{
    perf_params(
	    std::size_t max,
	    std::size_t window,
	    std::chrono::milliseconds timeout = std::chrono::milliseconds(15000),
	    std::size_t download = 0,
	    std::size_t upload = 0);
    std::size_t max_connections;
    std::size_t window_size;
    std::chrono::milliseconds connection_timeout;
    std::size_t download_bytes_per_sec;
    std::size_t upload_bytes_per_sec;
};

enum class connection_result
{
    success,
    already_connected,
    failure
};

template <class in_connection_t, class out_connection_t>
class initiator
{
public:
    typedef in_connection_t in_connection_type;
    typedef out_connection_t out_connection_type;
    initiator(asio::io_service::strand& strand, perf_params&& params);
    inline bool is_connected() const { return peer_.get() != nullptr; }
    connection_result connect(std::vector<beam::internet::ipv4::address>&& receive_candidates, beam::duplex::common::port port);
    void disconnect();
    void async_send(std::function<void(out_connection_t&)> callback);
    void async_receive(const typename in_connection_t::event_handlers& handlers);
private:
    initiator() = delete;
    initiator(const initiator&) = delete;
    initiator& operator=(const initiator&) = delete;
    void exec_send(std::function<void(out_connection_t&)> callback);
    void exec_receive(const typename in_connection_t::event_handlers& handlers);
    asio::io_service::strand& strand_;
    perf_params params_;
    beam::message::buffer_pool pool_;
    typename out_connection_type::metadata_map_type metadata_;
    std::unique_ptr<ENetHost, std::function<void(ENetHost*)>> host_;
    std::unique_ptr<ENetPeer, std::function<void(ENetPeer*)>> peer_;
    std::unique_ptr<out_connection_t> out_;
    // TODO add a peer_map
};

enum class bind_result
{
    success,
    already_bound,
    failure
};

template <class in_connection_t, class out_connection_t>
class responder
{
public:
    typedef in_connection_t in_connection_type;
    typedef out_connection_t out_connection_type;
    responder(asio::io_service::strand& strand, perf_params&& params);
    inline bool is_bound() const { return host_.get() != nullptr; }
    inline bool has_connections() const { return !peer_map_.empty(); }
    bind_result bind(const beam::internet::endpoint_id& id);
    void unbind();
    void async_send(std::function<void(std::function<out_connection_t*(const beam::internet::endpoint_id&)>)> callback);
    void async_receive(const typename in_connection_t::event_handlers& handlers);
private:
    responder() = delete;
    responder(const responder&) = delete;
    responder& operator=(const responder&) = delete;
    void exec_unbind();
    void exec_send(std::function<void(std::function<out_connection_t*(const beam::internet::endpoint_id&)>)> callback);
    void exec_receive(const typename in_connection_t::event_handlers& handlers);
    asio::io_service::strand& strand_;
    perf_params params_;
    beam::message::buffer_pool pool_;
    typename out_connection_type::metadata_map_type metadata_;
    std::unique_ptr<ENetHost, std::function<void(ENetHost*)>> host_;
    std::unordered_map<beam::internet::endpoint_id, std::tuple<in_connection_t, out_connection_t>> peer_map_;
};

} // namespace unordered_mixed
} // namespace duplex
} // namespace beam

#endif
<commit_msg>responder can now return the bound endpoint_id<commit_after>#ifndef BEAM_DUPLEX_UNORDERED_MIXED_HPP
#define BEAM_DUPLEX_UNORDERED_MIXED_HPP

#include <chrono>
#include <functional>
#include <memory>
#include <tuple>
#include <unordered_map>
#include <asio/strand.hpp>
#include <beam/duplex/common.hpp>
#include <beam/internet/endpoint.hpp>
#include <beam/message/buffer_pool.hpp>
#include <beam/message/capnproto.hpp>
#include <enet/enet.h>
#include <kj/array.h>

namespace beam {
namespace duplex {
namespace unordered_mixed {

namespace channel_id
{
    enum type
    {
	unreliable = 0,
	reliable = 1
    };
}

struct key;

template <class unreliable_msg_t, class reliable_msg_t>
class in_connection
{
public:
    typedef unreliable_msg_t unreliable_msg_type;
    typedef reliable_msg_t reliable_msg_type;
    struct event_handlers
    {
        std::function<void(const event_handlers& current)> on_timeout;
        std::function<void(const in_connection& connection)> on_connect;
        std::function<void(const in_connection& connection)> on_disconnect;
        std::function<void(const in_connection& connection, beam::message::capnproto::payload<unreliable_msg_t>&& payload)> on_receive_unreliable_msg;
        std::function<void(const in_connection& connection, beam::message::capnproto::payload<reliable_msg_t>&& payload)> on_receive_reliable_msg;
    };
    in_connection(const key&, asio::io_service::strand& strand, beam::message::buffer_pool& pool, ENetHost& host, ENetPeer& peer);
    beam::internet::endpoint_id get_source_id() const;
private:
    in_connection() = delete;
    asio::io_service::strand& strand_;
    beam::message::buffer_pool& pool_;
    ENetHost& host_;
    ENetPeer& peer_;
};

template <class unreliable_msg_t, class reliable_msg_t>
class out_connection
{
public:
    struct delivery_metadata
    {
	inline delivery_metadata(
		beam::message::buffer_pool* p,
		std::unordered_map<beam::message::buffer_pool::capacity_type, delivery_metadata>* m)
	    :
		pool(p),
		metadata_map(m)
	{ }
	beam::message::buffer_pool* pool;
	std::unordered_map<beam::message::buffer_pool::capacity_type, delivery_metadata>* metadata_map;
    };
    typedef std::unordered_map<beam::message::buffer_pool::capacity_type, delivery_metadata> metadata_map_type;
    typedef unreliable_msg_t unreliable_msg_type;
    typedef reliable_msg_t reliable_msg_type;
    out_connection(
	    const key&,
	    asio::io_service::strand& strand,
	    beam::message::buffer_pool& pool,
	    metadata_map_type& metadata,
	    ENetHost& host,
	    ENetPeer& peer);
    beam::internet::endpoint_id get_destination_id() const;
    void send_unreliable(beam::message::capnproto::payload<unreliable_msg_t>& message);
    void send_reliable(beam::message::capnproto::payload<reliable_msg_t>& message);
private:
    out_connection() = delete;
    static uint32_t get_packet_flags(channel_id::type channel);
    static void return_message(ENetPacket* packet);
    void send(beam::message::buffer& message, channel_id::type channel);
    asio::io_service::strand& strand_;
    beam::message::buffer_pool& pool_;
    metadata_map_type& metadata_;
    ENetHost& host_;
    ENetPeer& peer_;
};

struct perf_params
{
    perf_params(
	    std::size_t max,
	    std::size_t window,
	    std::chrono::milliseconds timeout = std::chrono::milliseconds(15000),
	    std::size_t download = 0,
	    std::size_t upload = 0);
    std::size_t max_connections;
    std::size_t window_size;
    std::chrono::milliseconds connection_timeout;
    std::size_t download_bytes_per_sec;
    std::size_t upload_bytes_per_sec;
};

enum class connection_result
{
    success,
    already_connected,
    failure
};

template <class in_connection_t, class out_connection_t>
class initiator
{
public:
    typedef in_connection_t in_connection_type;
    typedef out_connection_t out_connection_type;
    initiator(asio::io_service::strand& strand, perf_params&& params);
    inline bool is_connected() const { return peer_.get() != nullptr; }
    connection_result connect(std::vector<beam::internet::ipv4::address>&& receive_candidates, beam::duplex::common::port port);
    void disconnect();
    void async_send(std::function<void(out_connection_t&)> callback);
    void async_receive(const typename in_connection_t::event_handlers& handlers);
private:
    initiator() = delete;
    initiator(const initiator&) = delete;
    initiator& operator=(const initiator&) = delete;
    void exec_send(std::function<void(out_connection_t&)> callback);
    void exec_receive(const typename in_connection_t::event_handlers& handlers);
    asio::io_service::strand& strand_;
    perf_params params_;
    beam::message::buffer_pool pool_;
    typename out_connection_type::metadata_map_type metadata_;
    std::unique_ptr<ENetHost, std::function<void(ENetHost*)>> host_;
    std::unique_ptr<ENetPeer, std::function<void(ENetPeer*)>> peer_;
    std::unique_ptr<out_connection_t> out_;
    // TODO add a peer_map
};

enum class bind_result
{
    success,
    already_bound,
    failure
};

template <class in_connection_t, class out_connection_t>
class responder
{
public:
    typedef in_connection_t in_connection_type;
    typedef out_connection_t out_connection_type;
    responder(asio::io_service::strand& strand, perf_params&& params);
    inline bool is_bound() const { return host_.get() != nullptr; }
    inline bool has_connections() const { return !peer_map_.empty(); }
    inline beam::internet::endpoint_id get_binding() const
    {
	return is_bound()
		? beam::internet::endpoint_id(host_->address.host, host_->address.port)
		: beam::internet::endpoint_id();
    }
    bind_result bind(const beam::internet::endpoint_id& id);
    void unbind();
    void async_send(std::function<void(std::function<out_connection_t*(const beam::internet::endpoint_id&)>)> callback);
    void async_receive(const typename in_connection_t::event_handlers& handlers);
private:
    responder() = delete;
    responder(const responder&) = delete;
    responder& operator=(const responder&) = delete;
    void exec_unbind();
    void exec_send(std::function<void(std::function<out_connection_t*(const beam::internet::endpoint_id&)>)> callback);
    void exec_receive(const typename in_connection_t::event_handlers& handlers);
    asio::io_service::strand& strand_;
    perf_params params_;
    beam::message::buffer_pool pool_;
    typename out_connection_type::metadata_map_type metadata_;
    std::unique_ptr<ENetHost, std::function<void(ENetHost*)>> host_;
    std::unordered_map<beam::internet::endpoint_id, std::tuple<in_connection_t, out_connection_t>> peer_map_;
};

} // namespace unordered_mixed
} // namespace duplex
} // namespace beam

#endif
<|endoftext|>


<commit_before>//===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization  ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a gold plugin for LLVM. It provides an LLVM implementation of the
// interface described in http://gcc.gnu.org/wiki/whopr/driver .
//
//===----------------------------------------------------------------------===//

#include "plugin-api.h"

#include "llvm-c/lto.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"

#include <cstdlib>
#include <cstring>
#include <list>
#include <vector>
#include <cerrno>

using namespace llvm;

namespace {
  ld_plugin_status discard_message(int level, const char *format, ...) {
    // Die loudly. Recent versions of Gold pass ld_plugin_message as the first
    // callback in the transfer vector. This should never be called.
    abort();
  }

  ld_plugin_add_symbols add_symbols = NULL;
  ld_plugin_get_symbols get_symbols = NULL;
  ld_plugin_add_input_file add_input_file = NULL;
  ld_plugin_message message = discard_message;

  int api_version = 0;
  int gold_version = 0;

  struct claimed_file {
    lto_module_t M;
    void *handle;
    void *buf;
    std::vector<ld_plugin_symbol> syms;
  };

  lto_codegen_model output_type = LTO_CODEGEN_PIC_MODEL_STATIC;
  std::list<claimed_file> Modules;
  std::vector<sys::Path> Cleanup;
}

ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
                                 int *claimed);
ld_plugin_status all_symbols_read_hook(void);
ld_plugin_status cleanup_hook(void);

extern "C" ld_plugin_status onload(ld_plugin_tv *tv);
ld_plugin_status onload(ld_plugin_tv *tv) {
  // We're given a pointer to the first transfer vector. We read through them
  // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values
  // contain pointers to functions that we need to call to register our own
  // hooks. The others are addresses of functions we can use to call into gold
  // for services.

  bool registeredClaimFile = false;
  bool registeredAllSymbolsRead = false;
  bool registeredCleanup = false;

  for (; tv->tv_tag != LDPT_NULL; ++tv) {
    switch (tv->tv_tag) {
      case LDPT_API_VERSION:
        api_version = tv->tv_u.tv_val;
        break;
      case LDPT_GOLD_VERSION:  // major * 100 + minor
        gold_version = tv->tv_u.tv_val;
        break;
      case LDPT_LINKER_OUTPUT:
        switch (tv->tv_u.tv_val) {
          case LDPO_REL:  // .o
          case LDPO_DYN:  // .so
            output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
            break;
          case LDPO_EXEC:  // .exe
            output_type = LTO_CODEGEN_PIC_MODEL_STATIC;
            break;
          default:
            (*message)(LDPL_ERROR, "Unknown output file type %d",
                       tv->tv_u.tv_val);
            return LDPS_ERR;
        }
        // TODO: add an option to disable PIC.
        //output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
        break;
      case LDPT_OPTION:
        (*message)(LDPL_WARNING, "Ignoring flag %s", tv->tv_u.tv_string);
        break;
      case LDPT_REGISTER_CLAIM_FILE_HOOK: {
        ld_plugin_register_claim_file callback;
        callback = tv->tv_u.tv_register_claim_file;

        if ((*callback)(claim_file_hook) != LDPS_OK)
          return LDPS_ERR;

        registeredClaimFile = true;
      } break;
      case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: {
        ld_plugin_register_all_symbols_read callback;
        callback = tv->tv_u.tv_register_all_symbols_read;

        if ((*callback)(all_symbols_read_hook) != LDPS_OK)
          return LDPS_ERR;

        registeredAllSymbolsRead = true;
      } break;
      case LDPT_REGISTER_CLEANUP_HOOK: {
        ld_plugin_register_cleanup callback;
        callback = tv->tv_u.tv_register_cleanup;

        if ((*callback)(cleanup_hook) != LDPS_OK)
          return LDPS_ERR;

        registeredCleanup = true;
      } break;
      case LDPT_ADD_SYMBOLS:
        add_symbols = tv->tv_u.tv_add_symbols;
        break;
      case LDPT_GET_SYMBOLS:
        get_symbols = tv->tv_u.tv_get_symbols;
        break;
      case LDPT_ADD_INPUT_FILE:
        add_input_file = tv->tv_u.tv_add_input_file;
        break;
      case LDPT_MESSAGE:
        message = tv->tv_u.tv_message;
        break;
      default:
        break;
    }
  }

  if (!registeredClaimFile || !registeredAllSymbolsRead || !registeredCleanup ||
      !add_symbols || !get_symbols || !add_input_file) {
    (*message)(LDPL_ERROR, "Not all hooks registered for LLVMgold.");
    return LDPS_ERR;
  }

  return LDPS_OK;
}

/// claim_file_hook - called by gold to see whether this file is one that
/// our plugin can handle. We'll try to open it and register all the symbols
/// with add_symbol if possible.
ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
                                 int *claimed) {
  void *buf = NULL;
  // If set, this means gold found IR in an ELF section. LLVM doesn't wrap its
  // IR in ELF, so we know it's not us. But it can also be an .a file containing
  // LLVM IR.
  if (file->offset) {
    if (lseek(file->fd, file->offset, SEEK_SET) == -1) {
      (*message)(LDPL_ERROR,
                 "Failed to seek to archive member of %s at offset %d: %s\n",
                 file->name,
                 file->offset, strerror(errno));
      return LDPS_ERR;
    }
    buf = malloc(file->filesize);
    if (!buf) {
      (*message)(LDPL_ERROR,
                 "Failed to allocate buffer for archive member of size: %d\n",
                 file->filesize);
      return LDPS_ERR;
    }
    if (read(file->fd, buf, file->filesize) != file->filesize) {
      (*message)(LDPL_ERROR,
                 "Failed to read archive member of %s at offset %d: %s\n",
                 file->name,
                 file->offset,
                 strerror(errno));
      free(buf);
      return LDPS_ERR;
    }
    if (!lto_module_is_object_file_in_memory(buf, file->filesize)) {
      free(buf);
      return LDPS_OK;
    }
  } else if (!lto_module_is_object_file(file->name))
    return LDPS_OK;

  *claimed = 1;
  Modules.resize(Modules.size() + 1);
  claimed_file &cf = Modules.back();

  cf.M = buf ?  lto_module_create_from_memory(buf, file->filesize) :
                lto_module_create(file->name);
  cf.buf = buf;
  if (!cf.M) {
    (*message)(LDPL_ERROR, "Failed to create LLVM module: %s",
               lto_get_error_message());
    return LDPS_ERR;
  }
  cf.handle = file->handle;
  unsigned sym_count = lto_module_get_num_symbols(cf.M);
  cf.syms.reserve(sym_count);

  for (unsigned i = 0; i != sym_count; ++i) {
    lto_symbol_attributes attrs = lto_module_get_symbol_attribute(cf.M, i);
    if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL)
      continue;

    cf.syms.push_back(ld_plugin_symbol());
    ld_plugin_symbol &sym = cf.syms.back();
    sym.name = const_cast<char *>(lto_module_get_symbol_name(cf.M, i));
    sym.version = NULL;

    int scope = attrs & LTO_SYMBOL_SCOPE_MASK;
    switch (scope) {
      case LTO_SYMBOL_SCOPE_HIDDEN:
        sym.visibility = LDPV_HIDDEN;
        break;
      case LTO_SYMBOL_SCOPE_PROTECTED:
        sym.visibility = LDPV_PROTECTED;
        break;
      case 0: // extern
      case LTO_SYMBOL_SCOPE_DEFAULT:
        sym.visibility = LDPV_DEFAULT;
        break;
      default:
        (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope);
        free(buf);
        return LDPS_ERR;
    }

    int definition = attrs & LTO_SYMBOL_DEFINITION_MASK;
    switch (definition) {
      case LTO_SYMBOL_DEFINITION_REGULAR:
        sym.def = LDPK_DEF;
        break;
      case LTO_SYMBOL_DEFINITION_UNDEFINED:
        sym.def = LDPK_UNDEF;
        break;
      case LTO_SYMBOL_DEFINITION_TENTATIVE:
        sym.def = LDPK_COMMON;
        break;
      case LTO_SYMBOL_DEFINITION_WEAK:
        sym.def = LDPK_WEAKDEF;
        break;
      default:
        (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition);
        free(buf);
        return LDPS_ERR;
    }

    // LLVM never emits COMDAT.
    sym.size = 0;
    sym.comdat_key = NULL;

    sym.resolution = LDPR_UNKNOWN;
  }

  cf.syms.reserve(cf.syms.size());

  if (!cf.syms.empty()) {
    if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) {
      (*message)(LDPL_ERROR, "Unable to add symbols!");
      free(buf);
      return LDPS_ERR;
    }
  }

  return LDPS_OK;
}

/// all_symbols_read_hook - gold informs us that all symbols have been read.
/// At this point, we use get_symbols to see if any of our definitions have
/// been overridden by a native object file. Then, perform optimization and
/// codegen.
ld_plugin_status all_symbols_read_hook(void) {
  lto_code_gen_t cg = lto_codegen_create();

  for (std::list<claimed_file>::iterator I = Modules.begin(),
       E = Modules.end(); I != E; ++I)
    lto_codegen_add_module(cg, I->M);

  // If we don't preserve any symbols, libLTO will assume that all symbols are
  // needed. Keep all symbols unless we're producing a final executable.
  if (output_type == LTO_CODEGEN_PIC_MODEL_STATIC) {
    bool anySymbolsPreserved = false;
    for (std::list<claimed_file>::iterator I = Modules.begin(),
         E = Modules.end(); I != E; ++I) {
      (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]);
      for (unsigned i = 0, e = I->syms.size(); i != e; i++) {
        (*message)(LDPL_WARNING, "def: %d visibility: %d resolution %d",
                   I->syms[i].def, I->syms[i].visibility, I->syms[i].resolution);
        if (I->syms[i].resolution == LDPR_PREVAILING_DEF) {
          lto_codegen_add_must_preserve_symbol(cg, I->syms[i].name);
          anySymbolsPreserved = true;
        }
      }
    }

    if (!anySymbolsPreserved) {
      // This entire file is unnecessary!
      lto_codegen_dispose(cg);
      return LDPS_OK;
    }
  }

  lto_codegen_set_pic_model(cg, output_type);
  lto_codegen_set_debug_model(cg, LTO_DEBUG_MODEL_DWARF);

  size_t bufsize = 0;
  const char *buffer = static_cast<const char *>(lto_codegen_compile(cg,
                                                                     &bufsize));

  std::string ErrMsg;

  sys::Path uniqueObjPath("/tmp/llvmgold.o");
  if (uniqueObjPath.createTemporaryFileOnDisk(true, &ErrMsg)) {
    (*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
    return LDPS_ERR;
  }
  raw_fd_ostream *objFile = new raw_fd_ostream(uniqueObjPath.c_str(), true,
                                               ErrMsg);
  if (!ErrMsg.empty()) {
    delete objFile;
    (*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
    return LDPS_ERR;
  }

  objFile->write(buffer, bufsize);
  objFile->close();

  lto_codegen_dispose(cg);
  for (std::list<claimed_file>::iterator I = Modules.begin(),
       E = Modules.end(); I != E; ++I) {
    free(I->buf);
  }

  if ((*add_input_file)(const_cast<char*>(uniqueObjPath.c_str())) != LDPS_OK) {
    (*message)(LDPL_ERROR, "Unable to add .o file to the link.");
    (*message)(LDPL_ERROR, "File left behind in: %s", uniqueObjPath.c_str());
    return LDPS_ERR;
  }

  Cleanup.push_back(uniqueObjPath);

  return LDPS_OK;
}

ld_plugin_status cleanup_hook(void) {
  std::string ErrMsg;

  for (int i = 0, e = Cleanup.size(); i != e; ++i)
    if (Cleanup[i].eraseFromDisk(false, &ErrMsg))
      (*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(),
                 ErrMsg.c_str());

  return LDPS_OK;
}
<commit_msg>Alphabetize includes. Update comment.<commit_after>//===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization  ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a gold plugin for LLVM. It provides an LLVM implementation of the
// interface described in http://gcc.gnu.org/wiki/whopr/driver .
//
//===----------------------------------------------------------------------===//

#include "plugin-api.h"

#include "llvm-c/lto.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"

#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <list>
#include <vector>

using namespace llvm;

namespace {
  ld_plugin_status discard_message(int level, const char *format, ...) {
    // Die loudly. Recent versions of Gold pass ld_plugin_message as the first
    // callback in the transfer vector. This should never be called.
    abort();
  }

  ld_plugin_add_symbols add_symbols = NULL;
  ld_plugin_get_symbols get_symbols = NULL;
  ld_plugin_add_input_file add_input_file = NULL;
  ld_plugin_message message = discard_message;

  int api_version = 0;
  int gold_version = 0;

  struct claimed_file {
    lto_module_t M;
    void *handle;
    void *buf;
    std::vector<ld_plugin_symbol> syms;
  };

  lto_codegen_model output_type = LTO_CODEGEN_PIC_MODEL_STATIC;
  std::list<claimed_file> Modules;
  std::vector<sys::Path> Cleanup;
}

ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
                                 int *claimed);
ld_plugin_status all_symbols_read_hook(void);
ld_plugin_status cleanup_hook(void);

extern "C" ld_plugin_status onload(ld_plugin_tv *tv);
ld_plugin_status onload(ld_plugin_tv *tv) {
  // We're given a pointer to the first transfer vector. We read through them
  // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values
  // contain pointers to functions that we need to call to register our own
  // hooks. The others are addresses of functions we can use to call into gold
  // for services.

  bool registeredClaimFile = false;
  bool registeredAllSymbolsRead = false;
  bool registeredCleanup = false;

  for (; tv->tv_tag != LDPT_NULL; ++tv) {
    switch (tv->tv_tag) {
      case LDPT_API_VERSION:
        api_version = tv->tv_u.tv_val;
        break;
      case LDPT_GOLD_VERSION:  // major * 100 + minor
        gold_version = tv->tv_u.tv_val;
        break;
      case LDPT_LINKER_OUTPUT:
        switch (tv->tv_u.tv_val) {
          case LDPO_REL:  // .o
          case LDPO_DYN:  // .so
            output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
            break;
          case LDPO_EXEC:  // .exe
            output_type = LTO_CODEGEN_PIC_MODEL_STATIC;
            break;
          default:
            (*message)(LDPL_ERROR, "Unknown output file type %d",
                       tv->tv_u.tv_val);
            return LDPS_ERR;
        }
        // TODO: add an option to disable PIC.
        //output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
        break;
      case LDPT_OPTION:
        (*message)(LDPL_WARNING, "Ignoring flag %s", tv->tv_u.tv_string);
        break;
      case LDPT_REGISTER_CLAIM_FILE_HOOK: {
        ld_plugin_register_claim_file callback;
        callback = tv->tv_u.tv_register_claim_file;

        if ((*callback)(claim_file_hook) != LDPS_OK)
          return LDPS_ERR;

        registeredClaimFile = true;
      } break;
      case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: {
        ld_plugin_register_all_symbols_read callback;
        callback = tv->tv_u.tv_register_all_symbols_read;

        if ((*callback)(all_symbols_read_hook) != LDPS_OK)
          return LDPS_ERR;

        registeredAllSymbolsRead = true;
      } break;
      case LDPT_REGISTER_CLEANUP_HOOK: {
        ld_plugin_register_cleanup callback;
        callback = tv->tv_u.tv_register_cleanup;

        if ((*callback)(cleanup_hook) != LDPS_OK)
          return LDPS_ERR;

        registeredCleanup = true;
      } break;
      case LDPT_ADD_SYMBOLS:
        add_symbols = tv->tv_u.tv_add_symbols;
        break;
      case LDPT_GET_SYMBOLS:
        get_symbols = tv->tv_u.tv_get_symbols;
        break;
      case LDPT_ADD_INPUT_FILE:
        add_input_file = tv->tv_u.tv_add_input_file;
        break;
      case LDPT_MESSAGE:
        message = tv->tv_u.tv_message;
        break;
      default:
        break;
    }
  }

  if (!registeredClaimFile || !registeredAllSymbolsRead || !registeredCleanup ||
      !add_symbols || !get_symbols || !add_input_file) {
    (*message)(LDPL_ERROR, "Not all hooks registered for LLVMgold.");
    return LDPS_ERR;
  }

  return LDPS_OK;
}

/// claim_file_hook - called by gold to see whether this file is one that
/// our plugin can handle. We'll try to open it and register all the symbols
/// with add_symbol if possible.
ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
                                 int *claimed) {
  void *buf = NULL;
  if (file->offset) {
    /* This is probably an archive member containing either an ELF object, or
     * LLVM IR. Find out which one it is */
    if (lseek(file->fd, file->offset, SEEK_SET) == -1) {
      (*message)(LDPL_ERROR,
                 "Failed to seek to archive member of %s at offset %d: %s\n",
                 file->name,
                 file->offset, strerror(errno));
      return LDPS_ERR;
    }
    buf = malloc(file->filesize);
    if (!buf) {
      (*message)(LDPL_ERROR,
                 "Failed to allocate buffer for archive member of size: %d\n",
                 file->filesize);
      return LDPS_ERR;
    }
    if (read(file->fd, buf, file->filesize) != file->filesize) {
      (*message)(LDPL_ERROR,
                 "Failed to read archive member of %s at offset %d: %s\n",
                 file->name,
                 file->offset,
                 strerror(errno));
      free(buf);
      return LDPS_ERR;
    }
    if (!lto_module_is_object_file_in_memory(buf, file->filesize)) {
      free(buf);
      return LDPS_OK;
    }
  } else if (!lto_module_is_object_file(file->name))
    return LDPS_OK;

  *claimed = 1;
  Modules.resize(Modules.size() + 1);
  claimed_file &cf = Modules.back();

  cf.M = buf ?  lto_module_create_from_memory(buf, file->filesize) :
                lto_module_create(file->name);
  cf.buf = buf;
  if (!cf.M) {
    (*message)(LDPL_ERROR, "Failed to create LLVM module: %s",
               lto_get_error_message());
    return LDPS_ERR;
  }
  cf.handle = file->handle;
  unsigned sym_count = lto_module_get_num_symbols(cf.M);
  cf.syms.reserve(sym_count);

  for (unsigned i = 0; i != sym_count; ++i) {
    lto_symbol_attributes attrs = lto_module_get_symbol_attribute(cf.M, i);
    if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL)
      continue;

    cf.syms.push_back(ld_plugin_symbol());
    ld_plugin_symbol &sym = cf.syms.back();
    sym.name = const_cast<char *>(lto_module_get_symbol_name(cf.M, i));
    sym.version = NULL;

    int scope = attrs & LTO_SYMBOL_SCOPE_MASK;
    switch (scope) {
      case LTO_SYMBOL_SCOPE_HIDDEN:
        sym.visibility = LDPV_HIDDEN;
        break;
      case LTO_SYMBOL_SCOPE_PROTECTED:
        sym.visibility = LDPV_PROTECTED;
        break;
      case 0: // extern
      case LTO_SYMBOL_SCOPE_DEFAULT:
        sym.visibility = LDPV_DEFAULT;
        break;
      default:
        (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope);
        free(buf);
        return LDPS_ERR;
    }

    int definition = attrs & LTO_SYMBOL_DEFINITION_MASK;
    switch (definition) {
      case LTO_SYMBOL_DEFINITION_REGULAR:
        sym.def = LDPK_DEF;
        break;
      case LTO_SYMBOL_DEFINITION_UNDEFINED:
        sym.def = LDPK_UNDEF;
        break;
      case LTO_SYMBOL_DEFINITION_TENTATIVE:
        sym.def = LDPK_COMMON;
        break;
      case LTO_SYMBOL_DEFINITION_WEAK:
        sym.def = LDPK_WEAKDEF;
        break;
      default:
        (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition);
        free(buf);
        return LDPS_ERR;
    }

    // LLVM never emits COMDAT.
    sym.size = 0;
    sym.comdat_key = NULL;

    sym.resolution = LDPR_UNKNOWN;
  }

  cf.syms.reserve(cf.syms.size());

  if (!cf.syms.empty()) {
    if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) {
      (*message)(LDPL_ERROR, "Unable to add symbols!");
      free(buf);
      return LDPS_ERR;
    }
  }

  return LDPS_OK;
}

/// all_symbols_read_hook - gold informs us that all symbols have been read.
/// At this point, we use get_symbols to see if any of our definitions have
/// been overridden by a native object file. Then, perform optimization and
/// codegen.
ld_plugin_status all_symbols_read_hook(void) {
  lto_code_gen_t cg = lto_codegen_create();

  for (std::list<claimed_file>::iterator I = Modules.begin(),
       E = Modules.end(); I != E; ++I)
    lto_codegen_add_module(cg, I->M);

  // If we don't preserve any symbols, libLTO will assume that all symbols are
  // needed. Keep all symbols unless we're producing a final executable.
  if (output_type == LTO_CODEGEN_PIC_MODEL_STATIC) {
    bool anySymbolsPreserved = false;
    for (std::list<claimed_file>::iterator I = Modules.begin(),
         E = Modules.end(); I != E; ++I) {
      (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]);
      for (unsigned i = 0, e = I->syms.size(); i != e; i++) {
        (*message)(LDPL_WARNING, "def: %d visibility: %d resolution %d",
                   I->syms[i].def, I->syms[i].visibility, I->syms[i].resolution);
        if (I->syms[i].resolution == LDPR_PREVAILING_DEF) {
          lto_codegen_add_must_preserve_symbol(cg, I->syms[i].name);
          anySymbolsPreserved = true;
        }
      }
    }

    if (!anySymbolsPreserved) {
      // This entire file is unnecessary!
      lto_codegen_dispose(cg);
      return LDPS_OK;
    }
  }

  lto_codegen_set_pic_model(cg, output_type);
  lto_codegen_set_debug_model(cg, LTO_DEBUG_MODEL_DWARF);

  size_t bufsize = 0;
  const char *buffer = static_cast<const char *>(lto_codegen_compile(cg,
                                                                     &bufsize));

  std::string ErrMsg;

  sys::Path uniqueObjPath("/tmp/llvmgold.o");
  if (uniqueObjPath.createTemporaryFileOnDisk(true, &ErrMsg)) {
    (*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
    return LDPS_ERR;
  }
  raw_fd_ostream *objFile = new raw_fd_ostream(uniqueObjPath.c_str(), true,
                                               ErrMsg);
  if (!ErrMsg.empty()) {
    delete objFile;
    (*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
    return LDPS_ERR;
  }

  objFile->write(buffer, bufsize);
  objFile->close();

  lto_codegen_dispose(cg);
  for (std::list<claimed_file>::iterator I = Modules.begin(),
       E = Modules.end(); I != E; ++I) {
    free(I->buf);
  }

  if ((*add_input_file)(const_cast<char*>(uniqueObjPath.c_str())) != LDPS_OK) {
    (*message)(LDPL_ERROR, "Unable to add .o file to the link.");
    (*message)(LDPL_ERROR, "File left behind in: %s", uniqueObjPath.c_str());
    return LDPS_ERR;
  }

  Cleanup.push_back(uniqueObjPath);

  return LDPS_OK;
}

ld_plugin_status cleanup_hook(void) {
  std::string ErrMsg;

  for (int i = 0, e = Cleanup.size(); i != e; ++i)
    if (Cleanup[i].eraseFromDisk(false, &ErrMsg))
      (*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(),
                 ErrMsg.c_str());

  return LDPS_OK;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: resmgr.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2008-02-25 15:58:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _TOOLS_RESMGR_HXX
#define _TOOLS_RESMGR_HXX

#ifndef INCLUDED_TOOLSDLLAPI_H
#include "tools/toolsdllapi.h"
#endif

#ifndef INCLUDED_I18NPOOL_LANG_H
#include <i18npool/lang.h>
#endif

#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif
#ifndef _REF_HXX
#include <tools/ref.hxx>
#endif

#ifndef _TOOLS_RESID_HXX
#include <tools/resid.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_
#include <com/sun/star/lang/Locale.hpp>
#endif

#define CREATEVERSIONRESMGR_NAME( Name )   #Name
#define CREATEVERSIONRESMGR( Name )        ResMgr::CreateResMgr( #Name )

#define LOCALE_MAX_FALLBACK 6

#include <vector>

class SvStream;
class InternalResMgr;

// -----------------
// - RSHEADER_TYPE -
// -----------------

// Definition der Struktur, aus denen die Resource aufgebaut ist
struct RSHEADER_TYPE
{
private:
    sal_uInt32              nId;        // Identifier der Resource
    RESOURCE_TYPE           nRT;        // Resource Typ
    sal_uInt32              nGlobOff;   // Globaler Offset
    sal_uInt32              nLocalOff;  // Lokaler Offset

public:
    inline sal_uInt32       GetId();       // Identifier der Resource
    inline RESOURCE_TYPE    GetRT();       // Resource Typ
    inline sal_uInt32       GetGlobOff();   // Globaler Offset
    inline sal_uInt32       GetLocalOff();  // Lokaler Offset
};

// ----------
// - ResMgr -
// ----------

typedef void (*ResHookProc)( UniString& rStr );

// ----------
// - ResMgr -
// ----------

// Initialisierung
#define RC_NOTYPE               0x00
// Globale Resource
#define RC_GLOBAL               0x01
#define RC_AUTORELEASE          0x02
#define RC_NOTFOUND             0x04
#define RC_FALLBACK_DOWN        0x08
#define RC_FALLBACK_UP          0x10

class Resource;
class ResMgr;
struct ImpRCStack
{
    // pResource and pClassRes equal NULL: resource was not loaded
    RSHEADER_TYPE * pResource;          // pointer to resource
    void          * pClassRes;          // pointer to class specified init data
    short           Flags;              // resource status
    void *          aResHandle;         // Resource-Identifier from InternalResMgr
    const Resource* pResObj;            // pointer to Resource object
    sal_uInt32      nId;                // ResId used for error message
    ResMgr*         pResMgr;            // ResMgr for Resource pResObj

    void            Clear();
    void            Init( ResMgr * pMgr, const Resource * pObj, sal_uInt32 nId );
};

class TOOLS_DLLPUBLIC ResMgr
{
private:
    InternalResMgr*            pImpRes;
    std::vector< ImpRCStack >  aStack;  // resource context stack
    int                        nCurStack;
    ResMgr*         pFallbackResMgr;    // fallback ResMgr in case the Resource
                                        // was not contained in this ResMgr
    ResMgr*         pOriginalResMgr;    // the res mgr that fell back to this
                                        // stack level

    TOOLS_DLLPRIVATE void         incStack();
    TOOLS_DLLPRIVATE void         decStack();

    TOOLS_DLLPRIVATE const ImpRCStack * StackTop( sal_uInt32 nOff = 0 ) const
    {
        return (((int)nOff >= nCurStack) ? NULL : &aStack[nCurStack-nOff]);
    }
    TOOLS_DLLPRIVATE void               Init( const rtl::OUString& rFileName );

    TOOLS_DLLPRIVATE ResMgr( InternalResMgr * pImp );

    #ifdef DBG_UTIL
    TOOLS_DLLPRIVATE static void RscError_Impl( const sal_Char* pMessage, ResMgr* pResMgr,
                               RESOURCE_TYPE nRT, sal_uInt32 nId,
                               std::vector< ImpRCStack >& rResStack, int nDepth );
    #endif

    // called from within GetResource() if a resource could not be found
    TOOLS_DLLPRIVATE ResMgr* CreateFallbackResMgr( const ResId& rId, const Resource* pResource );
    // creates a 1k sized buffer set to zero for unfound resources
    // used in case RC_NOTFOUND
    static void* pEmptyBuffer;
    TOOLS_DLLPRIVATE static void* getEmptyBuffer();

    // the next two methods are needed to prevent the string hook called
    // with the res mgr mutex locked
    // like GetString, but doesn't call the string hook
    TOOLS_DLLPRIVATE static sal_uInt32  GetStringWithoutHook( UniString& rStr, const BYTE* pStr );
    // like ReadString but doesn't call the string hook
    TOOLS_DLLPRIVATE UniString          ReadStringWithoutHook();

    static ResMgr* ImplCreateResMgr( InternalResMgr* pImpl ) { return new ResMgr( pImpl ); }

    //No copying
    ResMgr(const ResMgr&);
    ResMgr& operator=(const ResMgr&);
public:
    static void         DestroyAllResMgr();  // Wird gerufen, wenn App beendet wird

    ~ResMgr();

                        // Sprachabhaengige Ressource Library
    static const sal_Char*  GetLang( LanguageType& eLanguage, USHORT nPrio = 0 ); //depricated! see "tools/source/rc/resmgr.cxx"
    static ResMgr*      SearchCreateResMgr( const sal_Char* pPrefixName,
                                            com::sun::star::lang::Locale& rLocale );
     static ResMgr*     CreateResMgr( const sal_Char* pPrefixName,
                                      com::sun::star::lang::Locale aLocale = com::sun::star::lang::Locale( rtl::OUString(),
                                                                                rtl::OUString(),
                                                                                rtl::OUString()));

    // Testet ob Resource noch da ist
    void                TestStack( const Resource * );

    // ist Resource verfuegbar
    BOOL                IsAvailable( const ResId& rId,
                                     const Resource* = NULL) const;

    // Resource suchen und laden
    BOOL                GetResource( const ResId& rId, const Resource * = NULL );
    static void *       GetResourceSkipHeader( const ResId& rResId, ResMgr ** ppResMgr );
    // Kontext freigeben
    void                PopContext( const Resource* = NULL );

    // Resourcezeiger erhoehen
    void*               Increment( sal_uInt32 nSize );

    // Groesse ein Objektes in der Resource
    static sal_uInt32   GetObjSize( RSHEADER_TYPE* pHT )
                            { return( pHT->GetGlobOff() ); }

    // Liefert einen String aus der Resource
    static sal_uInt32   GetString( UniString& rStr, const BYTE* pStr );

    // Groesse eines Strings in der Resource
    static sal_uInt32   GetStringSize( sal_uInt32 nLen )
                            { nLen++; return (nLen + nLen%2); }
    static sal_uInt32   GetStringSize( const BYTE* pStr );

    // return a int64
    static sal_uInt64   GetUInt64( void* pDatum );
    // Gibt einen long zurueck
    static INT32        GetLong( void * pLong );
    // return a short
    static INT16        GetShort( void * pShort );

    // Gibt einen Zeiger auf die Resource zurueck
    void *              GetClass();

    RSHEADER_TYPE *     CreateBlock( const ResId & rId );

    // Gibt die verbleibende Groesse zurueck
    sal_uInt32          GetRemainSize();

    const rtl::OUString&GetFileName() const;

    INT16               ReadShort();
    INT32               ReadLong();
    UniString           ReadString();

     // generate auto help id for current resource stack
    ULONG               GetAutoHelpId();

    static void         SetReadStringHook( ResHookProc pProc );
    static ResHookProc  GetReadStringHook();
    static void         SetDefaultLocale( const com::sun::star::lang::Locale& rLocale );
};

inline sal_uInt32 RSHEADER_TYPE::GetId()
{
    return (sal_uInt32)ResMgr::GetLong( &nId );
}
inline RESOURCE_TYPE RSHEADER_TYPE::GetRT()
{
    return (RESOURCE_TYPE)ResMgr::GetLong( &nRT );
}
inline sal_uInt32 RSHEADER_TYPE::GetGlobOff()
{
    return (sal_uInt32)ResMgr::GetLong( &nGlobOff );
}
inline sal_uInt32 RSHEADER_TYPE::GetLocalOff()
{
    return (sal_uInt32)ResMgr::GetLong( &nLocalOff );
}

#endif // _SV_RESMGR_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.4.16); FILE MERGED 2008/04/01 16:01:28 thb 1.4.16.3: #i85898# Stripping all external header guards 2008/04/01 12:57:22 thb 1.4.16.2: #i85898# Stripping all external header guards 2008/03/28 15:41:12 rt 1.4.16.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: resmgr.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _TOOLS_RESMGR_HXX
#define _TOOLS_RESMGR_HXX

#include "tools/toolsdllapi.h"
#include <i18npool/lang.h>
#include <tools/string.hxx>
#include <tools/ref.hxx>
#include <tools/resid.hxx>
#include <com/sun/star/lang/Locale.hpp>

#define CREATEVERSIONRESMGR_NAME( Name )   #Name
#define CREATEVERSIONRESMGR( Name )        ResMgr::CreateResMgr( #Name )

#define LOCALE_MAX_FALLBACK 6

#include <vector>

class SvStream;
class InternalResMgr;

// -----------------
// - RSHEADER_TYPE -
// -----------------

// Definition der Struktur, aus denen die Resource aufgebaut ist
struct RSHEADER_TYPE
{
private:
    sal_uInt32              nId;        // Identifier der Resource
    RESOURCE_TYPE           nRT;        // Resource Typ
    sal_uInt32              nGlobOff;   // Globaler Offset
    sal_uInt32              nLocalOff;  // Lokaler Offset

public:
    inline sal_uInt32       GetId();       // Identifier der Resource
    inline RESOURCE_TYPE    GetRT();       // Resource Typ
    inline sal_uInt32       GetGlobOff();   // Globaler Offset
    inline sal_uInt32       GetLocalOff();  // Lokaler Offset
};

// ----------
// - ResMgr -
// ----------

typedef void (*ResHookProc)( UniString& rStr );

// ----------
// - ResMgr -
// ----------

// Initialisierung
#define RC_NOTYPE               0x00
// Globale Resource
#define RC_GLOBAL               0x01
#define RC_AUTORELEASE          0x02
#define RC_NOTFOUND             0x04
#define RC_FALLBACK_DOWN        0x08
#define RC_FALLBACK_UP          0x10

class Resource;
class ResMgr;
struct ImpRCStack
{
    // pResource and pClassRes equal NULL: resource was not loaded
    RSHEADER_TYPE * pResource;          // pointer to resource
    void          * pClassRes;          // pointer to class specified init data
    short           Flags;              // resource status
    void *          aResHandle;         // Resource-Identifier from InternalResMgr
    const Resource* pResObj;            // pointer to Resource object
    sal_uInt32      nId;                // ResId used for error message
    ResMgr*         pResMgr;            // ResMgr for Resource pResObj

    void            Clear();
    void            Init( ResMgr * pMgr, const Resource * pObj, sal_uInt32 nId );
};

class TOOLS_DLLPUBLIC ResMgr
{
private:
    InternalResMgr*            pImpRes;
    std::vector< ImpRCStack >  aStack;  // resource context stack
    int                        nCurStack;
    ResMgr*         pFallbackResMgr;    // fallback ResMgr in case the Resource
                                        // was not contained in this ResMgr
    ResMgr*         pOriginalResMgr;    // the res mgr that fell back to this
                                        // stack level

    TOOLS_DLLPRIVATE void         incStack();
    TOOLS_DLLPRIVATE void         decStack();

    TOOLS_DLLPRIVATE const ImpRCStack * StackTop( sal_uInt32 nOff = 0 ) const
    {
        return (((int)nOff >= nCurStack) ? NULL : &aStack[nCurStack-nOff]);
    }
    TOOLS_DLLPRIVATE void               Init( const rtl::OUString& rFileName );

    TOOLS_DLLPRIVATE ResMgr( InternalResMgr * pImp );

    #ifdef DBG_UTIL
    TOOLS_DLLPRIVATE static void RscError_Impl( const sal_Char* pMessage, ResMgr* pResMgr,
                               RESOURCE_TYPE nRT, sal_uInt32 nId,
                               std::vector< ImpRCStack >& rResStack, int nDepth );
    #endif

    // called from within GetResource() if a resource could not be found
    TOOLS_DLLPRIVATE ResMgr* CreateFallbackResMgr( const ResId& rId, const Resource* pResource );
    // creates a 1k sized buffer set to zero for unfound resources
    // used in case RC_NOTFOUND
    static void* pEmptyBuffer;
    TOOLS_DLLPRIVATE static void* getEmptyBuffer();

    // the next two methods are needed to prevent the string hook called
    // with the res mgr mutex locked
    // like GetString, but doesn't call the string hook
    TOOLS_DLLPRIVATE static sal_uInt32  GetStringWithoutHook( UniString& rStr, const BYTE* pStr );
    // like ReadString but doesn't call the string hook
    TOOLS_DLLPRIVATE UniString          ReadStringWithoutHook();

    static ResMgr* ImplCreateResMgr( InternalResMgr* pImpl ) { return new ResMgr( pImpl ); }

    //No copying
    ResMgr(const ResMgr&);
    ResMgr& operator=(const ResMgr&);
public:
    static void         DestroyAllResMgr();  // Wird gerufen, wenn App beendet wird

    ~ResMgr();

                        // Sprachabhaengige Ressource Library
    static const sal_Char*  GetLang( LanguageType& eLanguage, USHORT nPrio = 0 ); //depricated! see "tools/source/rc/resmgr.cxx"
    static ResMgr*      SearchCreateResMgr( const sal_Char* pPrefixName,
                                            com::sun::star::lang::Locale& rLocale );
     static ResMgr*     CreateResMgr( const sal_Char* pPrefixName,
                                      com::sun::star::lang::Locale aLocale = com::sun::star::lang::Locale( rtl::OUString(),
                                                                                rtl::OUString(),
                                                                                rtl::OUString()));

    // Testet ob Resource noch da ist
    void                TestStack( const Resource * );

    // ist Resource verfuegbar
    BOOL                IsAvailable( const ResId& rId,
                                     const Resource* = NULL) const;

    // Resource suchen und laden
    BOOL                GetResource( const ResId& rId, const Resource * = NULL );
    static void *       GetResourceSkipHeader( const ResId& rResId, ResMgr ** ppResMgr );
    // Kontext freigeben
    void                PopContext( const Resource* = NULL );

    // Resourcezeiger erhoehen
    void*               Increment( sal_uInt32 nSize );

    // Groesse ein Objektes in der Resource
    static sal_uInt32   GetObjSize( RSHEADER_TYPE* pHT )
                            { return( pHT->GetGlobOff() ); }

    // Liefert einen String aus der Resource
    static sal_uInt32   GetString( UniString& rStr, const BYTE* pStr );

    // Groesse eines Strings in der Resource
    static sal_uInt32   GetStringSize( sal_uInt32 nLen )
                            { nLen++; return (nLen + nLen%2); }
    static sal_uInt32   GetStringSize( const BYTE* pStr );

    // return a int64
    static sal_uInt64   GetUInt64( void* pDatum );
    // Gibt einen long zurueck
    static INT32        GetLong( void * pLong );
    // return a short
    static INT16        GetShort( void * pShort );

    // Gibt einen Zeiger auf die Resource zurueck
    void *              GetClass();

    RSHEADER_TYPE *     CreateBlock( const ResId & rId );

    // Gibt die verbleibende Groesse zurueck
    sal_uInt32          GetRemainSize();

    const rtl::OUString&GetFileName() const;

    INT16               ReadShort();
    INT32               ReadLong();
    UniString           ReadString();

     // generate auto help id for current resource stack
    ULONG               GetAutoHelpId();

    static void         SetReadStringHook( ResHookProc pProc );
    static ResHookProc  GetReadStringHook();
    static void         SetDefaultLocale( const com::sun::star::lang::Locale& rLocale );
};

inline sal_uInt32 RSHEADER_TYPE::GetId()
{
    return (sal_uInt32)ResMgr::GetLong( &nId );
}
inline RESOURCE_TYPE RSHEADER_TYPE::GetRT()
{
    return (RESOURCE_TYPE)ResMgr::GetLong( &nRT );
}
inline sal_uInt32 RSHEADER_TYPE::GetGlobOff()
{
    return (sal_uInt32)ResMgr::GetLong( &nGlobOff );
}
inline sal_uInt32 RSHEADER_TYPE::GetLocalOff()
{
    return (sal_uInt32)ResMgr::GetLong( &nLocalOff );
}

#endif // _SV_RESMGR_HXX
<|endoftext|>