<commit_before>// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/util/overload.h>
#include <vespa/vespalib/util/visit_ranges.h>
#include <vespa/vespalib/gtest/gtest.h>
#include <variant>
#include <string>

using namespace vespalib;

TEST(VisitRangeExample, set_intersection) {
    std::vector<int> first({1,3,7});
    std::vector<int> second({2,3,8});
    std::vector<int> result;
    vespalib::visit_ranges(overload{[](visit_ranges_either, int) {},
                                    [&result](visit_ranges_both, int x, int) { result.push_back(x); }},
                           first.begin(), first.end(), second.begin(), second.end());
    EXPECT_EQ(result, std::vector<int>({3}));
}

TEST(VisitRangeExample, set_subtraction) {
    std::vector<int> first({1,3,7});
    std::vector<int> second({2,3,8});
    std::vector<int> result;
    vespalib::visit_ranges(overload{[&result](visit_ranges_first, int a) { result.push_back(a); },
                                    [](visit_ranges_second, int) {},
                                    [](visit_ranges_both, int, int) {}},
                           first.begin(), first.end(), second.begin(), second.end());
    EXPECT_EQ(result, std::vector<int>({1,7}));
}

TEST(VisitRangesTest, empty_ranges_can_be_visited) {
    std::vector<int> a;
    std::vector<int> b;
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_either, int) {
                           c.push_back(42);
                       },
                       [&c](visit_ranges_both, int, int) {
                           c.push_back(42);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end());
    EXPECT_EQ(c, std::vector<int>({}));
}

TEST(VisitRangesTest, simple_merge_can_be_implemented) {
    std::vector<int> a({1,3,7});
    std::vector<int> b({2,3,8});
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_either, int x) {
                           c.push_back(x);
                       },
                       [&c](visit_ranges_both, int x, int y) {
                           c.push_back(x);
                           c.push_back(y);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end());
    EXPECT_EQ(c, std::vector<int>({1,2,3,3,7,8}));
}

TEST(VisitRangesTest, simple_union_can_be_implemented) {
    std::vector<int> a({1,3,7});
    std::vector<int> b({2,3,8});
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_either, int x) {
                           c.push_back(x);
                       },
                       [&c](visit_ranges_both, int x, int) {
                           c.push_back(x);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end());
    EXPECT_EQ(c, std::vector<int>({1,2,3,7,8}));
}

TEST(VisitRangesTest, asymmetric_merge_can_be_implemented) {
    std::vector<int> a({1,3,7});
    std::vector<int> b({2,3,8});
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_first, int x) {
                           c.push_back(x);
                       },
                       [&c](visit_ranges_second, int) {},
                       [&c](visit_ranges_both, int x, int y) {
                           c.push_back(x * y);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end());
    EXPECT_EQ(c, std::vector<int>({1,9,7}));
}

TEST(VisitRangesTest, comparator_can_be_specified) {
    std::vector<int> a({7,3,1});
    std::vector<int> b({8,3,2});
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_either, int x) {
                           c.push_back(x);
                       },
                       [&c](visit_ranges_both, int x, int y) {
                           c.push_back(x);
                           c.push_back(y);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end(), std::greater<>());
    EXPECT_EQ(c, std::vector<int>({8,7,3,3,2,1}));
}

GTEST_MAIN_RUN_ALL_TESTS()
<commit_msg>Remove unused lambda capture.<commit_after>// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/util/overload.h>
#include <vespa/vespalib/util/visit_ranges.h>
#include <vespa/vespalib/gtest/gtest.h>
#include <variant>
#include <string>

using namespace vespalib;

TEST(VisitRangeExample, set_intersection) {
    std::vector<int> first({1,3,7});
    std::vector<int> second({2,3,8});
    std::vector<int> result;
    vespalib::visit_ranges(overload{[](visit_ranges_either, int) {},
                                    [&result](visit_ranges_both, int x, int) { result.push_back(x); }},
                           first.begin(), first.end(), second.begin(), second.end());
    EXPECT_EQ(result, std::vector<int>({3}));
}

TEST(VisitRangeExample, set_subtraction) {
    std::vector<int> first({1,3,7});
    std::vector<int> second({2,3,8});
    std::vector<int> result;
    vespalib::visit_ranges(overload{[&result](visit_ranges_first, int a) { result.push_back(a); },
                                    [](visit_ranges_second, int) {},
                                    [](visit_ranges_both, int, int) {}},
                           first.begin(), first.end(), second.begin(), second.end());
    EXPECT_EQ(result, std::vector<int>({1,7}));
}

TEST(VisitRangesTest, empty_ranges_can_be_visited) {
    std::vector<int> a;
    std::vector<int> b;
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_either, int) {
                           c.push_back(42);
                       },
                       [&c](visit_ranges_both, int, int) {
                           c.push_back(42);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end());
    EXPECT_EQ(c, std::vector<int>({}));
}

TEST(VisitRangesTest, simple_merge_can_be_implemented) {
    std::vector<int> a({1,3,7});
    std::vector<int> b({2,3,8});
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_either, int x) {
                           c.push_back(x);
                       },
                       [&c](visit_ranges_both, int x, int y) {
                           c.push_back(x);
                           c.push_back(y);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end());
    EXPECT_EQ(c, std::vector<int>({1,2,3,3,7,8}));
}

TEST(VisitRangesTest, simple_union_can_be_implemented) {
    std::vector<int> a({1,3,7});
    std::vector<int> b({2,3,8});
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_either, int x) {
                           c.push_back(x);
                       },
                       [&c](visit_ranges_both, int x, int) {
                           c.push_back(x);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end());
    EXPECT_EQ(c, std::vector<int>({1,2,3,7,8}));
}

TEST(VisitRangesTest, asymmetric_merge_can_be_implemented) {
    std::vector<int> a({1,3,7});
    std::vector<int> b({2,3,8});
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_first, int x) {
                           c.push_back(x);
                       },
                       [](visit_ranges_second, int) {},
                       [&c](visit_ranges_both, int x, int y) {
                           c.push_back(x * y);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end());
    EXPECT_EQ(c, std::vector<int>({1,9,7}));
}

TEST(VisitRangesTest, comparator_can_be_specified) {
    std::vector<int> a({7,3,1});
    std::vector<int> b({8,3,2});
    std::vector<int> c;
    auto visitor = overload
                   {
                       [&c](visit_ranges_either, int x) {
                           c.push_back(x);
                       },
                       [&c](visit_ranges_both, int x, int y) {
                           c.push_back(x);
                           c.push_back(y);
                       }
                   };
    vespalib::visit_ranges(visitor, a.begin(), a.end(), b.begin(), b.end(), std::greater<>());
    EXPECT_EQ(c, std::vector<int>({8,7,3,3,2,1}));
}

GTEST_MAIN_RUN_ALL_TESTS()
<|endoftext|>


<commit_before><commit_msg>remove debug assert that is not 100% correct and can fail in some models<commit_after><|endoftext|>


<commit_before><commit_msg>updates to render correctly<commit_after><|endoftext|>


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

#include "config.h"
#include "modules/serviceworkers/InspectorServiceWorkerCacheAgent.h"

#include "core/InspectorBackendDispatcher.h"
#include "core/InspectorTypeBuilder.h"
#include "modules/serviceworkers/ServiceWorkerGlobalScope.h"
#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
#include "platform/JSONValues.h"
#include "platform/heap/Handle.h"
#include "public/platform/WebServiceWorkerCache.h"
#include "public/platform/WebServiceWorkerCacheError.h"
#include "public/platform/WebServiceWorkerCacheStorage.h"
#include "public/platform/WebServiceWorkerRequest.h"
#include "public/platform/WebServiceWorkerResponse.h"
#include "public/platform/WebString.h"
#include "public/platform/WebURL.h"
#include "public/platform/WebVector.h"
#include "wtf/Noncopyable.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
#include "wtf/text/StringBuilder.h"

#include <algorithm>

using blink::TypeBuilder::Array;
using blink::TypeBuilder::ServiceWorkerCache::DataEntry;

typedef blink::InspectorBackendDispatcher::ServiceWorkerCacheCommandHandler::DeleteCacheCallback DeleteCacheCallback;
typedef blink::InspectorBackendDispatcher::ServiceWorkerCacheCommandHandler::RequestCacheNamesCallback RequestCacheNamesCallback;
typedef blink::InspectorBackendDispatcher::ServiceWorkerCacheCommandHandler::RequestEntriesCallback RequestEntriesCallback;
typedef blink::InspectorBackendDispatcher::CallbackBase RequestCallback;

namespace blink {

namespace {

WebServiceWorkerCacheStorage* assertCacheStorage(ErrorString* errorString, ServiceWorkerGlobalScope* globalScope)
{
    ServiceWorkerGlobalScopeClient* client = ServiceWorkerGlobalScopeClient::from(globalScope);
    if (!client) {
        *errorString = "Could not find service worker global scope.";
        return nullptr;
    }
    WebServiceWorkerCacheStorage* cache = client->cacheStorage();
    if (!cache) {
        *errorString = "Cache not available on service worker global client.";
        return nullptr;
    }
    return cache;
}

CString serviceWorkerCacheErrorString(WebServiceWorkerCacheError* error)
{
    switch (*error) {
    case WebServiceWorkerCacheErrorNotImplemented:
        return CString("not implemented.");
        break;
    case WebServiceWorkerCacheErrorNotFound:
        return CString("not found.");
        break;
    case WebServiceWorkerCacheErrorExists:
        return CString("cache already exists.");
        break;
    default:
        return CString("unknown error.");
        break;
    }
}

class RequestCacheNames
    : public WebServiceWorkerCacheStorage::CacheStorageKeysCallbacks {
    WTF_MAKE_NONCOPYABLE(RequestCacheNames);

public:
    RequestCacheNames(PassRefPtr<RequestCacheNamesCallback> callback)
        : m_callback(callback)
    {
    }

    virtual ~RequestCacheNames() { }

    void onSuccess(WebVector<WebString>* caches)
    {
        RefPtr<TypeBuilder::Array<String>> array = TypeBuilder::Array<String>::create();
        for (size_t i = 0; i < caches->size(); i++) {
            array->addItem(String((*caches)[i]));
        }
        m_callback->sendSuccess(array);
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting cache names: %s", serviceWorkerCacheErrorString(error).data()));
    }

private:
    RefPtr<RequestCacheNamesCallback> m_callback;
};

struct DataRequestParams {
    String cacheName;
    int skipCount;
    int pageSize;
};

struct RequestResponse {
    RequestResponse() { }
    RequestResponse(const String& request, const String& response)
        : request(request)
        , response(response)
    {
    }
    String request;
    String response;
};

class ResponsesAccumulator : public RefCounted<ResponsesAccumulator> {
    WTF_MAKE_NONCOPYABLE(ResponsesAccumulator);

public:
    ResponsesAccumulator(int numResponses, const DataRequestParams& params, PassRefPtr<RequestEntriesCallback> callback)
        : m_params(params)
        , m_numResponsesLeft(numResponses)
        , m_responses(static_cast<size_t>(numResponses))
        , m_callback(callback)
    {
    }

    void addRequestResponsePair(const WebServiceWorkerRequest& request, const WebServiceWorkerResponse& response)
    {
        ASSERT(m_numResponsesLeft > 0);
        RequestResponse& requestResponse = m_responses.at(m_responses.size() - m_numResponsesLeft);
        requestResponse.request = request.url().string();
        requestResponse.response = response.statusText();

        if (--m_numResponsesLeft != 0)
            return;

        std::sort(m_responses.begin(), m_responses.end(),
            [](const RequestResponse& a, const RequestResponse& b)
            {
                return WTF::codePointCompareLessThan(a.request, b.request);
            });
        if (m_params.skipCount > 0)
            m_responses.remove(0, m_params.skipCount);
        bool hasMore = false;
        if (static_cast<size_t>(m_params.pageSize) < m_responses.size()) {
            m_responses.remove(m_params.pageSize, m_responses.size() - m_params.pageSize);
            hasMore = true;
        }
        RefPtr<TypeBuilder::Array<DataEntry>> array = TypeBuilder::Array<DataEntry>::create();
        for (const auto& requestResponse : m_responses) {
            RefPtr<DataEntry> entry = DataEntry::create()
                .setRequest(JSONString::create(requestResponse.request)->toJSONString())
                .setResponse(JSONString::create(requestResponse.response)->toJSONString());
            array->addItem(entry);
        }
        m_callback->sendSuccess(array, hasMore);
    }

private:
    DataRequestParams m_params;
    int m_numResponsesLeft;
    Vector<RequestResponse> m_responses;
    RefPtr<RequestEntriesCallback> m_callback;
};

class GetCacheResponsesForRequestData : public WebServiceWorkerCache::CacheMatchCallbacks {
    WTF_MAKE_NONCOPYABLE(GetCacheResponsesForRequestData);

public:
    GetCacheResponsesForRequestData(
        const DataRequestParams& params, const WebServiceWorkerRequest& request,
        PassRefPtr<ResponsesAccumulator> accum, PassRefPtr<RequestEntriesCallback> callback)
        : m_params(params)
        , m_request(request)
        , m_accumulator(accum)
        , m_callback(callback)
    {
    }
    virtual ~GetCacheResponsesForRequestData() { }

    void onSuccess(WebServiceWorkerResponse* response)
    {
        m_accumulator->addRequestResponsePair(m_request, *response);
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting responses for cache  %s: %s", m_params.cacheName.utf8().data(), serviceWorkerCacheErrorString(error).data()));
    }

private:
    DataRequestParams m_params;
    WebServiceWorkerRequest m_request;
    RefPtr<ResponsesAccumulator> m_accumulator;
    RefPtr<RequestEntriesCallback> m_callback;
};

class GetCacheKeysForRequestData : public WebServiceWorkerCache::CacheWithRequestsCallbacks {
    WTF_MAKE_NONCOPYABLE(GetCacheKeysForRequestData);

public:
    GetCacheKeysForRequestData(const DataRequestParams& params, PassOwnPtr<WebServiceWorkerCache> cache, PassRefPtr<RequestEntriesCallback> callback)
        : m_params(params)
        , m_cache(cache)
        , m_callback(callback)
    {
    }
    virtual ~GetCacheKeysForRequestData() { }

    void onSuccess(WebVector<WebServiceWorkerRequest>* requests)
    {
        RefPtr<ResponsesAccumulator> accumulator = adoptRef(new ResponsesAccumulator(requests->size(), m_params, m_callback));

        for (size_t i = 0; i < requests->size(); i++) {
            const auto& request = (*requests)[i];
            auto* cacheRequest = new GetCacheResponsesForRequestData(m_params, request, accumulator, m_callback);
            m_cache->dispatchMatch(cacheRequest, request, WebServiceWorkerCache::QueryParams());
        }
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting requests for cache %s: %s", m_params.cacheName.utf8().data(), serviceWorkerCacheErrorString(error).data()));
    }

private:
    DataRequestParams m_params;
    OwnPtr<WebServiceWorkerCache> m_cache;
    RefPtr<RequestEntriesCallback> m_callback;
};

class GetCacheForRequestData
    : public WebServiceWorkerCacheStorage::CacheStorageWithCacheCallbacks {
    WTF_MAKE_NONCOPYABLE(GetCacheForRequestData);

public:
    GetCacheForRequestData(const DataRequestParams& params, PassRefPtr<RequestEntriesCallback> callback)
        : m_params(params)
        , m_callback(callback)
    {
    }
    virtual ~GetCacheForRequestData() { }

    void onSuccess(WebServiceWorkerCache* cache)
    {
        auto* cacheRequest = new GetCacheKeysForRequestData(m_params, adoptPtr(cache), m_callback);
        cache->dispatchKeys(cacheRequest, nullptr, WebServiceWorkerCache::QueryParams());
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting cache %s: %s", m_params.cacheName.utf8().data(), serviceWorkerCacheErrorString(error).data()));
    }

private:
    DataRequestParams m_params;
    RefPtr<RequestEntriesCallback> m_callback;
};

class DeleteCache : public WebServiceWorkerCacheStorage::CacheStorageCallbacks {
    WTF_MAKE_NONCOPYABLE(DeleteCache);

public:
    DeleteCache(PassRefPtr<DeleteCacheCallback> callback)
        : m_callback(callback)
    {
    }
    virtual ~DeleteCache() { }

    void onSuccess()
    {
        m_callback->sendSuccess();
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting cache names: %s", serviceWorkerCacheErrorString(error).data()));
    }

private:
    RefPtr<DeleteCacheCallback> m_callback;
};

} // namespace

InspectorServiceWorkerCacheAgent::InspectorServiceWorkerCacheAgent(ServiceWorkerGlobalScope* scope)
    : InspectorBaseAgent<blink::InspectorServiceWorkerCacheAgent>("ServiceWorkerCache")
    , m_globalScope(scope)
{
}

InspectorServiceWorkerCacheAgent::~InspectorServiceWorkerCacheAgent() { }

void InspectorServiceWorkerCacheAgent::trace(Visitor* visitor)
{
    InspectorBaseAgent::trace(visitor);
}

void InspectorServiceWorkerCacheAgent::clearFrontend() { }
void InspectorServiceWorkerCacheAgent::restore() { }

void InspectorServiceWorkerCacheAgent::requestCacheNames(ErrorString* errorString, PassRefPtrWillBeRawPtr<RequestCacheNamesCallback> callback)
{
    WebServiceWorkerCacheStorage* cache = assertCacheStorage(errorString, m_globalScope);
    if (!cache) {
        callback->sendFailure(*errorString);
        return;
    }
    cache->dispatchKeys(new RequestCacheNames(callback));
}

void InspectorServiceWorkerCacheAgent::requestEntries(ErrorString* errorString, const String& cacheName, int skipCount, int pageSize, PassRefPtrWillBeRawPtr<RequestEntriesCallback> callback)
{
    WebServiceWorkerCacheStorage* cache = assertCacheStorage(errorString, m_globalScope);
    if (!cache) {
        callback->sendFailure(*errorString);
        return;
    }
    DataRequestParams params;
    params.cacheName = cacheName;
    params.pageSize = pageSize;
    params.skipCount = skipCount;
    cache->dispatchOpen(new GetCacheForRequestData(params, callback), WebString(cacheName));
}

void InspectorServiceWorkerCacheAgent::deleteCache(ErrorString* errorString, const String& cacheName, PassRefPtrWillBeRawPtr<DeleteCacheCallback> callback)
{
    WebServiceWorkerCacheStorage* cache = assertCacheStorage(errorString, m_globalScope);
    if (!cache) {
        callback->sendFailure(*errorString);
        return;
    }
    cache->dispatchDelete(new DeleteCache(callback), WebString(cacheName));
}

} // namespace blink
<commit_msg>Oilpan: fix build after r186900.<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "modules/serviceworkers/InspectorServiceWorkerCacheAgent.h"

#include "core/InspectorBackendDispatcher.h"
#include "core/InspectorTypeBuilder.h"
#include "modules/serviceworkers/ServiceWorkerGlobalScope.h"
#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
#include "platform/JSONValues.h"
#include "platform/heap/Handle.h"
#include "public/platform/WebServiceWorkerCache.h"
#include "public/platform/WebServiceWorkerCacheError.h"
#include "public/platform/WebServiceWorkerCacheStorage.h"
#include "public/platform/WebServiceWorkerRequest.h"
#include "public/platform/WebServiceWorkerResponse.h"
#include "public/platform/WebString.h"
#include "public/platform/WebURL.h"
#include "public/platform/WebVector.h"
#include "wtf/Noncopyable.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
#include "wtf/text/StringBuilder.h"

#include <algorithm>

using blink::TypeBuilder::Array;
using blink::TypeBuilder::ServiceWorkerCache::DataEntry;

typedef blink::InspectorBackendDispatcher::ServiceWorkerCacheCommandHandler::DeleteCacheCallback DeleteCacheCallback;
typedef blink::InspectorBackendDispatcher::ServiceWorkerCacheCommandHandler::RequestCacheNamesCallback RequestCacheNamesCallback;
typedef blink::InspectorBackendDispatcher::ServiceWorkerCacheCommandHandler::RequestEntriesCallback RequestEntriesCallback;
typedef blink::InspectorBackendDispatcher::CallbackBase RequestCallback;

namespace blink {

namespace {

WebServiceWorkerCacheStorage* assertCacheStorage(ErrorString* errorString, ServiceWorkerGlobalScope* globalScope)
{
    ServiceWorkerGlobalScopeClient* client = ServiceWorkerGlobalScopeClient::from(globalScope);
    if (!client) {
        *errorString = "Could not find service worker global scope.";
        return nullptr;
    }
    WebServiceWorkerCacheStorage* cache = client->cacheStorage();
    if (!cache) {
        *errorString = "Cache not available on service worker global client.";
        return nullptr;
    }
    return cache;
}

CString serviceWorkerCacheErrorString(WebServiceWorkerCacheError* error)
{
    switch (*error) {
    case WebServiceWorkerCacheErrorNotImplemented:
        return CString("not implemented.");
        break;
    case WebServiceWorkerCacheErrorNotFound:
        return CString("not found.");
        break;
    case WebServiceWorkerCacheErrorExists:
        return CString("cache already exists.");
        break;
    default:
        return CString("unknown error.");
        break;
    }
}

class RequestCacheNames
    : public WebServiceWorkerCacheStorage::CacheStorageKeysCallbacks {
    WTF_MAKE_NONCOPYABLE(RequestCacheNames);

public:
    RequestCacheNames(PassRefPtrWillBeRawPtr<RequestCacheNamesCallback> callback)
        : m_callback(callback)
    {
    }

    virtual ~RequestCacheNames() { }

    void onSuccess(WebVector<WebString>* caches)
    {
        RefPtr<TypeBuilder::Array<String>> array = TypeBuilder::Array<String>::create();
        for (size_t i = 0; i < caches->size(); i++) {
            array->addItem(String((*caches)[i]));
        }
        m_callback->sendSuccess(array);
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting cache names: %s", serviceWorkerCacheErrorString(error).data()));
    }

private:
    RefPtrWillBePersistent<RequestCacheNamesCallback> m_callback;
};

struct DataRequestParams {
    String cacheName;
    int skipCount;
    int pageSize;
};

struct RequestResponse {
    RequestResponse() { }
    RequestResponse(const String& request, const String& response)
        : request(request)
        , response(response)
    {
    }
    String request;
    String response;
};

class ResponsesAccumulator : public RefCounted<ResponsesAccumulator> {
    WTF_MAKE_NONCOPYABLE(ResponsesAccumulator);

public:
    ResponsesAccumulator(int numResponses, const DataRequestParams& params, PassRefPtrWillBeRawPtr<RequestEntriesCallback> callback)
        : m_params(params)
        , m_numResponsesLeft(numResponses)
        , m_responses(static_cast<size_t>(numResponses))
        , m_callback(callback)
    {
    }

    void addRequestResponsePair(const WebServiceWorkerRequest& request, const WebServiceWorkerResponse& response)
    {
        ASSERT(m_numResponsesLeft > 0);
        RequestResponse& requestResponse = m_responses.at(m_responses.size() - m_numResponsesLeft);
        requestResponse.request = request.url().string();
        requestResponse.response = response.statusText();

        if (--m_numResponsesLeft != 0)
            return;

        std::sort(m_responses.begin(), m_responses.end(),
            [](const RequestResponse& a, const RequestResponse& b)
            {
                return WTF::codePointCompareLessThan(a.request, b.request);
            });
        if (m_params.skipCount > 0)
            m_responses.remove(0, m_params.skipCount);
        bool hasMore = false;
        if (static_cast<size_t>(m_params.pageSize) < m_responses.size()) {
            m_responses.remove(m_params.pageSize, m_responses.size() - m_params.pageSize);
            hasMore = true;
        }
        RefPtr<TypeBuilder::Array<DataEntry>> array = TypeBuilder::Array<DataEntry>::create();
        for (const auto& requestResponse : m_responses) {
            RefPtr<DataEntry> entry = DataEntry::create()
                .setRequest(JSONString::create(requestResponse.request)->toJSONString())
                .setResponse(JSONString::create(requestResponse.response)->toJSONString());
            array->addItem(entry);
        }
        m_callback->sendSuccess(array, hasMore);
    }

private:
    DataRequestParams m_params;
    int m_numResponsesLeft;
    Vector<RequestResponse> m_responses;
    RefPtrWillBePersistent<RequestEntriesCallback> m_callback;
};

class GetCacheResponsesForRequestData : public WebServiceWorkerCache::CacheMatchCallbacks {
    WTF_MAKE_NONCOPYABLE(GetCacheResponsesForRequestData);

public:
    GetCacheResponsesForRequestData(
        const DataRequestParams& params, const WebServiceWorkerRequest& request,
        PassRefPtr<ResponsesAccumulator> accum, PassRefPtrWillBeRawPtr<RequestEntriesCallback> callback)
        : m_params(params)
        , m_request(request)
        , m_accumulator(accum)
        , m_callback(callback)
    {
    }
    virtual ~GetCacheResponsesForRequestData() { }

    void onSuccess(WebServiceWorkerResponse* response)
    {
        m_accumulator->addRequestResponsePair(m_request, *response);
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting responses for cache  %s: %s", m_params.cacheName.utf8().data(), serviceWorkerCacheErrorString(error).data()));
    }

private:
    DataRequestParams m_params;
    WebServiceWorkerRequest m_request;
    RefPtr<ResponsesAccumulator> m_accumulator;
    RefPtrWillBePersistent<RequestEntriesCallback> m_callback;
};

class GetCacheKeysForRequestData : public WebServiceWorkerCache::CacheWithRequestsCallbacks {
    WTF_MAKE_NONCOPYABLE(GetCacheKeysForRequestData);

public:
    GetCacheKeysForRequestData(const DataRequestParams& params, PassOwnPtr<WebServiceWorkerCache> cache, PassRefPtrWillBeRawPtr<RequestEntriesCallback> callback)
        : m_params(params)
        , m_cache(cache)
        , m_callback(callback)
    {
    }
    virtual ~GetCacheKeysForRequestData() { }

    void onSuccess(WebVector<WebServiceWorkerRequest>* requests)
    {
        RefPtr<ResponsesAccumulator> accumulator = adoptRef(new ResponsesAccumulator(requests->size(), m_params, m_callback));

        for (size_t i = 0; i < requests->size(); i++) {
            const auto& request = (*requests)[i];
            auto* cacheRequest = new GetCacheResponsesForRequestData(m_params, request, accumulator, m_callback);
            m_cache->dispatchMatch(cacheRequest, request, WebServiceWorkerCache::QueryParams());
        }
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting requests for cache %s: %s", m_params.cacheName.utf8().data(), serviceWorkerCacheErrorString(error).data()));
    }

private:
    DataRequestParams m_params;
    OwnPtr<WebServiceWorkerCache> m_cache;
    RefPtrWillBePersistent<RequestEntriesCallback> m_callback;
};

class GetCacheForRequestData
    : public WebServiceWorkerCacheStorage::CacheStorageWithCacheCallbacks {
    WTF_MAKE_NONCOPYABLE(GetCacheForRequestData);

public:
    GetCacheForRequestData(const DataRequestParams& params, PassRefPtrWillBeRawPtr<RequestEntriesCallback> callback)
        : m_params(params)
        , m_callback(callback)
    {
    }
    virtual ~GetCacheForRequestData() { }

    void onSuccess(WebServiceWorkerCache* cache)
    {
        auto* cacheRequest = new GetCacheKeysForRequestData(m_params, adoptPtr(cache), m_callback);
        cache->dispatchKeys(cacheRequest, nullptr, WebServiceWorkerCache::QueryParams());
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting cache %s: %s", m_params.cacheName.utf8().data(), serviceWorkerCacheErrorString(error).data()));
    }

private:
    DataRequestParams m_params;
    RefPtrWillBePersistent<RequestEntriesCallback> m_callback;
};

class DeleteCache : public WebServiceWorkerCacheStorage::CacheStorageCallbacks {
    WTF_MAKE_NONCOPYABLE(DeleteCache);

public:
    DeleteCache(PassRefPtrWillBeRawPtr<DeleteCacheCallback> callback)
        : m_callback(callback)
    {
    }
    virtual ~DeleteCache() { }

    void onSuccess()
    {
        m_callback->sendSuccess();
    }

    void onError(WebServiceWorkerCacheError* error)
    {
        m_callback->sendFailure(String::format("Error requesting cache names: %s", serviceWorkerCacheErrorString(error).data()));
    }

private:
    RefPtrWillBePersistent<DeleteCacheCallback> m_callback;
};

} // namespace

InspectorServiceWorkerCacheAgent::InspectorServiceWorkerCacheAgent(ServiceWorkerGlobalScope* scope)
    : InspectorBaseAgent<blink::InspectorServiceWorkerCacheAgent>("ServiceWorkerCache")
    , m_globalScope(scope)
{
}

InspectorServiceWorkerCacheAgent::~InspectorServiceWorkerCacheAgent() { }

void InspectorServiceWorkerCacheAgent::trace(Visitor* visitor)
{
    InspectorBaseAgent::trace(visitor);
}

void InspectorServiceWorkerCacheAgent::clearFrontend() { }
void InspectorServiceWorkerCacheAgent::restore() { }

void InspectorServiceWorkerCacheAgent::requestCacheNames(ErrorString* errorString, PassRefPtrWillBeRawPtr<RequestCacheNamesCallback> callback)
{
    WebServiceWorkerCacheStorage* cache = assertCacheStorage(errorString, m_globalScope);
    if (!cache) {
        callback->sendFailure(*errorString);
        return;
    }
    cache->dispatchKeys(new RequestCacheNames(callback));
}

void InspectorServiceWorkerCacheAgent::requestEntries(ErrorString* errorString, const String& cacheName, int skipCount, int pageSize, PassRefPtrWillBeRawPtr<RequestEntriesCallback> callback)
{
    WebServiceWorkerCacheStorage* cache = assertCacheStorage(errorString, m_globalScope);
    if (!cache) {
        callback->sendFailure(*errorString);
        return;
    }
    DataRequestParams params;
    params.cacheName = cacheName;
    params.pageSize = pageSize;
    params.skipCount = skipCount;
    cache->dispatchOpen(new GetCacheForRequestData(params, callback), WebString(cacheName));
}

void InspectorServiceWorkerCacheAgent::deleteCache(ErrorString* errorString, const String& cacheName, PassRefPtrWillBeRawPtr<DeleteCacheCallback> callback)
{
    WebServiceWorkerCacheStorage* cache = assertCacheStorage(errorString, m_globalScope);
    if (!cache) {
        callback->sendFailure(*errorString);
        return;
    }
    cache->dispatchDelete(new DeleteCache(callback), WebString(cacheName));
}

} // namespace blink
<|endoftext|>


<commit_before><commit_msg>X87: EmitCreateIteratorResult loads map from function's context<commit_after><|endoftext|>


<commit_before>/*
    Copyright (C) 2000 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csgeom/math3d.h"
#include "csutil/parser.h"
#include "csutil/scanstr.h"
#include "csutil/cscolor.h"
#include "ballldr.h"
#include "imesh/imeshobj.h"
#include "iengine/imeshobj.h"
#include "iengine/iengine.h"
#include "isys/isystem.h"
#include "imesh/imball.h"
#include "ivideo/igraph3d.h"
#include "qint.h"
#include "iutil/istrvec.h"
#include "csutil/util.h"
#include "iobject/iobject.h"
#include "iengine/imater.h"
#include "csengine/material.h"
#include "iengine/imovable.h"

CS_TOKEN_DEF_START
  CS_TOKEN_DEF (ADD)
  CS_TOKEN_DEF (ALPHA)
  CS_TOKEN_DEF (COPY)
  CS_TOKEN_DEF (KEYCOLOR)
  CS_TOKEN_DEF (MULTIPLY2)
  CS_TOKEN_DEF (MULTIPLY)
  CS_TOKEN_DEF (TRANSPARENT)

  CS_TOKEN_DEF (NUMRIM)
  CS_TOKEN_DEF (MATERIAL)
  CS_TOKEN_DEF (FACTORY)
  CS_TOKEN_DEF (MIXMODE)
  CS_TOKEN_DEF (RADIUS)
  CS_TOKEN_DEF (SHIFT)
CS_TOKEN_DEF_END

IMPLEMENT_IBASE (csBallFactoryLoader)
  IMPLEMENTS_INTERFACE (iLoaderPlugIn)
  IMPLEMENTS_INTERFACE (iPlugIn)
IMPLEMENT_IBASE_END

IMPLEMENT_IBASE (csBallFactorySaver)
  IMPLEMENTS_INTERFACE (iSaverPlugIn)
  IMPLEMENTS_INTERFACE (iPlugIn)
IMPLEMENT_IBASE_END

IMPLEMENT_IBASE (csBallLoader)
  IMPLEMENTS_INTERFACE (iLoaderPlugIn)
  IMPLEMENTS_INTERFACE (iPlugIn)
IMPLEMENT_IBASE_END

IMPLEMENT_IBASE (csBallSaver)
  IMPLEMENTS_INTERFACE (iSaverPlugIn)
  IMPLEMENTS_INTERFACE (iPlugIn)
IMPLEMENT_IBASE_END

IMPLEMENT_FACTORY (csBallFactoryLoader)
IMPLEMENT_FACTORY (csBallFactorySaver)
IMPLEMENT_FACTORY (csBallLoader)
IMPLEMENT_FACTORY (csBallSaver)

EXPORT_CLASS_TABLE (ballldr)
  EXPORT_CLASS (csBallFactoryLoader, "crystalspace.mesh.loader.factory.ball",
    "Crystal Space Ball Factory Loader")
  EXPORT_CLASS (csBallFactorySaver, "crystalspace.mesh.saver.factory.ball",
    "Crystal Space Ball Factory Saver")
  EXPORT_CLASS (csBallLoader, "crystalspace.mesh.loader.ball",
    "Crystal Space Ball Mesh Loader")
  EXPORT_CLASS (csBallSaver, "crystalspace.mesh.saver.ball",
    "Crystal Space Ball Mesh Saver")
EXPORT_CLASS_TABLE_END

csBallFactoryLoader::csBallFactoryLoader (iBase* pParent)
{
  CONSTRUCT_IBASE (pParent);
}

csBallFactoryLoader::~csBallFactoryLoader ()
{
}

bool csBallFactoryLoader::Initialize (iSystem* system)
{
  sys = system;
  return true;
}

iBase* csBallFactoryLoader::Parse (const char* /*string*/, iEngine* /*engine*/)
{
  iMeshObjectType* type = QUERY_PLUGIN_CLASS (sys, "crystalspace.mesh.object.ball", "MeshObj", iMeshObjectType);
  if (!type)
  {
    type = LOAD_PLUGIN (sys, "crystalspace.mesh.object.ball", "MeshObj", iMeshObjectType);
    printf ("Load TYPE plugin crystalspace.mesh.object.ball\n");
  }
  iMeshObjectFactory* fact = type->NewFactory ();
  type->DecRef ();
  return fact;
}

//---------------------------------------------------------------------------

csBallFactorySaver::csBallFactorySaver (iBase* pParent)
{
  CONSTRUCT_IBASE (pParent);
}

csBallFactorySaver::~csBallFactorySaver ()
{
}

bool csBallFactorySaver::Initialize (iSystem* system)
{
  sys = system;
  return true;
}

#define MAXLINE 100 /* max number of chars per line... */

void csBallFactorySaver::WriteDown (iBase* obj, iStrVector *str,
  iEngine* /*engine*/)
{
  iFactory *fact = QUERY_INTERFACE (this, iFactory);
  char buf[MAXLINE];
  char name[MAXLINE];
  csFindReplace(name, fact->QueryDescription (), "Saver", "Loader", MAXLINE);
  sprintf(buf, "MESHOBJ '%s' (\n", name);
  str->Push(strnew(buf));
  csFindReplace(name, fact->QueryClassID (), "saver", "loader", MAXLINE);
  sprintf(buf, "  PLUGIN ('%s')\n", name);
  str->Push(strnew(buf));
  str->Push(strnew("  PARAMS ()\n"));
  str->Push(strnew(")\n"));
  fact->DecRef();
}

//---------------------------------------------------------------------------

csBallLoader::csBallLoader (iBase* pParent)
{
  CONSTRUCT_IBASE (pParent);
}

csBallLoader::~csBallLoader ()
{
}

bool csBallLoader::Initialize (iSystem* system)
{
  sys = system;
  return true;
}

static UInt ParseMixmode (char* buf)
{
  CS_TOKEN_TABLE_START (modes)
    CS_TOKEN_TABLE (COPY)
    CS_TOKEN_TABLE (MULTIPLY2)
    CS_TOKEN_TABLE (MULTIPLY)
    CS_TOKEN_TABLE (ADD)
    CS_TOKEN_TABLE (ALPHA)
    CS_TOKEN_TABLE (TRANSPARENT)
    CS_TOKEN_TABLE (KEYCOLOR)
  CS_TOKEN_TABLE_END

  char* name;
  long cmd;
  char* params;

  UInt Mixmode = 0;

  while ((cmd = csGetObject (&buf, modes, &name, &params)) > 0)
  {
    if (!params)
    {
      printf ("Expected parameters instead of '%s'!\n", buf);
      return 0;
    }
    switch (cmd)
    {
      case CS_TOKEN_COPY: Mixmode |= CS_FX_COPY; break;
      case CS_TOKEN_MULTIPLY: Mixmode |= CS_FX_MULTIPLY; break;
      case CS_TOKEN_MULTIPLY2: Mixmode |= CS_FX_MULTIPLY2; break;
      case CS_TOKEN_ADD: Mixmode |= CS_FX_ADD; break;
      case CS_TOKEN_ALPHA:
	Mixmode &= ~CS_FX_MASK_ALPHA;
	float alpha;
	int ialpha;
        ScanStr (params, "%f", &alpha);
	ialpha = QInt (alpha * 255.99);
	Mixmode |= CS_FX_SETALPHA(ialpha);
	break;
      case CS_TOKEN_TRANSPARENT: Mixmode |= CS_FX_TRANSPARENT; break;
      case CS_TOKEN_KEYCOLOR: Mixmode |= CS_FX_KEYCOLOR; break;
    }
  }
  if (cmd == CS_PARSERR_TOKENNOTFOUND)
  {
    printf ("Token '%s' not found while parsing the modes!\n", csGetLastOffender ());
    return 0;
  }
  return Mixmode;
}

iBase* csBallLoader::Parse (const char* string, iEngine* engine)
{
  CS_TOKEN_TABLE_START (commands)
    CS_TOKEN_TABLE (MATERIAL)
    CS_TOKEN_TABLE (FACTORY)
    CS_TOKEN_TABLE (NUMRIM)
    CS_TOKEN_TABLE (RADIUS)
    CS_TOKEN_TABLE (SHIFT)
    CS_TOKEN_TABLE (MIXMODE)
  CS_TOKEN_TABLE_END

  char* name;
  long cmd;
  char* params;
  char str[255];

  iMeshObject* mesh = NULL;
  iBallState* ballstate = NULL;

  char* buf = (char*)string;
  while ((cmd = csGetObject (&buf, commands, &name, &params)) > 0)
  {
    if (!params)
    {
      // @@@ Error handling!
      if (ballstate) ballstate->DecRef ();
      return NULL;
    }
    switch (cmd)
    {
      case CS_TOKEN_RADIUS:
	{
	  float x, y, z;
	  ScanStr (params, "%f,%f,%f", &x, &y, &z);
	  ballstate->SetRadius (x, y, z);
	}
	break;
      case CS_TOKEN_SHIFT:
	{
	  float x, y, z;
	  ScanStr (params, "%f,%f,%f", &x, &y, &z);
	  ballstate->SetShift (x, y, z);
	}
	break;
      case CS_TOKEN_NUMRIM:
	{
	  int f;
	  ScanStr (params, "%d", &f);
	  ballstate->SetRimVertices (f);
	}
	break;
      case CS_TOKEN_FACTORY:
	{
          ScanStr (params, "%s", str);
	  iMeshFactoryWrapper* fact = engine->FindMeshFactory (str);
	  if (!fact)
	  {
	    // @@@ Error handling!
	    return NULL;
	  }
	  mesh = fact->GetMeshObjectFactory ()->NewInstance ();
          ballstate = QUERY_INTERFACE (mesh, iBallState);
	}
	break;
      case CS_TOKEN_MATERIAL:
	{
          ScanStr (params, "%s", str);
          iMaterialWrapper* mat = engine->FindMaterial (str);
	  if (!mat)
	  {
            // @@@ Error handling!
            mesh->DecRef ();
            return NULL;
	  }
	  ballstate->SetMaterialWrapper (mat);
	}
	break;
      case CS_TOKEN_MIXMODE:
        ballstate->SetMixMode (ParseMixmode (params));
	break;
    }
  }

  if (ballstate) ballstate->DecRef ();
  return mesh;
}

//---------------------------------------------------------------------------

csBallSaver::csBallSaver (iBase* pParent)
{
  CONSTRUCT_IBASE (pParent);
}

csBallSaver::~csBallSaver ()
{
}

bool csBallSaver::Initialize (iSystem* system)
{
  sys = system;
  return true;
}

static void WriteMixmode(iStrVector *str, UInt mixmode)
{
  str->Push(strnew("  MIXMODE ("));
  if(mixmode&CS_FX_COPY) str->Push(strnew(" COPY ()"));
  if(mixmode&CS_FX_ADD) str->Push(strnew(" ADD ()"));
  if(mixmode&CS_FX_MULTIPLY) str->Push(strnew(" MULTIPLY ()"));
  if(mixmode&CS_FX_MULTIPLY2) str->Push(strnew(" MULTIPLY2 ()"));
  if(mixmode&CS_FX_KEYCOLOR) str->Push(strnew(" KEYCOLOR ()"));
  if(mixmode&CS_FX_TRANSPARENT) str->Push(strnew(" TRANSPARENT ()"));
  if(mixmode&CS_FX_ALPHA) {
    char buf[MAXLINE];
    sprintf(buf, "ALPHA (%g)", float(mixmode&CS_FX_MASK_ALPHA)/255.);
    str->Push(strnew(buf));
  }
  str->Push(strnew(")"));
}

void csBallSaver::WriteDown (iBase* obj, iStrVector *str,
  iEngine* /*engine*/)
{
  iFactory *fact = QUERY_INTERFACE (this, iFactory);
  iMeshObject *mesh = QUERY_INTERFACE(obj, iMeshObject);
  if(!mesh)
  {
    printf("Error: non-mesh given to %s.\n",
      fact->QueryDescription () );
    fact->DecRef();
    return;
  }
  iBallState *state = QUERY_INTERFACE(obj, iBallState);
  if(!state)
  {
    printf("Error: invalid mesh given to %s.\n",
      fact->QueryDescription () );
    fact->DecRef();
    mesh->DecRef();
    return;
  }

  char buf[MAXLINE];
  char name[MAXLINE];
  csFindReplace(name, fact->QueryDescription (), "Saver", "Loader", MAXLINE);
  sprintf(buf, "FACTORY ('%s')\n", name);
  str->Push(strnew(buf));
  if(state->GetMixMode() != CS_FX_COPY)
  {
    WriteMixmode(str, state->GetMixMode());
  }

  // Mesh information
  float x=0, y=0, z=0;
  state->GetRadius(x, y, z);
  sprintf(buf, "RADIUS (%g, %g, %g)\n", x, y, z);
  str->Push(strnew(buf));
  sprintf(buf, "SHIFT (%g, %g, %g)\n", state->GetShift ().x,
    state->GetShift ().y, state->GetShift ().z);
  str->Push(strnew(buf));
  sprintf(buf, "NUMRIM (%d)\n", state->GetRimVertices());
  str->Push(strnew(buf));
  sprintf(buf, "MATERIAL (%s)\n", state->GetMaterialWrapper()->
    GetPrivateObject()->GetName());
  str->Push(strnew(buf));

  fact->DecRef();
  mesh->DecRef();
  state->DecRef();

}

//---------------------------------------------------------------------------
<commit_msg>Fixes ball factory saver. Now it does nothing, which is correct.<commit_after>/*
    Copyright (C) 2000 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csgeom/math3d.h"
#include "csutil/parser.h"
#include "csutil/scanstr.h"
#include "csutil/cscolor.h"
#include "ballldr.h"
#include "imesh/imeshobj.h"
#include "iengine/imeshobj.h"
#include "iengine/iengine.h"
#include "isys/isystem.h"
#include "imesh/imball.h"
#include "ivideo/igraph3d.h"
#include "qint.h"
#include "iutil/istrvec.h"
#include "csutil/util.h"
#include "iobject/iobject.h"
#include "iengine/imater.h"
#include "csengine/material.h"
#include "iengine/imovable.h"

CS_TOKEN_DEF_START
  CS_TOKEN_DEF (ADD)
  CS_TOKEN_DEF (ALPHA)
  CS_TOKEN_DEF (COPY)
  CS_TOKEN_DEF (KEYCOLOR)
  CS_TOKEN_DEF (MULTIPLY2)
  CS_TOKEN_DEF (MULTIPLY)
  CS_TOKEN_DEF (TRANSPARENT)

  CS_TOKEN_DEF (NUMRIM)
  CS_TOKEN_DEF (MATERIAL)
  CS_TOKEN_DEF (FACTORY)
  CS_TOKEN_DEF (MIXMODE)
  CS_TOKEN_DEF (RADIUS)
  CS_TOKEN_DEF (SHIFT)
CS_TOKEN_DEF_END

IMPLEMENT_IBASE (csBallFactoryLoader)
  IMPLEMENTS_INTERFACE (iLoaderPlugIn)
  IMPLEMENTS_INTERFACE (iPlugIn)
IMPLEMENT_IBASE_END

IMPLEMENT_IBASE (csBallFactorySaver)
  IMPLEMENTS_INTERFACE (iSaverPlugIn)
  IMPLEMENTS_INTERFACE (iPlugIn)
IMPLEMENT_IBASE_END

IMPLEMENT_IBASE (csBallLoader)
  IMPLEMENTS_INTERFACE (iLoaderPlugIn)
  IMPLEMENTS_INTERFACE (iPlugIn)
IMPLEMENT_IBASE_END

IMPLEMENT_IBASE (csBallSaver)
  IMPLEMENTS_INTERFACE (iSaverPlugIn)
  IMPLEMENTS_INTERFACE (iPlugIn)
IMPLEMENT_IBASE_END

IMPLEMENT_FACTORY (csBallFactoryLoader)
IMPLEMENT_FACTORY (csBallFactorySaver)
IMPLEMENT_FACTORY (csBallLoader)
IMPLEMENT_FACTORY (csBallSaver)

EXPORT_CLASS_TABLE (ballldr)
  EXPORT_CLASS (csBallFactoryLoader, "crystalspace.mesh.loader.factory.ball",
    "Crystal Space Ball Factory Loader")
  EXPORT_CLASS (csBallFactorySaver, "crystalspace.mesh.saver.factory.ball",
    "Crystal Space Ball Factory Saver")
  EXPORT_CLASS (csBallLoader, "crystalspace.mesh.loader.ball",
    "Crystal Space Ball Mesh Loader")
  EXPORT_CLASS (csBallSaver, "crystalspace.mesh.saver.ball",
    "Crystal Space Ball Mesh Saver")
EXPORT_CLASS_TABLE_END

csBallFactoryLoader::csBallFactoryLoader (iBase* pParent)
{
  CONSTRUCT_IBASE (pParent);
}

csBallFactoryLoader::~csBallFactoryLoader ()
{
}

bool csBallFactoryLoader::Initialize (iSystem* system)
{
  sys = system;
  return true;
}

iBase* csBallFactoryLoader::Parse (const char* /*string*/, iEngine* /*engine*/)
{
  iMeshObjectType* type = QUERY_PLUGIN_CLASS (sys, "crystalspace.mesh.object.ball", "MeshObj", iMeshObjectType);
  if (!type)
  {
    type = LOAD_PLUGIN (sys, "crystalspace.mesh.object.ball", "MeshObj", iMeshObjectType);
    printf ("Load TYPE plugin crystalspace.mesh.object.ball\n");
  }
  iMeshObjectFactory* fact = type->NewFactory ();
  type->DecRef ();
  return fact;
}

//---------------------------------------------------------------------------

csBallFactorySaver::csBallFactorySaver (iBase* pParent)
{
  CONSTRUCT_IBASE (pParent);
}

csBallFactorySaver::~csBallFactorySaver ()
{
}

bool csBallFactorySaver::Initialize (iSystem* system)
{
  sys = system;
  return true;
}

#define MAXLINE 100 /* max number of chars per line... */

void csBallFactorySaver::WriteDown (iBase* /*obj*/, iStrVector * /*str*/,
  iEngine* /*engine*/)
{
  // no params
}

//---------------------------------------------------------------------------

csBallLoader::csBallLoader (iBase* pParent)
{
  CONSTRUCT_IBASE (pParent);
}

csBallLoader::~csBallLoader ()
{
}

bool csBallLoader::Initialize (iSystem* system)
{
  sys = system;
  return true;
}

static UInt ParseMixmode (char* buf)
{
  CS_TOKEN_TABLE_START (modes)
    CS_TOKEN_TABLE (COPY)
    CS_TOKEN_TABLE (MULTIPLY2)
    CS_TOKEN_TABLE (MULTIPLY)
    CS_TOKEN_TABLE (ADD)
    CS_TOKEN_TABLE (ALPHA)
    CS_TOKEN_TABLE (TRANSPARENT)
    CS_TOKEN_TABLE (KEYCOLOR)
  CS_TOKEN_TABLE_END

  char* name;
  long cmd;
  char* params;

  UInt Mixmode = 0;

  while ((cmd = csGetObject (&buf, modes, &name, &params)) > 0)
  {
    if (!params)
    {
      printf ("Expected parameters instead of '%s'!\n", buf);
      return 0;
    }
    switch (cmd)
    {
      case CS_TOKEN_COPY: Mixmode |= CS_FX_COPY; break;
      case CS_TOKEN_MULTIPLY: Mixmode |= CS_FX_MULTIPLY; break;
      case CS_TOKEN_MULTIPLY2: Mixmode |= CS_FX_MULTIPLY2; break;
      case CS_TOKEN_ADD: Mixmode |= CS_FX_ADD; break;
      case CS_TOKEN_ALPHA:
	Mixmode &= ~CS_FX_MASK_ALPHA;
	float alpha;
	int ialpha;
        ScanStr (params, "%f", &alpha);
	ialpha = QInt (alpha * 255.99);
	Mixmode |= CS_FX_SETALPHA(ialpha);
	break;
      case CS_TOKEN_TRANSPARENT: Mixmode |= CS_FX_TRANSPARENT; break;
      case CS_TOKEN_KEYCOLOR: Mixmode |= CS_FX_KEYCOLOR; break;
    }
  }
  if (cmd == CS_PARSERR_TOKENNOTFOUND)
  {
    printf ("Token '%s' not found while parsing the modes!\n", csGetLastOffender ());
    return 0;
  }
  return Mixmode;
}

iBase* csBallLoader::Parse (const char* string, iEngine* engine)
{
  CS_TOKEN_TABLE_START (commands)
    CS_TOKEN_TABLE (MATERIAL)
    CS_TOKEN_TABLE (FACTORY)
    CS_TOKEN_TABLE (NUMRIM)
    CS_TOKEN_TABLE (RADIUS)
    CS_TOKEN_TABLE (SHIFT)
    CS_TOKEN_TABLE (MIXMODE)
  CS_TOKEN_TABLE_END

  char* name;
  long cmd;
  char* params;
  char str[255];

  iMeshObject* mesh = NULL;
  iBallState* ballstate = NULL;

  char* buf = (char*)string;
  while ((cmd = csGetObject (&buf, commands, &name, &params)) > 0)
  {
    if (!params)
    {
      // @@@ Error handling!
      if (ballstate) ballstate->DecRef ();
      return NULL;
    }
    switch (cmd)
    {
      case CS_TOKEN_RADIUS:
	{
	  float x, y, z;
	  ScanStr (params, "%f,%f,%f", &x, &y, &z);
	  ballstate->SetRadius (x, y, z);
	}
	break;
      case CS_TOKEN_SHIFT:
	{
	  float x, y, z;
	  ScanStr (params, "%f,%f,%f", &x, &y, &z);
	  ballstate->SetShift (x, y, z);
	}
	break;
      case CS_TOKEN_NUMRIM:
	{
	  int f;
	  ScanStr (params, "%d", &f);
	  ballstate->SetRimVertices (f);
	}
	break;
      case CS_TOKEN_FACTORY:
	{
          ScanStr (params, "%s", str);
	  iMeshFactoryWrapper* fact = engine->FindMeshFactory (str);
	  if (!fact)
	  {
	    // @@@ Error handling!
	    return NULL;
	  }
	  mesh = fact->GetMeshObjectFactory ()->NewInstance ();
          ballstate = QUERY_INTERFACE (mesh, iBallState);
	}
	break;
      case CS_TOKEN_MATERIAL:
	{
          ScanStr (params, "%s", str);
          iMaterialWrapper* mat = engine->FindMaterial (str);
	  if (!mat)
	  {
            // @@@ Error handling!
            mesh->DecRef ();
            return NULL;
	  }
	  ballstate->SetMaterialWrapper (mat);
	}
	break;
      case CS_TOKEN_MIXMODE:
        ballstate->SetMixMode (ParseMixmode (params));
	break;
    }
  }

  if (ballstate) ballstate->DecRef ();
  return mesh;
}

//---------------------------------------------------------------------------

csBallSaver::csBallSaver (iBase* pParent)
{
  CONSTRUCT_IBASE (pParent);
}

csBallSaver::~csBallSaver ()
{
}

bool csBallSaver::Initialize (iSystem* system)
{
  sys = system;
  return true;
}

static void WriteMixmode(iStrVector *str, UInt mixmode)
{
  str->Push(strnew("  MIXMODE ("));
  if(mixmode&CS_FX_COPY) str->Push(strnew(" COPY ()"));
  if(mixmode&CS_FX_ADD) str->Push(strnew(" ADD ()"));
  if(mixmode&CS_FX_MULTIPLY) str->Push(strnew(" MULTIPLY ()"));
  if(mixmode&CS_FX_MULTIPLY2) str->Push(strnew(" MULTIPLY2 ()"));
  if(mixmode&CS_FX_KEYCOLOR) str->Push(strnew(" KEYCOLOR ()"));
  if(mixmode&CS_FX_TRANSPARENT) str->Push(strnew(" TRANSPARENT ()"));
  if(mixmode&CS_FX_ALPHA) {
    char buf[MAXLINE];
    sprintf(buf, "ALPHA (%g)", float(mixmode&CS_FX_MASK_ALPHA)/255.);
    str->Push(strnew(buf));
  }
  str->Push(strnew(")"));
}

void csBallSaver::WriteDown (iBase* obj, iStrVector *str,
  iEngine* /*engine*/)
{
  iFactory *fact = QUERY_INTERFACE (this, iFactory);
  iMeshObject *mesh = QUERY_INTERFACE(obj, iMeshObject);
  if(!mesh)
  {
    printf("Error: non-mesh given to %s.\n",
      fact->QueryDescription () );
    fact->DecRef();
    return;
  }
  iBallState *state = QUERY_INTERFACE(obj, iBallState);
  if(!state)
  {
    printf("Error: invalid mesh given to %s.\n",
      fact->QueryDescription () );
    fact->DecRef();
    mesh->DecRef();
    return;
  }

  char buf[MAXLINE];
  char name[MAXLINE];
  csFindReplace(name, fact->QueryDescription (), "Saver", "Loader", MAXLINE);
  sprintf(buf, "FACTORY ('%s')\n", name);
  str->Push(strnew(buf));
  if(state->GetMixMode() != CS_FX_COPY)
  {
    WriteMixmode(str, state->GetMixMode());
  }

  // Mesh information
  float x=0, y=0, z=0;
  state->GetRadius(x, y, z);
  sprintf(buf, "RADIUS (%g, %g, %g)\n", x, y, z);
  str->Push(strnew(buf));
  sprintf(buf, "SHIFT (%g, %g, %g)\n", state->GetShift ().x,
    state->GetShift ().y, state->GetShift ().z);
  str->Push(strnew(buf));
  sprintf(buf, "NUMRIM (%d)\n", state->GetRimVertices());
  str->Push(strnew(buf));
  sprintf(buf, "MATERIAL (%s)\n", state->GetMaterialWrapper()->
    GetPrivateObject()->GetName());
  str->Push(strnew(buf));

  fact->DecRef();
  mesh->DecRef();
  state->DecRef();

}

//---------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include <silicium/config.hpp>
#include <silicium/bounded_int.hpp>
#include <silicium/variant.hpp>
#include <silicium/arithmetic/add.hpp>
#include <boost/test/unit_test.hpp>

#if SILICIUM_COMPILER_HAS_USING
namespace Si
{
	namespace m2
	{
		using std::size_t;
		using std::move;

		struct empty_t
		{
		};

		static BOOST_CONSTEXPR_OR_CONST empty_t empty;

		struct out_of_memory
		{
		};

		struct piece_of_memory
		{
			void *begin;

			piece_of_memory()
			    : begin(nullptr)
			{
			}

			explicit piece_of_memory(void *begin)
			    : begin(begin)
			{
			}
		};

		struct standard_allocator
		{
			variant<piece_of_memory, out_of_memory> allocate(size_t size)
			{
				void *memory = std::malloc(size);
				if (memory)
				{
					return piece_of_memory{memory};
				}
				return out_of_memory();
			}

			variant<piece_of_memory, out_of_memory> reallocate(piece_of_memory existing_allocation, size_t new_size)
			{
				void *new_allocation = std::realloc(existing_allocation.begin, new_size);
				if (new_allocation)
				{
					return piece_of_memory{new_allocation};
				}
				return out_of_memory();
			}

			void deallocate(piece_of_memory existing_allocation)
			{
				std::free(existing_allocation.begin);
			}
		};

		enum class resize_result
		{
			success,
			out_of_memory
		};

		template <class T, class Length, class Allocator>
		struct dynamic_storage : private Allocator
		{
			typedef T element_type;
			typedef Length length_type;

			dynamic_storage(empty_t, Allocator allocator = Allocator())
			    : Allocator(move(allocator))
			    , m_begin()
			    , m_length(length_type::template literal<0>())
			{
			}

			~dynamic_storage()
			{
				Allocator::deallocate(m_begin);
			}

			length_type length() const
			{
				return m_length;
			}

			resize_result resize(length_type new_length)
			{
				// TODO: handle overflow
				size_t const size_in_bytes = new_length.value() * sizeof(element_type);
				return visit<resize_result>(Allocator::reallocate(m_begin, size_in_bytes),
				                            [this, new_length](piece_of_memory const reallocated)
				                            {
					                            m_begin = reallocated;
					                            m_length = new_length;
					                            return resize_result::success;
					                        },
				                            [](out_of_memory)
				                            {
					                            return resize_result::out_of_memory;
					                        });
			}

			T &data() const
			{
				return *begin();
			}

			dynamic_storage(dynamic_storage &&other) BOOST_NOEXCEPT : Allocator(move(other)),
			                                                          m_begin(other.m_begin),
			                                                          m_length(other.m_length)
			{
				other.m_begin = piece_of_memory();
				other.m_length = length_type::template literal<0>();
			}

			dynamic_storage &operator=(dynamic_storage &&other) BOOST_NOEXCEPT
			{
				using std::swap;
				swap(static_cast<Allocator &>(*this), static_cast<Allocator &>(other));
				swap(m_begin, other.m_begin);
				swap(m_length, other.m_length);
				return *this;
			}

			SILICIUM_DISABLE_COPY(dynamic_storage)

		private:
			piece_of_memory m_begin;
			length_type m_length;

			T *begin() const
			{
				return static_cast<T *>(m_begin.begin);
			}
		};

		enum class emplace_back_result
		{
			success,
			out_of_memory,
			full
		};

		template <class DynamicStorage>
		struct basic_vector
		{
			typedef typename DynamicStorage::element_type element_type;
			typedef typename DynamicStorage::length_type length_type;

			basic_vector(empty_t, DynamicStorage storage)
			    : m_storage(move(storage))
			    , m_used(length_type::template literal<0>())
			{
			}

			length_type capacity() const
			{
				return m_storage.length();
			}

			length_type length() const
			{
				return m_used;
			}

			template <class... Args>
			emplace_back_result emplace_back(Args &&... args)
			{
				overflow_or<typename length_type::value_type> const maybe_new_size =
				    checked_add<typename length_type::value_type>(capacity().value(), 1);
				if (maybe_new_size.is_overflow())
				{
					return emplace_back_result::full;
				}
				length_type const new_size = *length_type::create(*maybe_new_size.value());
				if (m_storage.length() < new_size)
				{
					// TODO: exponential growth
					switch (m_storage.resize(new_size))
					{
					case resize_result::success:
						break;

					case resize_result::out_of_memory:
						return emplace_back_result::out_of_memory;
					}
				}
				new (&m_storage.data()) element_type{std::forward<Args>(args)...};
				m_used = new_size;
				return emplace_back_result::success;
			}

			basic_vector(basic_vector &&other) BOOST_NOEXCEPT : m_storage(move(other.m_storage)), m_used(other.m_used)
			{
				// TODO: solve more generically
				other.m_used = length_type::template literal<0>();
			}

			basic_vector &operator=(basic_vector &&other) BOOST_NOEXCEPT
			{
				m_storage = move(other.m_storage);
				m_used = other.m_used;
				// TODO: solve more generically
				other.m_used = length_type::template literal<0>();
				return *this;
			}

			SILICIUM_DISABLE_COPY(basic_vector)

		private:
			DynamicStorage m_storage;
			length_type m_used;
		};

		template <class T, class Length>
		using vector = basic_vector<dynamic_storage<T, Length, standard_allocator>>;
	}
}

BOOST_AUTO_TEST_CASE(move2_vector_emplace_back)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(0u, v.capacity().value());
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	BOOST_REQUIRE_EQUAL(1u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, v.capacity().value());
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(13u));
	BOOST_REQUIRE_EQUAL(2u, v.length().value());
	BOOST_REQUIRE_EQUAL(2u, v.capacity().value());
}

BOOST_AUTO_TEST_CASE(move2_vector_move_construct)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> w{std::move(v)};
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, w.length().value());
}

BOOST_AUTO_TEST_CASE(move2_vector_move_assign)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> w{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	w = std::move(v);
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, w.length().value());
}
#endif
<commit_msg>implement ~basic_vector<commit_after>#include <silicium/config.hpp>
#include <silicium/bounded_int.hpp>
#include <silicium/variant.hpp>
#include <silicium/arithmetic/add.hpp>
#include <boost/test/unit_test.hpp>

#if SILICIUM_COMPILER_HAS_USING
namespace Si
{
	namespace m2
	{
		using std::size_t;
		using std::move;

		struct empty_t
		{
		};

		static BOOST_CONSTEXPR_OR_CONST empty_t empty;

		struct out_of_memory
		{
		};

		struct piece_of_memory
		{
			void *begin;

			piece_of_memory()
			    : begin(nullptr)
			{
			}

			explicit piece_of_memory(void *begin)
			    : begin(begin)
			{
			}
		};

		struct standard_allocator
		{
			variant<piece_of_memory, out_of_memory> allocate(size_t size)
			{
				void *memory = std::malloc(size);
				if (memory)
				{
					return piece_of_memory{memory};
				}
				return out_of_memory();
			}

			variant<piece_of_memory, out_of_memory> reallocate(piece_of_memory existing_allocation, size_t new_size)
			{
				void *new_allocation = std::realloc(existing_allocation.begin, new_size);
				if (new_allocation)
				{
					return piece_of_memory{new_allocation};
				}
				return out_of_memory();
			}

			void deallocate(piece_of_memory existing_allocation)
			{
				std::free(existing_allocation.begin);
			}
		};

		enum class resize_result
		{
			success,
			out_of_memory
		};

		template <class T, class Length, class Allocator>
		struct dynamic_storage : private Allocator
		{
			typedef T element_type;
			typedef Length length_type;

			dynamic_storage(empty_t, Allocator allocator = Allocator())
			    : Allocator(move(allocator))
			    , m_begin()
			    , m_length(length_type::template literal<0>())
			{
			}

			~dynamic_storage()
			{
				Allocator::deallocate(m_begin);
			}

			length_type length() const
			{
				return m_length;
			}

			resize_result resize(length_type new_length)
			{
				// TODO: handle overflow
				size_t const size_in_bytes = new_length.value() * sizeof(element_type);
				return visit<resize_result>(Allocator::reallocate(m_begin, size_in_bytes),
				                            [this, new_length](piece_of_memory const reallocated)
				                            {
					                            m_begin = reallocated;
					                            m_length = new_length;
					                            return resize_result::success;
					                        },
				                            [](out_of_memory)
				                            {
					                            return resize_result::out_of_memory;
					                        });
			}

			T &data() const
			{
				return *begin();
			}

			dynamic_storage(dynamic_storage &&other) BOOST_NOEXCEPT : Allocator(move(other)),
			                                                          m_begin(other.m_begin),
			                                                          m_length(other.m_length)
			{
				other.m_begin = piece_of_memory();
				other.m_length = length_type::template literal<0>();
			}

			dynamic_storage &operator=(dynamic_storage &&other) BOOST_NOEXCEPT
			{
				using std::swap;
				swap(static_cast<Allocator &>(*this), static_cast<Allocator &>(other));
				swap(m_begin, other.m_begin);
				swap(m_length, other.m_length);
				return *this;
			}

			SILICIUM_DISABLE_COPY(dynamic_storage)

		private:
			piece_of_memory m_begin;
			length_type m_length;

			T *begin() const
			{
				return static_cast<T *>(m_begin.begin);
			}
		};

		enum class emplace_back_result
		{
			success,
			out_of_memory,
			full
		};

		template <class DynamicStorage>
		struct basic_vector
		{
			typedef typename DynamicStorage::element_type element_type;
			typedef typename DynamicStorage::length_type length_type;

			basic_vector(empty_t, DynamicStorage storage)
			    : m_storage(move(storage))
			    , m_used(length_type::template literal<0>())
			{
			}

			~basic_vector() BOOST_NOEXCEPT
			{
				for (typename length_type::value_type i = 0; i < length().value(); ++i)
				{
					(&m_storage.data())[length().value() - 1 - i].~element_type();
				}
			}

			length_type capacity() const BOOST_NOEXCEPT
			{
				return m_storage.length();
			}

			length_type length() const BOOST_NOEXCEPT
			{
				return m_used;
			}

			template <class... Args>
			emplace_back_result emplace_back(Args &&... args)
			{
				overflow_or<typename length_type::value_type> const maybe_new_size =
				    checked_add<typename length_type::value_type>(capacity().value(), 1);
				if (maybe_new_size.is_overflow())
				{
					return emplace_back_result::full;
				}
				length_type const new_size = *length_type::create(*maybe_new_size.value());
				if (m_storage.length() < new_size)
				{
					// TODO: exponential growth
					switch (m_storage.resize(new_size))
					{
					case resize_result::success:
						break;

					case resize_result::out_of_memory:
						return emplace_back_result::out_of_memory;
					}
				}
				new (&m_storage.data()) element_type{std::forward<Args>(args)...};
				m_used = new_size;
				return emplace_back_result::success;
			}

			basic_vector(basic_vector &&other) BOOST_NOEXCEPT : m_storage(move(other.m_storage)), m_used(other.m_used)
			{
				// TODO: solve more generically
				other.m_used = length_type::template literal<0>();
			}

			basic_vector &operator=(basic_vector &&other) BOOST_NOEXCEPT
			{
				m_storage = move(other.m_storage);
				m_used = other.m_used;
				// TODO: solve more generically
				other.m_used = length_type::template literal<0>();
				return *this;
			}

			SILICIUM_DISABLE_COPY(basic_vector)

		private:
			DynamicStorage m_storage;
			length_type m_used;
		};

		template <class T, class Length>
		using vector = basic_vector<dynamic_storage<T, Length, standard_allocator>>;
	}
}

BOOST_AUTO_TEST_CASE(move2_vector_emplace_back)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(0u, v.capacity().value());
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	BOOST_REQUIRE_EQUAL(1u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, v.capacity().value());
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(13u));
	BOOST_REQUIRE_EQUAL(2u, v.length().value());
	BOOST_REQUIRE_EQUAL(2u, v.capacity().value());
}

BOOST_AUTO_TEST_CASE(move2_vector_move_construct)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> w{std::move(v)};
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, w.length().value());
}

BOOST_AUTO_TEST_CASE(move2_vector_move_assign)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> w{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	w = std::move(v);
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, w.length().value());
}
#endif
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"

template<typename MatrixType> void matrixRedux(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename MatrixType::RealScalar RealScalar;

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols);

  // The entries of m1 are uniformly distributed in [0,1], so m1.prod() is very small. This may lead to test
  // failures if we underflow into denormals. Thus, we scale so that entires are close to 1.
  MatrixType m1_for_prod = MatrixType::Ones(rows, cols) + RealScalar(0.2) * m1;

  VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows, cols).sum(), Scalar(1));
  VERIFY_IS_APPROX(MatrixType::Ones(rows, cols).sum(), Scalar(float(rows*cols))); // the float() here to shut up excessive MSVC warning about int->complex conversion being lossy
  Scalar s(0), p(1), minc(numext::real(m1.coeff(0))), maxc(numext::real(m1.coeff(0)));
  for(int j = 0; j < cols; j++)
  for(int i = 0; i < rows; i++)
  {
    s += m1(i,j);
    p *= m1_for_prod(i,j);
    minc = (std::min)(numext::real(minc), numext::real(m1(i,j)));
    maxc = (std::max)(numext::real(maxc), numext::real(m1(i,j)));
  }
  const Scalar mean = s/Scalar(RealScalar(rows*cols));

  VERIFY_IS_APPROX(m1.sum(), s);
  VERIFY_IS_APPROX(m1.mean(), mean);
  VERIFY_IS_APPROX(m1_for_prod.prod(), p);
  VERIFY_IS_APPROX(m1.real().minCoeff(), numext::real(minc));
  VERIFY_IS_APPROX(m1.real().maxCoeff(), numext::real(maxc));

  // test slice vectorization assuming assign is ok
  Index r0 = internal::random<Index>(0,rows-1);
  Index c0 = internal::random<Index>(0,cols-1);
  Index r1 = internal::random<Index>(r0+1,rows)-r0;
  Index c1 = internal::random<Index>(c0+1,cols)-c0;
  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).sum(), m1.block(r0,c0,r1,c1).eval().sum());
  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).mean(), m1.block(r0,c0,r1,c1).eval().mean());
  VERIFY_IS_APPROX(m1_for_prod.block(r0,c0,r1,c1).prod(), m1_for_prod.block(r0,c0,r1,c1).eval().prod());
  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().minCoeff(), m1.block(r0,c0,r1,c1).real().eval().minCoeff());
  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().maxCoeff(), m1.block(r0,c0,r1,c1).real().eval().maxCoeff());

  // test empty objects
  VERIFY_IS_APPROX(m1.block(r0,c0,0,0).sum(),   Scalar(0));
  VERIFY_IS_APPROX(m1.block(r0,c0,0,0).prod(),  Scalar(1));
}

template<typename VectorType> void vectorRedux(const VectorType& w)
{
  using std::abs;
  typedef typename VectorType::Index Index;
  typedef typename VectorType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  Index size = w.size();

  VectorType v = VectorType::Random(size);
  VectorType v_for_prod = VectorType::Ones(size) + Scalar(0.2) * v; // see comment above declaration of m1_for_prod

  for(int i = 1; i < size; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(numext::real(v.coeff(0))), maxc(numext::real(v.coeff(0)));
    for(int j = 0; j < i; j++)
    {
      s += v[j];
      p *= v_for_prod[j];
      minc = (std::min)(minc, numext::real(v[j]));
      maxc = (std::max)(maxc, numext::real(v[j]));
    }
    VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.head(i).sum()), Scalar(1));
    VERIFY_IS_APPROX(p, v_for_prod.head(i).prod());
    VERIFY_IS_APPROX(minc, v.real().head(i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().head(i).maxCoeff());
  }

  for(int i = 0; i < size-1; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(numext::real(v.coeff(i))), maxc(numext::real(v.coeff(i)));
    for(int j = i; j < size; j++)
    {
      s += v[j];
      p *= v_for_prod[j];
      minc = (std::min)(minc, numext::real(v[j]));
      maxc = (std::max)(maxc, numext::real(v[j]));
    }
    VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.tail(size-i).sum()), Scalar(1));
    VERIFY_IS_APPROX(p, v_for_prod.tail(size-i).prod());
    VERIFY_IS_APPROX(minc, v.real().tail(size-i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().tail(size-i).maxCoeff());
  }

  for(int i = 0; i < size/2; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(numext::real(v.coeff(i))), maxc(numext::real(v.coeff(i)));
    for(int j = i; j < size-i; j++)
    {
      s += v[j];
      p *= v_for_prod[j];
      minc = (std::min)(minc, numext::real(v[j]));
      maxc = (std::max)(maxc, numext::real(v[j]));
    }
    VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.segment(i, size-2*i).sum()), Scalar(1));
    VERIFY_IS_APPROX(p, v_for_prod.segment(i, size-2*i).prod());
    VERIFY_IS_APPROX(minc, v.real().segment(i, size-2*i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().segment(i, size-2*i).maxCoeff());
  }

  // test empty objects
  VERIFY_IS_APPROX(v.head(0).sum(),   Scalar(0));
  VERIFY_IS_APPROX(v.tail(0).prod(),  Scalar(1));
  VERIFY_RAISES_ASSERT(v.head(0).mean());
  VERIFY_RAISES_ASSERT(v.head(0).minCoeff());
  VERIFY_RAISES_ASSERT(v.head(0).maxCoeff());
}

void test_redux()
{
  // the max size cannot be too large, otherwise reduxion operations obviously generate large errors.
  int maxsize = (std::min)(100,EIGEN_TEST_MAX_SIZE);
  TEST_SET_BUT_UNUSED_VARIABLE(maxsize);
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( matrixRedux(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_1( matrixRedux(Array<float, 1, 1>()) );
    CALL_SUBTEST_2( matrixRedux(Matrix2f()) );
    CALL_SUBTEST_2( matrixRedux(Array2f()) );
    CALL_SUBTEST_3( matrixRedux(Matrix4d()) );
    CALL_SUBTEST_3( matrixRedux(Array4d()) );
    CALL_SUBTEST_4( matrixRedux(MatrixXcf(internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_4( matrixRedux(ArrayXXcf(internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_5( matrixRedux(MatrixXd (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_5( matrixRedux(ArrayXXd (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_6( matrixRedux(MatrixXi (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_6( matrixRedux(ArrayXXi (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
  }
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_7( vectorRedux(Vector4f()) );
    CALL_SUBTEST_7( vectorRedux(Array4f()) );
    CALL_SUBTEST_5( vectorRedux(VectorXd(internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_5( vectorRedux(ArrayXd(internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_8( vectorRedux(VectorXf(internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_8( vectorRedux(ArrayXf(internal::random<int>(1,maxsize))) );
  }
}
<commit_msg>Add unit test to check nesting of complex expressions in redux()<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define TEST_ENABLE_TEMPORARY_TRACKING

#include "main.h"

template<typename MatrixType> void matrixRedux(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename MatrixType::RealScalar RealScalar;

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols);

  // The entries of m1 are uniformly distributed in [0,1], so m1.prod() is very small. This may lead to test
  // failures if we underflow into denormals. Thus, we scale so that entires are close to 1.
  MatrixType m1_for_prod = MatrixType::Ones(rows, cols) + RealScalar(0.2) * m1;

  VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows, cols).sum(), Scalar(1));
  VERIFY_IS_APPROX(MatrixType::Ones(rows, cols).sum(), Scalar(float(rows*cols))); // the float() here to shut up excessive MSVC warning about int->complex conversion being lossy
  Scalar s(0), p(1), minc(numext::real(m1.coeff(0))), maxc(numext::real(m1.coeff(0)));
  for(int j = 0; j < cols; j++)
  for(int i = 0; i < rows; i++)
  {
    s += m1(i,j);
    p *= m1_for_prod(i,j);
    minc = (std::min)(numext::real(minc), numext::real(m1(i,j)));
    maxc = (std::max)(numext::real(maxc), numext::real(m1(i,j)));
  }
  const Scalar mean = s/Scalar(RealScalar(rows*cols));

  VERIFY_IS_APPROX(m1.sum(), s);
  VERIFY_IS_APPROX(m1.mean(), mean);
  VERIFY_IS_APPROX(m1_for_prod.prod(), p);
  VERIFY_IS_APPROX(m1.real().minCoeff(), numext::real(minc));
  VERIFY_IS_APPROX(m1.real().maxCoeff(), numext::real(maxc));

  // test slice vectorization assuming assign is ok
  Index r0 = internal::random<Index>(0,rows-1);
  Index c0 = internal::random<Index>(0,cols-1);
  Index r1 = internal::random<Index>(r0+1,rows)-r0;
  Index c1 = internal::random<Index>(c0+1,cols)-c0;
  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).sum(), m1.block(r0,c0,r1,c1).eval().sum());
  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).mean(), m1.block(r0,c0,r1,c1).eval().mean());
  VERIFY_IS_APPROX(m1_for_prod.block(r0,c0,r1,c1).prod(), m1_for_prod.block(r0,c0,r1,c1).eval().prod());
  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().minCoeff(), m1.block(r0,c0,r1,c1).real().eval().minCoeff());
  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().maxCoeff(), m1.block(r0,c0,r1,c1).real().eval().maxCoeff());

  // test empty objects
  VERIFY_IS_APPROX(m1.block(r0,c0,0,0).sum(),   Scalar(0));
  VERIFY_IS_APPROX(m1.block(r0,c0,0,0).prod(),  Scalar(1));

  // test nesting complex expression
  VERIFY_EVALUATION_COUNT( (m1.matrix()*m1.matrix().transpose()).sum(), (MatrixType::SizeAtCompileTime==Dynamic ? 1 : 0) );
  VERIFY_EVALUATION_COUNT( ((m1.matrix()*m1.matrix().transpose())*Scalar(2)).sum(), (MatrixType::SizeAtCompileTime==Dynamic ? 1 : 0) );

}

template<typename VectorType> void vectorRedux(const VectorType& w)
{
  using std::abs;
  typedef typename VectorType::Index Index;
  typedef typename VectorType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  Index size = w.size();

  VectorType v = VectorType::Random(size);
  VectorType v_for_prod = VectorType::Ones(size) + Scalar(0.2) * v; // see comment above declaration of m1_for_prod

  for(int i = 1; i < size; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(numext::real(v.coeff(0))), maxc(numext::real(v.coeff(0)));
    for(int j = 0; j < i; j++)
    {
      s += v[j];
      p *= v_for_prod[j];
      minc = (std::min)(minc, numext::real(v[j]));
      maxc = (std::max)(maxc, numext::real(v[j]));
    }
    VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.head(i).sum()), Scalar(1));
    VERIFY_IS_APPROX(p, v_for_prod.head(i).prod());
    VERIFY_IS_APPROX(minc, v.real().head(i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().head(i).maxCoeff());
  }

  for(int i = 0; i < size-1; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(numext::real(v.coeff(i))), maxc(numext::real(v.coeff(i)));
    for(int j = i; j < size; j++)
    {
      s += v[j];
      p *= v_for_prod[j];
      minc = (std::min)(minc, numext::real(v[j]));
      maxc = (std::max)(maxc, numext::real(v[j]));
    }
    VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.tail(size-i).sum()), Scalar(1));
    VERIFY_IS_APPROX(p, v_for_prod.tail(size-i).prod());
    VERIFY_IS_APPROX(minc, v.real().tail(size-i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().tail(size-i).maxCoeff());
  }

  for(int i = 0; i < size/2; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(numext::real(v.coeff(i))), maxc(numext::real(v.coeff(i)));
    for(int j = i; j < size-i; j++)
    {
      s += v[j];
      p *= v_for_prod[j];
      minc = (std::min)(minc, numext::real(v[j]));
      maxc = (std::max)(maxc, numext::real(v[j]));
    }
    VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.segment(i, size-2*i).sum()), Scalar(1));
    VERIFY_IS_APPROX(p, v_for_prod.segment(i, size-2*i).prod());
    VERIFY_IS_APPROX(minc, v.real().segment(i, size-2*i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().segment(i, size-2*i).maxCoeff());
  }

  // test empty objects
  VERIFY_IS_APPROX(v.head(0).sum(),   Scalar(0));
  VERIFY_IS_APPROX(v.tail(0).prod(),  Scalar(1));
  VERIFY_RAISES_ASSERT(v.head(0).mean());
  VERIFY_RAISES_ASSERT(v.head(0).minCoeff());
  VERIFY_RAISES_ASSERT(v.head(0).maxCoeff());
}

void test_redux()
{
  // the max size cannot be too large, otherwise reduxion operations obviously generate large errors.
  int maxsize = (std::min)(100,EIGEN_TEST_MAX_SIZE);
  TEST_SET_BUT_UNUSED_VARIABLE(maxsize);
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( matrixRedux(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_1( matrixRedux(Array<float, 1, 1>()) );
    CALL_SUBTEST_2( matrixRedux(Matrix2f()) );
    CALL_SUBTEST_2( matrixRedux(Array2f()) );
    CALL_SUBTEST_3( matrixRedux(Matrix4d()) );
    CALL_SUBTEST_3( matrixRedux(Array4d()) );
    CALL_SUBTEST_4( matrixRedux(MatrixXcf(internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_4( matrixRedux(ArrayXXcf(internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_5( matrixRedux(MatrixXd (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_5( matrixRedux(ArrayXXd (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_6( matrixRedux(MatrixXi (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_6( matrixRedux(ArrayXXi (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
  }
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_7( vectorRedux(Vector4f()) );
    CALL_SUBTEST_7( vectorRedux(Array4f()) );
    CALL_SUBTEST_5( vectorRedux(VectorXd(internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_5( vectorRedux(ArrayXd(internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_8( vectorRedux(VectorXf(internal::random<int>(1,maxsize))) );
    CALL_SUBTEST_8( vectorRedux(ArrayXf(internal::random<int>(1,maxsize))) );
  }
}
<|endoftext|>


<commit_before><commit_msg>AV1InvTxfm2d.RunRoundtripCheck: Add TX64X64 test.<commit_after><|endoftext|>


<commit_before>/*
 * This file is part of the SPLINTER library.
 * Copyright (C) 2012 Bjarne Grimstad (bjarne.grimstad@gmail.com).
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <operator_overloads.h>
#include <testingutilities.h>

namespace SPLINTER
{

/*
 * Comparison operators
 */
bool operator==(const DataTable &lhs, const DataTable &rhs) {
    return
            lhs.getNumVariables() == rhs.getNumVariables()
            && lhs.getNumSamples() == rhs.getNumSamples()
            && lhs.getSamples() == rhs.getSamples()
            && lhs.getGrid() == rhs.getGrid();
}

bool operator==(const DataSample &lhs, const DataSample &rhs) {
    for(unsigned int i = 0; i < lhs.getDimX(); i++)
    {
        if(!equalsWithinRange(lhs.getX().at(i), rhs.getX().at(i))) {
            return false;
        }
    }

    if(!equalsWithinRange(lhs.getY(), rhs.getY())) {
        return false;
    }

    return true;
}

bool operator==(const BSpline &lhs, const BSpline &rhs)
{
    return
            lhs.getNumVariables() == rhs.getNumVariables()
            && lhs.getNumControlPoints() == rhs.getNumControlPoints()
            && lhs.getNumBasisFunctions() == rhs.getNumBasisFunctions()
            && lhs.getKnotVectors() == rhs.getKnotVectors()
            && lhs.getBasisDegrees() == rhs.getBasisDegrees()
            && lhs.getDomainLowerBound() == rhs.getDomainLowerBound()
            && lhs.getDomainUpperBound() == rhs.getDomainUpperBound();
}

bool operator==(const PSpline &lhs, const PSpline &rhs)
{
    return
            lhs.getNumVariables() == rhs.getNumVariables();
}

bool operator==(const RadialBasisFunction &lhs, const RadialBasisFunction &rhs)
{
    return
            lhs.getNumVariables() == rhs.getNumVariables();
}

bool operator==(const PolynomialRegression &lhs, const PolynomialRegression &rhs)
{
    return
            lhs.getNumVariables() == rhs.getNumVariables();
}

template <class T>
bool operator==(const std::vector<T> &lhs, const std::vector<T> &rhs)
{
    auto lit = lhs.cbegin(), rit = rhs.cbegin();
    for (; lit != lhs.cend() && rit != rhs.cend(); ++lit, ++rit)
    {
        if(*lit != *rit) {
            return false;
        }
    }
    return true;
}

template <class T>
bool operator==(const std::set<T> &lhs, const std::set<T> &rhs)
{
    auto lit = lhs.cbegin(), rit = rhs.cbegin();
    for (; lit != lhs.cend() && rit != rhs.cend(); ++lit, ++rit)
    {
        if(*lit != *rit) {
            return false;
        }
    }
    return true;
}

template <class T>
bool operator==(const std::multiset<T> &lhs, const std::multiset<T> &rhs)
{
    auto lit = lhs.cbegin(), rit = rhs.cbegin();
    for (; lit != lhs.cend() && rit != rhs.cend(); ++lit, ++rit)
    {
        if(*lit != *rit) {
            return false;
        }
    }
    return true;
}

template <class T>
bool operator!=(const T &lhs, const T &rhs) {
    return !(lhs == rhs);
}

/*
 * Output stream operator
 */
std::ostream &operator<<(std::ostream &out, const DataSample &sample) {
    out << "(";
    bool firstLoop = true;
    for(auto val : sample.getX()) {
        out << val;
        if(!firstLoop) {
            out << ", ";
        }
        firstLoop = false;
    }
    out << ") = (" << sample.getY() << ")";

    return out;
}

std::ostream &operator<<(std::ostream &out, const DataTable &table) {
    out << "numVariables: " << table.getNumVariables() << std::endl;
    out << "numSamples: " << table.getNumSamples() << std::endl;
    // out << "samples: " << table.getSamples() << std::endl;
    out << "grid dimensions: ";
    bool firstLoop = true;
    for(const auto &dimension : table.getGrid()) {
        out << dimension.size();
        if(!firstLoop) {
            out << ", ";
        }
        firstLoop = false;
    }

    return out;
}

template <class T>
std::ostream &operator<<(std::ostream &out, const std::vector<T> &obj) {
    for(const T &elem : obj) {
        out << elem << std::endl;
    }

    return out;
}

template <class T>
std::ostream &operator<<(std::ostream &out, const std::set<T> &obj) {
    for(const T &elem : obj) {
        out << elem << std::endl;
    }

    return out;
}

template <class T>
std::ostream &operator<<(std::ostream &out, const std::multiset<T> &obj) {
    for(const T &elem : obj) {
        out << elem << std::endl;
    }

    return out;
}

} // namespace SPLINTER
<commit_msg>Minor fix to sample and grid printing<commit_after>/*
 * This file is part of the SPLINTER library.
 * Copyright (C) 2012 Bjarne Grimstad (bjarne.grimstad@gmail.com).
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <operator_overloads.h>
#include <testingutilities.h>

namespace SPLINTER
{

/*
 * Comparison operators
 */
bool operator==(const DataTable &lhs, const DataTable &rhs) {
    return
            lhs.getNumVariables() == rhs.getNumVariables()
            && lhs.getNumSamples() == rhs.getNumSamples()
            && lhs.getSamples() == rhs.getSamples()
            && lhs.getGrid() == rhs.getGrid();
}

bool operator==(const DataSample &lhs, const DataSample &rhs) {
    for(unsigned int i = 0; i < lhs.getDimX(); i++)
    {
        if(!equalsWithinRange(lhs.getX().at(i), rhs.getX().at(i))) {
            return false;
        }
    }

    if(!equalsWithinRange(lhs.getY(), rhs.getY())) {
        return false;
    }

    return true;
}

bool operator==(const BSpline &lhs, const BSpline &rhs)
{
    return
            lhs.getNumVariables() == rhs.getNumVariables()
            && lhs.getNumControlPoints() == rhs.getNumControlPoints()
            && lhs.getNumBasisFunctions() == rhs.getNumBasisFunctions()
            && lhs.getKnotVectors() == rhs.getKnotVectors()
            && lhs.getBasisDegrees() == rhs.getBasisDegrees()
            && lhs.getDomainLowerBound() == rhs.getDomainLowerBound()
            && lhs.getDomainUpperBound() == rhs.getDomainUpperBound();
}

bool operator==(const PSpline &lhs, const PSpline &rhs)
{
    return
            lhs.getNumVariables() == rhs.getNumVariables();
}

bool operator==(const RadialBasisFunction &lhs, const RadialBasisFunction &rhs)
{
    return
            lhs.getNumVariables() == rhs.getNumVariables();
}

bool operator==(const PolynomialRegression &lhs, const PolynomialRegression &rhs)
{
    return
            lhs.getNumVariables() == rhs.getNumVariables();
}

template <class T>
bool operator==(const std::vector<T> &lhs, const std::vector<T> &rhs)
{
    auto lit = lhs.cbegin(), rit = rhs.cbegin();
    for (; lit != lhs.cend() && rit != rhs.cend(); ++lit, ++rit)
    {
        if(*lit != *rit) {
            return false;
        }
    }
    return true;
}

template <class T>
bool operator==(const std::set<T> &lhs, const std::set<T> &rhs)
{
    auto lit = lhs.cbegin(), rit = rhs.cbegin();
    for (; lit != lhs.cend() && rit != rhs.cend(); ++lit, ++rit)
    {
        if(*lit != *rit) {
            return false;
        }
    }
    return true;
}

template <class T>
bool operator==(const std::multiset<T> &lhs, const std::multiset<T> &rhs)
{
    auto lit = lhs.cbegin(), rit = rhs.cbegin();
    for (; lit != lhs.cend() && rit != rhs.cend(); ++lit, ++rit)
    {
        if(*lit != *rit) {
            return false;
        }
    }
    return true;
}

template <class T>
bool operator!=(const T &lhs, const T &rhs) {
    return !(lhs == rhs);
}

/*
 * Output stream operator
 */
std::ostream &operator<<(std::ostream &out, const DataSample &sample) {
    out << "(";
    bool firstLoop = true;
    for(auto val : sample.getX()) {
        if(!firstLoop) {
            out << ", ";
        }
        out << val;
        firstLoop = false;
    }
    out << ") = (" << sample.getY() << ")";

    return out;
}

std::ostream &operator<<(std::ostream &out, const DataTable &table) {
    out << "numVariables: " << table.getNumVariables() << std::endl;
    out << "numSamples: " << table.getNumSamples() << std::endl;
    //out << "samples: " << table.getSamples() << std::endl;
    out << "grid dimensions: ";
    bool firstLoop = true;
    for(const auto &dimension : table.getGrid()) {
        if(!firstLoop) {
            out << ", ";
        }
        out << dimension.size();
        firstLoop = false;
    }

    return out;
}

template <class T>
std::ostream &operator<<(std::ostream &out, const std::vector<T> &obj) {
    for(const T &elem : obj) {
        out << elem << std::endl;
    }

    return out;
}

template <class T>
std::ostream &operator<<(std::ostream &out, const std::set<T> &obj) {
    for(const T &elem : obj) {
        out << elem << std::endl;
    }

    return out;
}

template <class T>
std::ostream &operator<<(std::ostream &out, const std::multiset<T> &obj) {
    for(const T &elem : obj) {
        out << elem << std::endl;
    }

    return out;
}

} // namespace SPLINTER
<|endoftext|>