<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/vespalib/util/alloc.h>
#include <vespa/vespalib/util/exceptions.h>
#include <cstddef>

using namespace vespalib;
using namespace vespalib::alloc;

template <typename T>
void
testSwap(T & a, T & b)
{
    void * tmpA(a.get());
    void * tmpB(b.get());
    EXPECT_EQUAL(4096ul, a.size());
    EXPECT_EQUAL(8192ul, b.size());
    std::swap(a, b);
    EXPECT_EQUAL(4096ul, b.size());
    EXPECT_EQUAL(8192ul, a.size());
    EXPECT_EQUAL(tmpA, b.get());
    EXPECT_EQUAL(tmpB, a.get());
}

TEST("test roundUp2inN") {
    EXPECT_EQUAL(0u, roundUp2inN(0));
    EXPECT_EQUAL(2u, roundUp2inN(1));
    EXPECT_EQUAL(2u, roundUp2inN(2));
    EXPECT_EQUAL(4u, roundUp2inN(3));
    EXPECT_EQUAL(4u, roundUp2inN(4));
    EXPECT_EQUAL(8u, roundUp2inN(5));
    EXPECT_EQUAL(8u, roundUp2inN(6));
    EXPECT_EQUAL(8u, roundUp2inN(7));
    EXPECT_EQUAL(8u, roundUp2inN(8));
    EXPECT_EQUAL(16u, roundUp2inN(9));
}

TEST("test basics") {
    {
        Alloc h = Alloc::allocHeap(100);
        EXPECT_EQUAL(100u, h.size());
        EXPECT_TRUE(h.get() != nullptr);
    }
    {
        EXPECT_EXCEPTION(Alloc::allocAlignedHeap(100, 7), IllegalArgumentException, "Alloc::allocAlignedHeap(100, 7) does not support 7 alignment");
        Alloc h = Alloc::allocAlignedHeap(100, 1024);
        EXPECT_EQUAL(100u, h.size());
        EXPECT_TRUE(h.get() != nullptr);
    }
    {
        Alloc h = Alloc::allocMMap(100);
        EXPECT_EQUAL(4096u, h.size());
        EXPECT_TRUE(h.get() != nullptr);
    }
    {
        Alloc a = Alloc::allocHeap(4096), b = Alloc::allocHeap(8192);
        testSwap(a, b);
    }
    {
        Alloc a = Alloc::allocMMap(4096), b = Alloc::allocMMap(8192);
        testSwap(a, b);
    }
    {
        Alloc a = Alloc::allocAlignedHeap(4096, 1024), b = Alloc::allocAlignedHeap(8192, 1024);
        testSwap(a, b);
    }
    {
        Alloc a = Alloc::allocHeap(4096);
        Alloc b = Alloc::allocMMap(8192);
        testSwap(a, b);
    }
    {
        Alloc a = Alloc::allocHeap(100);
        Alloc b = Alloc::allocHeap(100);
        a = std::move(b);
        EXPECT_TRUE(b.get() == nullptr);
    }
}

TEST("test correct alignment") {
    {
        Alloc buf = Alloc::alloc(10, MemoryAllocator::HUGEPAGE_SIZE, 1024);
        EXPECT_TRUE(reinterpret_cast<ptrdiff_t>(buf.get()) % 1024 == 0);
    }

    {
        // Mmapped pointers are page-aligned, but sanity test anyway.
        Alloc buf = Alloc::alloc(3000000, MemoryAllocator::HUGEPAGE_SIZE, 512);
        EXPECT_TRUE(reinterpret_cast<ptrdiff_t>(buf.get()) % 512 == 0);
    }
}

TEST("no rounding of small heap buffer") {
    Alloc buf = Alloc::alloc(3, MemoryAllocator::HUGEPAGE_SIZE);
    EXPECT_EQUAL(3ul, buf.size());
}

TEST("no rounding of large heap buffer") {
    Alloc buf = Alloc::alloc(MemoryAllocator::HUGEPAGE_SIZE*11+3, MemoryAllocator::HUGEPAGE_SIZE*16);
    EXPECT_EQUAL(size_t(MemoryAllocator::HUGEPAGE_SIZE*11+3), buf.size());
}

TEST("rounding of small mmaped buffer") {
    Alloc buf = Alloc::alloc(MemoryAllocator::HUGEPAGE_SIZE);
    EXPECT_EQUAL(MemoryAllocator::HUGEPAGE_SIZE, buf.size());
    buf = Alloc::alloc(MemoryAllocator::HUGEPAGE_SIZE+1);
    EXPECT_EQUAL(MemoryAllocator::HUGEPAGE_SIZE*2ul, buf.size());
}

TEST("rounding of large mmaped buffer") {
    Alloc buf = Alloc::alloc(MemoryAllocator::HUGEPAGE_SIZE*11+3);
    EXPECT_EQUAL(MemoryAllocator::HUGEPAGE_SIZE*12ul, buf.size());
}

TEST("heap alloc can not be extended") {
    Alloc buf = Alloc::allocHeap(100);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(100ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(101));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(100ul, buf.size());
}

TEST("auto alloced heap alloc can not be extended") {
    Alloc buf = Alloc::alloc(100);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(100ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(101));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(100ul, buf.size());
}

TEST("auto alloced heap alloc can not be extended, even if resize will be mmapped") {
    Alloc buf = Alloc::alloc(100);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(100ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(MemoryAllocator::HUGEPAGE_SIZE*3));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(100ul, buf.size());
}

void verifyExtension(Alloc & buf, size_t currSZ, size_t newSZ) {
    bool expectSuccess = (currSZ != newSZ);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(currSZ, buf.size());
    EXPECT_EQUAL(expectSuccess, buf.resize_inplace(currSZ+1));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(newSZ, buf.size());
}

void ensureRoomForExtension(const Alloc & buf, Alloc & reserved) {
    // Normally mmapping starts at the top and grows down in address space.
    // Then there is no room to extend the last mapping.
    // So in order to verify this we first mmap a reserved area that we unmap
    // before we test extension.
    if (reserved.get() > buf.get()) {
        EXPECT_EQUAL(reserved.get(), static_cast<const char *>(buf.get()) + buf.size());
        {
            Alloc().swap(reserved);
        }
    }
}

void verifyNoExtensionWhenNoRoom(Alloc & buf, Alloc & reserved, size_t sz) {
    if (reserved.get() > buf.get()) {
        // Normally mmapping starts at the top and grows down in address space.
        // Then there is no room to extend the last mapping.
        EXPECT_EQUAL(reserved.get(), static_cast<const char *>(buf.get()) + buf.size());
        TEST_DO(verifyExtension(buf, sz, sz));
    } else {
        EXPECT_EQUAL(buf.get(), static_cast<const char *>(reserved.get()) + reserved.size());
        TEST_DO(verifyExtension(reserved, sz, sz));
    }
}

TEST("auto alloced mmap alloc can be extended if room") {
    static constexpr size_t SZ = MemoryAllocator::HUGEPAGE_SIZE*2;
    Alloc reserved = Alloc::alloc(SZ);
    Alloc buf = Alloc::alloc(SZ);

    TEST_DO(ensureRoomForExtension(buf, reserved));
    TEST_DO(verifyExtension(buf, SZ, (SZ/2)*3));
}

TEST("auto alloced mmap alloc can not be extended if no room") {
    static constexpr size_t SZ = MemoryAllocator::HUGEPAGE_SIZE*2;
    Alloc reserved = Alloc::alloc(SZ);
    Alloc buf = Alloc::alloc(SZ);

    TEST_DO(verifyNoExtensionWhenNoRoom(buf, reserved, SZ));
}

TEST("mmap alloc can be extended if room") {
    Alloc dummy = Alloc::allocMMap(100);
    Alloc reserved = Alloc::allocMMap(100);
    Alloc buf = Alloc::allocMMap(100);

    TEST_DO(ensureRoomForExtension(buf, reserved));
    TEST_DO(verifyExtension(buf, 4096, 4096*2));
}

TEST("mmap alloc can not be extended if no room") {
    Alloc dummy = Alloc::allocMMap(100);
    Alloc reserved = Alloc::allocMMap(100);
    Alloc buf = Alloc::allocMMap(100);

    TEST_DO(verifyNoExtensionWhenNoRoom(buf, reserved, 4096));
}

TEST("heap alloc can not be shrinked") {
    Alloc buf = Alloc::allocHeap(101);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(101ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(100));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(101ul, buf.size());
}

TEST("mmap alloc can be shrinked") {
    Alloc buf = Alloc::allocMMap(4097);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(8192ul, buf.size());
    EXPECT_TRUE(buf.resize_inplace(4095));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(4096ul, buf.size());
}

TEST("auto alloced heap alloc can not be shrinked") {
    Alloc buf = Alloc::alloc(101);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(101ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(100));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(101ul, buf.size());
}

TEST("auto alloced mmap alloc can be shrinked") {
    static constexpr size_t SZ = MemoryAllocator::HUGEPAGE_SIZE;
    Alloc buf = Alloc::alloc(SZ + 1);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(SZ + MemoryAllocator::HUGEPAGE_SIZE, buf.size());
    EXPECT_TRUE(buf.resize_inplace(SZ-1));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(SZ, buf.size());
}

TEST("auto alloced mmap alloc can not be shrinked below HUGEPAGE_SIZE/2 + 1 ") {
    static constexpr size_t SZ = MemoryAllocator::HUGEPAGE_SIZE;
    Alloc buf = Alloc::alloc(SZ + 1);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(SZ + MemoryAllocator::HUGEPAGE_SIZE, buf.size());
    EXPECT_TRUE(buf.resize_inplace(SZ/2 + 1));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(SZ, buf.size());
    EXPECT_FALSE(buf.resize_inplace(SZ/2));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(SZ, buf.size());
    EXPECT_TRUE(buf.resize_inplace(SZ));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(SZ, buf.size());
}

TEST_MAIN() { TEST_RUN_ALL(); }
<commit_msg>Check that pointers are equal, don't try to compare C strings. Skip some tests that depend on the linux vm subsystem when running unit tests on non-linux platform.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/vespalib/util/alloc.h>
#include <vespa/vespalib/util/exceptions.h>
#include <cstddef>

using namespace vespalib;
using namespace vespalib::alloc;

template <typename T>
void
testSwap(T & a, T & b)
{
    void * tmpA(a.get());
    void * tmpB(b.get());
    EXPECT_EQUAL(4096ul, a.size());
    EXPECT_EQUAL(8192ul, b.size());
    std::swap(a, b);
    EXPECT_EQUAL(4096ul, b.size());
    EXPECT_EQUAL(8192ul, a.size());
    EXPECT_EQUAL(tmpA, b.get());
    EXPECT_EQUAL(tmpB, a.get());
}

TEST("test roundUp2inN") {
    EXPECT_EQUAL(0u, roundUp2inN(0));
    EXPECT_EQUAL(2u, roundUp2inN(1));
    EXPECT_EQUAL(2u, roundUp2inN(2));
    EXPECT_EQUAL(4u, roundUp2inN(3));
    EXPECT_EQUAL(4u, roundUp2inN(4));
    EXPECT_EQUAL(8u, roundUp2inN(5));
    EXPECT_EQUAL(8u, roundUp2inN(6));
    EXPECT_EQUAL(8u, roundUp2inN(7));
    EXPECT_EQUAL(8u, roundUp2inN(8));
    EXPECT_EQUAL(16u, roundUp2inN(9));
}

TEST("test basics") {
    {
        Alloc h = Alloc::allocHeap(100);
        EXPECT_EQUAL(100u, h.size());
        EXPECT_TRUE(h.get() != nullptr);
    }
    {
        EXPECT_EXCEPTION(Alloc::allocAlignedHeap(100, 7), IllegalArgumentException, "Alloc::allocAlignedHeap(100, 7) does not support 7 alignment");
        Alloc h = Alloc::allocAlignedHeap(100, 1024);
        EXPECT_EQUAL(100u, h.size());
        EXPECT_TRUE(h.get() != nullptr);
    }
    {
        Alloc h = Alloc::allocMMap(100);
        EXPECT_EQUAL(4096u, h.size());
        EXPECT_TRUE(h.get() != nullptr);
    }
    {
        Alloc a = Alloc::allocHeap(4096), b = Alloc::allocHeap(8192);
        testSwap(a, b);
    }
    {
        Alloc a = Alloc::allocMMap(4096), b = Alloc::allocMMap(8192);
        testSwap(a, b);
    }
    {
        Alloc a = Alloc::allocAlignedHeap(4096, 1024), b = Alloc::allocAlignedHeap(8192, 1024);
        testSwap(a, b);
    }
    {
        Alloc a = Alloc::allocHeap(4096);
        Alloc b = Alloc::allocMMap(8192);
        testSwap(a, b);
    }
    {
        Alloc a = Alloc::allocHeap(100);
        Alloc b = Alloc::allocHeap(100);
        a = std::move(b);
        EXPECT_TRUE(b.get() == nullptr);
    }
}

TEST("test correct alignment") {
    {
        Alloc buf = Alloc::alloc(10, MemoryAllocator::HUGEPAGE_SIZE, 1024);
        EXPECT_TRUE(reinterpret_cast<ptrdiff_t>(buf.get()) % 1024 == 0);
    }

    {
        // Mmapped pointers are page-aligned, but sanity test anyway.
        Alloc buf = Alloc::alloc(3000000, MemoryAllocator::HUGEPAGE_SIZE, 512);
        EXPECT_TRUE(reinterpret_cast<ptrdiff_t>(buf.get()) % 512 == 0);
    }
}

TEST("no rounding of small heap buffer") {
    Alloc buf = Alloc::alloc(3, MemoryAllocator::HUGEPAGE_SIZE);
    EXPECT_EQUAL(3ul, buf.size());
}

TEST("no rounding of large heap buffer") {
    Alloc buf = Alloc::alloc(MemoryAllocator::HUGEPAGE_SIZE*11+3, MemoryAllocator::HUGEPAGE_SIZE*16);
    EXPECT_EQUAL(size_t(MemoryAllocator::HUGEPAGE_SIZE*11+3), buf.size());
}

TEST("rounding of small mmaped buffer") {
    Alloc buf = Alloc::alloc(MemoryAllocator::HUGEPAGE_SIZE);
    EXPECT_EQUAL(MemoryAllocator::HUGEPAGE_SIZE, buf.size());
    buf = Alloc::alloc(MemoryAllocator::HUGEPAGE_SIZE+1);
    EXPECT_EQUAL(MemoryAllocator::HUGEPAGE_SIZE*2ul, buf.size());
}

TEST("rounding of large mmaped buffer") {
    Alloc buf = Alloc::alloc(MemoryAllocator::HUGEPAGE_SIZE*11+3);
    EXPECT_EQUAL(MemoryAllocator::HUGEPAGE_SIZE*12ul, buf.size());
}

TEST("heap alloc can not be extended") {
    Alloc buf = Alloc::allocHeap(100);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(100ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(101));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(100ul, buf.size());
}

TEST("auto alloced heap alloc can not be extended") {
    Alloc buf = Alloc::alloc(100);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(100ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(101));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(100ul, buf.size());
}

TEST("auto alloced heap alloc can not be extended, even if resize will be mmapped") {
    Alloc buf = Alloc::alloc(100);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(100ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(MemoryAllocator::HUGEPAGE_SIZE*3));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(100ul, buf.size());
}

void verifyExtension(Alloc & buf, size_t currSZ, size_t newSZ) {
    bool expectSuccess = (currSZ != newSZ);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(currSZ, buf.size());
    EXPECT_EQUAL(expectSuccess, buf.resize_inplace(currSZ+1));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(newSZ, buf.size());
}

void ensureRoomForExtension(const Alloc & buf, Alloc & reserved) {
    // Normally mmapping starts at the top and grows down in address space.
    // Then there is no room to extend the last mapping.
    // So in order to verify this we first mmap a reserved area that we unmap
    // before we test extension.
    if (reserved.get() > buf.get()) {
        EXPECT_EQUAL(reserved.get(), static_cast<const void *>(static_cast<const char *>(buf.get()) + buf.size()));
        {
            Alloc().swap(reserved);
        }
    }
}

void verifyNoExtensionWhenNoRoom(Alloc & buf, Alloc & reserved, size_t sz) {
    if (reserved.get() > buf.get()) {
        // Normally mmapping starts at the top and grows down in address space.
        // Then there is no room to extend the last mapping.
        EXPECT_EQUAL(reserved.get(), static_cast<const void *>(static_cast<const char *>(buf.get()) + buf.size()));
        TEST_DO(verifyExtension(buf, sz, sz));
    } else {
        EXPECT_EQUAL(buf.get(), static_cast<const void *>(static_cast<const char *>(reserved.get()) + reserved.size()));
        TEST_DO(verifyExtension(reserved, sz, sz));
    }
}

#ifdef __linux__
TEST("auto alloced mmap alloc can be extended if room") {
    static constexpr size_t SZ = MemoryAllocator::HUGEPAGE_SIZE*2;
    Alloc reserved = Alloc::alloc(SZ);
    Alloc buf = Alloc::alloc(SZ);

    TEST_DO(ensureRoomForExtension(buf, reserved));
    TEST_DO(verifyExtension(buf, SZ, (SZ/2)*3));
}

TEST("auto alloced mmap alloc can not be extended if no room") {
    static constexpr size_t SZ = MemoryAllocator::HUGEPAGE_SIZE*2;
    Alloc reserved = Alloc::alloc(SZ);
    Alloc buf = Alloc::alloc(SZ);

    TEST_DO(verifyNoExtensionWhenNoRoom(buf, reserved, SZ));
}

TEST("mmap alloc can be extended if room") {
    Alloc dummy = Alloc::allocMMap(100);
    Alloc reserved = Alloc::allocMMap(100);
    Alloc buf = Alloc::allocMMap(100);

    TEST_DO(ensureRoomForExtension(buf, reserved));
    TEST_DO(verifyExtension(buf, 4096, 4096*2));
}

TEST("mmap alloc can not be extended if no room") {
    Alloc dummy = Alloc::allocMMap(100);
    Alloc reserved = Alloc::allocMMap(100);
    Alloc buf = Alloc::allocMMap(100);

    TEST_DO(verifyNoExtensionWhenNoRoom(buf, reserved, 4096));
}
#endif

TEST("heap alloc can not be shrinked") {
    Alloc buf = Alloc::allocHeap(101);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(101ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(100));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(101ul, buf.size());
}

TEST("mmap alloc can be shrinked") {
    Alloc buf = Alloc::allocMMap(4097);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(8192ul, buf.size());
    EXPECT_TRUE(buf.resize_inplace(4095));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(4096ul, buf.size());
}

TEST("auto alloced heap alloc can not be shrinked") {
    Alloc buf = Alloc::alloc(101);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(101ul, buf.size());
    EXPECT_FALSE(buf.resize_inplace(100));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(101ul, buf.size());
}

TEST("auto alloced mmap alloc can be shrinked") {
    static constexpr size_t SZ = MemoryAllocator::HUGEPAGE_SIZE;
    Alloc buf = Alloc::alloc(SZ + 1);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(SZ + MemoryAllocator::HUGEPAGE_SIZE, buf.size());
    EXPECT_TRUE(buf.resize_inplace(SZ-1));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(SZ, buf.size());
}

TEST("auto alloced mmap alloc can not be shrinked below HUGEPAGE_SIZE/2 + 1 ") {
    static constexpr size_t SZ = MemoryAllocator::HUGEPAGE_SIZE;
    Alloc buf = Alloc::alloc(SZ + 1);
    void * oldPtr = buf.get();
    EXPECT_EQUAL(SZ + MemoryAllocator::HUGEPAGE_SIZE, buf.size());
    EXPECT_TRUE(buf.resize_inplace(SZ/2 + 1));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(SZ, buf.size());
    EXPECT_FALSE(buf.resize_inplace(SZ/2));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(SZ, buf.size());
    EXPECT_TRUE(buf.resize_inplace(SZ));
    EXPECT_EQUAL(oldPtr, buf.get());
    EXPECT_EQUAL(SZ, buf.size());
}

TEST_MAIN() { TEST_RUN_ALL(); }
<|endoftext|>


<commit_before>/*
    Empath - Mailer for KDE

    Copyright 1999, 2000
        Rik Hemsley <rik@kde.org>
        Wilco Greven <j.w.greven@student.utwente.nl>

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

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

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

// System includes
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>

// KDE includes
#include <kuniqueapp.h>

// Local includes
#include "Empath.h"
#include "EmpathUI.h"

    int
main(int argc, char ** argv)
{
    // Don't do anything if we're being run as root.
    if (getuid() == 0 || geteuid() == 0) {
        fprintf(stderr, "DO NOT RUN GUI APPS AS ROOT !\n");
        return 1;
    }

    // Pick a sensible umask for everything Empath does.
    int prev_umask = umask(077);

#define DOSOMEDOSOMEDOSOME
#ifdef DOSOMEDOSOMEDOSOME

    if (!KUniqueApplication::start(argc, argv, "empath"))
        exit(0);

    KUniqueApplication app(argc, argv, "empath");

#else

    KApplication app(argc, argv, "empath");

#endif

    // Create the kernel.
    Empath::start();

    // Create the user interface.
    EmpathUI * ui = new EmpathUI;

    // Attempt to get the UI up and running quickly.
    app.processEvents();

    // Initialise the kernel.
    empath->init();

    // Enter the event loop.
    int retval = app.exec();

    delete ui;
    ui = 0;

    empath->shutdown();

    // Restore umask.
    umask(prev_umask);

    return retval;
}

// vim:ts=4:sw=4:tw=78
<commit_msg>include stdlib.h<commit_after>/*
    Empath - Mailer for KDE

    Copyright 1999, 2000
        Rik Hemsley <rik@kde.org>
        Wilco Greven <j.w.greven@student.utwente.nl>

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

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

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

// System includes
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>

// KDE includes
#include <kuniqueapp.h>

// Local includes
#include "Empath.h"
#include "EmpathUI.h"

    int
main(int argc, char ** argv)
{
    // Don't do anything if we're being run as root.
    if (getuid() == 0 || geteuid() == 0) {
        fprintf(stderr, "DO NOT RUN GUI APPS AS ROOT !\n");
        return 1;
    }

    // Pick a sensible umask for everything Empath does.
    int prev_umask = umask(077);

#define DOSOMEDOSOMEDOSOME
#ifdef DOSOMEDOSOMEDOSOME

    if (!KUniqueApplication::start(argc, argv, "empath"))
        exit(0);

    KUniqueApplication app(argc, argv, "empath");

#else

    KApplication app(argc, argv, "empath");

#endif

    // Create the kernel.
    Empath::start();

    // Create the user interface.
    EmpathUI * ui = new EmpathUI;

    // Attempt to get the UI up and running quickly.
    app.processEvents();

    // Initialise the kernel.
    empath->init();

    // Enter the event loop.
    int retval = app.exec();

    delete ui;
    ui = 0;

    empath->shutdown();

    // Restore umask.
    umask(prev_umask);

    return retval;
}

// vim:ts=4:sw=4:tw=78
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "TextProcessor.hxx"
#include "strmap.hxx"
#include "istream/UnusedPtr.hxx"
#include "istream/SubstIstream.hxx"
#include "widget/Widget.hxx"
#include "widget/Class.hxx"
#include "penv.hxx"
#include "pool/pool.hxx"
#include "escape_html.hxx"
#include "escape_pool.hxx"

#include <assert.h>

gcc_pure
static bool
text_processor_allowed_content_type(const char *content_type)
{
	assert(content_type != NULL);

	return strncmp(content_type, "text/", 5) == 0 ||
		strncmp(content_type, "application/json", 16) == 0 ||
		strncmp(content_type, "application/javascript", 22) == 0;
}

bool
text_processor_allowed(const StringMap &headers)
{
	const char *content_type = headers.Get("content-type");
	return content_type != NULL &&
		text_processor_allowed_content_type(content_type);
}

gcc_pure
static const char *
base_uri(struct pool *pool, const char *absolute_uri)
{
	const char *p;

	if (absolute_uri == NULL)
		return NULL;

	p = strchr(absolute_uri, ';');
	if (p == NULL) {
		p = strchr(absolute_uri, '?');
		if (p == NULL)
			return absolute_uri;
	}

	return p_strndup(pool, absolute_uri, p - absolute_uri);
}

static void
SubstAddEscaped(struct pool &pool, SubstTree &subst, const char *a,
		StringView b) noexcept
{
	if (!b.empty())
		b = escape_dup(&pool, &html_escape_class, b);

	subst.Add(pool, a, b);
}

static SubstTree
processor_subst_beng_widget(struct pool &pool,
			    const Widget &widget,
			    const struct processor_env &env)
{
	SubstTree subst;
	SubstAddEscaped(pool, subst, "&c:type;", widget.class_name);
	SubstAddEscaped(pool, subst, "&c:class;", widget.GetQuotedClassName());
	SubstAddEscaped(pool, subst, "&c:local;", widget.cls->local_uri);
	SubstAddEscaped(pool, subst, "&c:id;", widget.id);
	SubstAddEscaped(pool, subst, "&c:path;", widget.GetIdPath());
	SubstAddEscaped(pool, subst, "&c:prefix;", widget.GetPrefix());
	SubstAddEscaped(pool, subst, "&c:uri;", env.absolute_uri);
	SubstAddEscaped(pool, subst, "&c:base;", base_uri(&pool, env.uri));
	SubstAddEscaped(pool, subst, "&c:frame;", strmap_get_checked(env.args, "frame"));
	SubstAddEscaped(pool, subst, "&c:view;", widget.GetEffectiveView()->name);
	SubstAddEscaped(pool, subst, "&c:session;", nullptr); /* obsolete as of version 15.29 */
	return subst;
}

UnusedIstreamPtr
text_processor(struct pool &pool, UnusedIstreamPtr input,
	       const Widget &widget, const struct processor_env &env)
{
	return istream_subst_new(&pool, std::move(input),
				 processor_subst_beng_widget(pool, widget, env));
}
<commit_msg>bp/TextProcessor: disable escaping for several entities<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "TextProcessor.hxx"
#include "strmap.hxx"
#include "istream/UnusedPtr.hxx"
#include "istream/SubstIstream.hxx"
#include "widget/Widget.hxx"
#include "widget/Class.hxx"
#include "penv.hxx"
#include "pool/pool.hxx"
#include "escape_html.hxx"
#include "escape_pool.hxx"

#include <assert.h>

gcc_pure
static bool
text_processor_allowed_content_type(const char *content_type)
{
	assert(content_type != NULL);

	return strncmp(content_type, "text/", 5) == 0 ||
		strncmp(content_type, "application/json", 16) == 0 ||
		strncmp(content_type, "application/javascript", 22) == 0;
}

bool
text_processor_allowed(const StringMap &headers)
{
	const char *content_type = headers.Get("content-type");
	return content_type != NULL &&
		text_processor_allowed_content_type(content_type);
}

gcc_pure
static const char *
base_uri(struct pool *pool, const char *absolute_uri)
{
	const char *p;

	if (absolute_uri == NULL)
		return NULL;

	p = strchr(absolute_uri, ';');
	if (p == NULL) {
		p = strchr(absolute_uri, '?');
		if (p == NULL)
			return absolute_uri;
	}

	return p_strndup(pool, absolute_uri, p - absolute_uri);
}

static void
SubstAddEscaped(struct pool &pool, SubstTree &subst, const char *a,
		StringView b) noexcept
{
	if (!b.empty())
		b = escape_dup(&pool, &html_escape_class, b);

	subst.Add(pool, a, b);
}

static SubstTree
processor_subst_beng_widget(struct pool &pool,
			    const Widget &widget,
			    const struct processor_env &env)
{
	SubstTree subst;
	subst.Add(pool, "&c:type;", widget.class_name);
	subst.Add(pool, "&c:type;", widget.class_name);
	subst.Add(pool, "&c:class;", widget.GetQuotedClassName());
	SubstAddEscaped(pool, subst, "&c:local;", widget.cls->local_uri);
	subst.Add(pool, "&c:id;", widget.id);
	subst.Add(pool, "&c:path;", widget.GetIdPath());
	subst.Add(pool, "&c:prefix;", widget.GetPrefix());
	SubstAddEscaped(pool, subst, "&c:uri;", env.absolute_uri);
	SubstAddEscaped(pool, subst, "&c:base;", base_uri(&pool, env.uri));
	SubstAddEscaped(pool, subst, "&c:frame;", strmap_get_checked(env.args, "frame"));
	subst.Add(pool, "&c:view;", widget.GetEffectiveView()->name);
	subst.Add(pool, "&c:session;", nullptr); /* obsolete as of version 15.29 */
	return subst;
}

UnusedIstreamPtr
text_processor(struct pool &pool, UnusedIstreamPtr input,
	       const Widget &widget, const struct processor_env &env)
{
	return istream_subst_new(&pool, std::move(input),
				 processor_subst_beng_widget(pool, widget, env));
}
<|endoftext|>


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

#pragma once

#include <bsoncxx/config/prelude.hpp>

#include <cstdint>

#include <bsoncxx/document/view.hpp>
#include <bsoncxx/stdx/optional.hpp>

namespace bsoncxx {
BSONCXX_INLINE_NAMESPACE_BEGIN

class validator;

///
/// Validates a BSON document. This is a simplified overload that will
/// only do the bare minimum validation of document structure, and does
/// not provide any further information if the document is found to be invalid.
///
/// @param data
///   A buffer containing a BSON document to validate.
/// @param length
///   The size of the buffer.
///
/// @returns
///   An engaged optional containing a view if the document is valid, or
///   an unengaged optional if the document is invalid.
///
BSONCXX_API stdx::optional<document::view> validate(const std::uint8_t* data,
                                                    std::size_t length);

///
/// Validates a BSON document. This overload provides additional control over the
/// precise validation that is performed, and will give the caller access to the
/// offset at which the document was found to be invalid.
///
/// @param data
///   A buffer containing a BSON document to validate.
/// @param length
///   The size of the buffer.
/// @param validator
///   A validator used to configure what checks are done. If validation fails, it
///   will contain the offset at which the document was found to be invalid.
/// @param invalid_offset
///   If validation fails, the offset at which the document was found to be invalid
///   will be stored here (if non-null).
///
/// @returns
///   An engaged optional containing a view if the document is valid, or
///   an unengaged optional if the document is invalid.
///
BSONCXX_API stdx::optional<document::view> validate(const std::uint8_t* data,
                                                    std::size_t length,
                                                    const validator& validator,
                                                    std::size_t* invalid_offset = nullptr);
///
/// A validator is used to enable or disable specific checks that can be
/// performed during BSON validation.
///
class BSONCXX_API validator {
   public:
    ///
    /// Constructs a validator.
    ///
    validator();

    ///
    /// Destructs a validator.
    ///
    ~validator();

    ///
    /// Verify that all keys and string values are valid UTF-8.
    ///
    /// @param check_utf8
    ///   If true, UTF-8 validation is performed.
    ///
    void check_utf8(bool check_utf8);
    bool check_utf8() const;

    ///
    /// Verify that all keys and string values are valid UTF-8, but allow
    /// null bytes. This is generally bad practice, but some languages such
    /// as Python, can sennd UTF-8 encoded strings with null bytes.
    ///
    /// @param check_utf8_allow_null
    ///   If true, UTF-8 validation (with null bytes allowed) is performed.
    ///
    void check_utf8_allow_null(bool check_utf8_allow_null);
    bool check_utf8_allow_null() const;

    ///
    /// Verifies that document keys are not preceeded with '$'. Such keys
    /// are reserved for MongoDB internal use.
    ///
    /// @param check_dollar_keys
    ///   If true, keys starting with '$' will be treated as invalid.
    ///
    void check_dollar_keys(bool check_dollar_keys);
    bool check_dollar_keys() const;

    ///
    /// Verifies that document keys do not contain any '.' characters. The dot
    /// character is illegal in MongoDB keys.
    ///
    /// @param check_dollar_keys
    ///   If true, keys containing '.' will be treated as invalid.
    ///
    void check_dot_keys(bool check_dot_keys);
    bool check_dot_keys() const;

   private:
    struct BSONCXX_PRIVATE impl;
    std::unique_ptr<impl> _impl;
};

BSONCXX_INLINE_NAMESPACE_END
}  // namespace bsoncxx

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

#pragma once

#include <bsoncxx/config/prelude.hpp>

#include <cstdint>
#include <memory>

#include <bsoncxx/document/view.hpp>
#include <bsoncxx/stdx/optional.hpp>

namespace bsoncxx {
BSONCXX_INLINE_NAMESPACE_BEGIN

class validator;

///
/// Validates a BSON document. This is a simplified overload that will
/// only do the bare minimum validation of document structure, and does
/// not provide any further information if the document is found to be invalid.
///
/// @param data
///   A buffer containing a BSON document to validate.
/// @param length
///   The size of the buffer.
///
/// @returns
///   An engaged optional containing a view if the document is valid, or
///   an unengaged optional if the document is invalid.
///
BSONCXX_API stdx::optional<document::view> validate(const std::uint8_t* data,
                                                    std::size_t length);

///
/// Validates a BSON document. This overload provides additional control over the
/// precise validation that is performed, and will give the caller access to the
/// offset at which the document was found to be invalid.
///
/// @param data
///   A buffer containing a BSON document to validate.
/// @param length
///   The size of the buffer.
/// @param validator
///   A validator used to configure what checks are done. If validation fails, it
///   will contain the offset at which the document was found to be invalid.
/// @param invalid_offset
///   If validation fails, the offset at which the document was found to be invalid
///   will be stored here (if non-null).
///
/// @returns
///   An engaged optional containing a view if the document is valid, or
///   an unengaged optional if the document is invalid.
///
BSONCXX_API stdx::optional<document::view> validate(const std::uint8_t* data,
                                                    std::size_t length,
                                                    const validator& validator,
                                                    std::size_t* invalid_offset = nullptr);
///
/// A validator is used to enable or disable specific checks that can be
/// performed during BSON validation.
///
class BSONCXX_API validator {
   public:
    ///
    /// Constructs a validator.
    ///
    validator();

    ///
    /// Destructs a validator.
    ///
    ~validator();

    ///
    /// Verify that all keys and string values are valid UTF-8.
    ///
    /// @param check_utf8
    ///   If true, UTF-8 validation is performed.
    ///
    void check_utf8(bool check_utf8);
    bool check_utf8() const;

    ///
    /// Verify that all keys and string values are valid UTF-8, but allow
    /// null bytes. This is generally bad practice, but some languages such
    /// as Python, can sennd UTF-8 encoded strings with null bytes.
    ///
    /// @param check_utf8_allow_null
    ///   If true, UTF-8 validation (with null bytes allowed) is performed.
    ///
    void check_utf8_allow_null(bool check_utf8_allow_null);
    bool check_utf8_allow_null() const;

    ///
    /// Verifies that document keys are not preceeded with '$'. Such keys
    /// are reserved for MongoDB internal use.
    ///
    /// @param check_dollar_keys
    ///   If true, keys starting with '$' will be treated as invalid.
    ///
    void check_dollar_keys(bool check_dollar_keys);
    bool check_dollar_keys() const;

    ///
    /// Verifies that document keys do not contain any '.' characters. The dot
    /// character is illegal in MongoDB keys.
    ///
    /// @param check_dollar_keys
    ///   If true, keys containing '.' will be treated as invalid.
    ///
    void check_dot_keys(bool check_dot_keys);
    bool check_dot_keys() const;

   private:
    struct BSONCXX_PRIVATE impl;
    std::unique_ptr<impl> _impl;
};

BSONCXX_INLINE_NAMESPACE_END
}  // namespace bsoncxx

#include <bsoncxx/config/postlude.hpp>
<|endoftext|>


<commit_before>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <string>
#include <vector>

#include "common.h"
#include "bzfio.h"
#include "version.h"
#include "TextUtils.h"
#include "commands.h"
#include "bzfsAPI.h"
#include "DirectoryNames.h"

#ifdef _WIN32
std::string extension = ".dll";
std::string globalPluginDir = ".\\plugins\\";
#else
std::string extension = ".so";
std::string globalPluginDir = "$(prefix)/lib/bzflag/";
#endif

typedef struct
{
	std::string plugin;

#ifdef _WIN32
	HINSTANCE	handle;
#else
	void*		handle;
#endif
}trPluginRecord;

std::string findPlugin ( std::string pluginName )
{
	// see if we can just open the bloody thing
	FILE	*fp = fopen(pluginName.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return pluginName;
	}

	// now try it with the standard extension
	std::string name = pluginName + extension;
	fp = fopen(name.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return name;
	}

	// check the local users plugins dir
	name = getConfigDirName(BZ_CONFIG_DIR_VERSION) + pluginName + extension;
	fp = fopen(name.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return name;
	}

	// check the global plugins dir
	name = globalPluginDir + pluginName + extension;
	fp = fopen(name.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return name;
	}

	return std::string("");
}

std::vector<trPluginRecord>	vPluginList;

void unload1Plugin ( int iPluginID );

#ifdef _WIN32
#include <windows.h>

int getPluginVersion ( HINSTANCE hLib )
{
	int (*lpProc)(void);
	lpProc = (int (__cdecl *)(void))GetProcAddress(hLib, "bz_GetVersion");
	if (lpProc)
		return lpProc();
	return 0;
}

void loadPlugin ( std::string plugin, std::string config )
{
	int (*lpProc)(const char*);

	std::string realPluginName = findPlugin(plugin);

	HINSTANCE	hLib = LoadLibrary(realPluginName.c_str());
	if (hLib)
	{
		if (getPluginVersion(hLib) < BZ_API_VERSION)
		{
			DEBUG1("Plugin:%s found but expects an older API version (%d), upgrade it\n",plugin.c_str(),getPluginVersion(hLib));
			FreeLibrary(hLib);
		}
		else
		{
			lpProc = (int (__cdecl *)(const char*))GetProcAddress(hLib, "bz_Load");
			if (lpProc)
			{
				lpProc(config.c_str());
				DEBUG1("Plugin:%s loaded\n",plugin.c_str());

				trPluginRecord pluginRecord;
				pluginRecord.handle = hLib;
				pluginRecord.plugin = plugin;
				vPluginList.push_back(pluginRecord);
			}
			else
			{
				DEBUG1("Plugin:%s found but does not contain bz_Load method\n",plugin.c_str());
				FreeLibrary(hLib);
			}
		}
	}
	else
		DEBUG1("Plugin:%s not found\n",plugin.c_str());
}

void unload1Plugin ( int iPluginID )
{
	int (*lpProc)(void);

	trPluginRecord &plugin = vPluginList[iPluginID];

	lpProc = (int (__cdecl *)(void))GetProcAddress(plugin.handle, "bz_Unload");
	if (lpProc)
		lpProc();
	else
		DEBUG1("Plugin does not contain bz_UnLoad method\n");

	FreeLibrary(plugin.handle);
	plugin.handle = NULL;
}
#else

#include <dlfcn.h>
std::vector<void*>	vLibHandles;

int getPluginVersion ( void* hLib )
{
	int (*lpProc)(void);
	*(void**) &lpProc = dlsym(hLib,"bz_GetVersion");
	if (lpProc)
		return (*lpProc)();
	return 0;
}

void loadPlugin ( std::string plugin, std::string config )
{
	int (*lpProc)(const char*);

	std::string realPluginName = findPlugin(plugin);

	void*	hLib = dlopen(realPluginName.c_str(),RTLD_LAZY);
	if (hLib)
	{
		if (getPluginVersion(hLib) < BZ_API_VERSION)
		{
			DEBUG1("Plugin:%s found but expects an older API version (%d), upgrade it\n",plugin.c_str(),getPluginVersion(hLib));
			dlclose(hLib);
		}
		else
		{
			*(void**) &lpProc = dlsym(hLib,"bz_Load");
			if (lpProc)
			{
				(*lpProc)(config.c_str());
				DEBUG1("Plugin:%s loaded\n",plugin.c_str());
				trPluginRecord pluginRecord;
				pluginRecord.handle = hLib;
				pluginRecord.plugin = plugin;
				vPluginList.push_back(pluginRecord);
			}
			else
			{
				DEBUG1("Plugin:%s found but does not contain bz_Load method, error %s\n",plugin.c_str(),dlerror());
				dlclose(hLib);
			}
		}
	}
	else
		DEBUG1("Plugin:%s not found, error %s\n",plugin.c_str(), dlerror());
}

void unload1Plugin ( int iPluginID )
{
	int (*lpProc)(void);
	trPluginRecord &plugin = vPluginList[iPluginID];

	*(void**) &lpProc = dlsym(plugin.handle, "bz_Unload");
	if (lpProc)
		(*lpProc)();
	else
		DEBUG1("Plugin does not contain bz_UnLoad method, error %s\n",dlerror());

	dlclose(plugin.handle);
	plugin.handle = NULL;
}
#endif

void unloadPlugin ( std::string plugin )
{
	// unload the first one of the name we find
	for (unsigned int i = 0; i < vPluginList.size();i++)
	{
		if ( vPluginList[i].plugin == plugin )
		{
			unload1Plugin(i);
			vPluginList.erase(vPluginList.begin()+i);
			return;
		}
	}
}

void unloadPlugins ( void )
{
	for (unsigned int i = 0; i < vPluginList.size();i++)
		unload1Plugin(i);
	vPluginList.clear();

	removeCustomSlashCommand("loadplugin");
	removeCustomSlashCommand("unloadplugin");
	removeCustomSlashCommand("listplugins");
}

std::vector<std::string> getPluginList ( void )
{
	std::vector<std::string> plugins;
	for (unsigned int i = 0; i < vPluginList.size();i++)
		plugins.push_back(vPluginList[i].plugin);

	return plugins;
}

void parseServerCommand(const char *message, int dstPlayerId);

class DynamicPluginCommands : public CustomSlashCommandHandler
{
public:
	virtual ~DynamicPluginCommands(){};
	virtual bool handle ( int playerID, std::string command, std::string message )
	{
		bz_PlayerRecord	record;

		bz_getPlayerByIndex(playerID,&record);

		if ( !record.admin )
		{
			bz_sendTextMessage(BZ_SERVER,playerID,"Permision denied: ADMIN");
			return true;
		}

		if ( !message.size() )
		{
			bz_sendTextMessage(BZ_SERVER,playerID,"Error: Command must have a plugin name");
			return true;
		}

		if ( TextUtils::tolower(command) == "loadplugin" )
		{
			std::vector<std::string> params = TextUtils::tokenize(message,std::string(","));

			std::string config;
			if ( params.size() >1)
				config = params[1];

			loadPlugin(params[0],config);

			bz_sendTextMessage(BZ_SERVER,playerID,"Plug-in loaded");
			return true;
		}

		if ( TextUtils::tolower(command) == "unloadplugin" )
		{
			unloadPlugin(message);

			bz_sendTextMessage(BZ_SERVER,playerID,"Plug-in unloaded");
			return true;
		}

		if ( TextUtils::tolower(command) == "listplugins" )
		{
			std::vector<std::string>	plugins = getPluginList();

			if (!plugins.size())
				bz_sendTextMessage(BZ_SERVER,playerID,"No Plug-ins loaded;");
			else
			{
				bz_sendTextMessage(BZ_SERVER,playerID,"Plug-isn loaded;");

				for ( unsigned int i = 0; i < plugins.size(); i++)
					bz_sendTextMessage(BZ_SERVER,playerID,plugins[i].c_str());
			}
			return true;
		}
		return true;
	}
};

DynamicPluginCommands	command;

void initPlugins ( void )
{
	registerCustomSlashCommand("loadplugin",&command);
	registerCustomSlashCommand("unloadplugin",&command);
	registerCustomSlashCommand("listplugins",&command);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>plugins need to be loaded with RTLD_GLOBAL in order for symbol resolution on further libraries to work, like, say, a python builtin<commit_after>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <string>
#include <vector>

#include "common.h"
#include "bzfio.h"
#include "version.h"
#include "TextUtils.h"
#include "commands.h"
#include "bzfsAPI.h"
#include "DirectoryNames.h"

#ifdef _WIN32
std::string extension = ".dll";
std::string globalPluginDir = ".\\plugins\\";
#else
std::string extension = ".so";
std::string globalPluginDir = "$(prefix)/lib/bzflag/";
#endif

typedef struct
{
	std::string plugin;

#ifdef _WIN32
	HINSTANCE	handle;
#else
	void*		handle;
#endif
}trPluginRecord;

std::string findPlugin ( std::string pluginName )
{
	// see if we can just open the bloody thing
	FILE	*fp = fopen(pluginName.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return pluginName;
	}

	// now try it with the standard extension
	std::string name = pluginName + extension;
	fp = fopen(name.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return name;
	}

	// check the local users plugins dir
	name = getConfigDirName(BZ_CONFIG_DIR_VERSION) + pluginName + extension;
	fp = fopen(name.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return name;
	}

	// check the global plugins dir
	name = globalPluginDir + pluginName + extension;
	fp = fopen(name.c_str(),"rb");
	if (fp)
	{
		fclose(fp);
		return name;
	}

	return std::string("");
}

std::vector<trPluginRecord>	vPluginList;

void unload1Plugin ( int iPluginID );

#ifdef _WIN32
#include <windows.h>

int getPluginVersion ( HINSTANCE hLib )
{
	int (*lpProc)(void);
	lpProc = (int (__cdecl *)(void))GetProcAddress(hLib, "bz_GetVersion");
	if (lpProc)
		return lpProc();
	return 0;
}

void loadPlugin ( std::string plugin, std::string config )
{
	int (*lpProc)(const char*);

	std::string realPluginName = findPlugin(plugin);

	HINSTANCE	hLib = LoadLibrary(realPluginName.c_str());
	if (hLib)
	{
		if (getPluginVersion(hLib) < BZ_API_VERSION)
		{
			DEBUG1("Plugin:%s found but expects an older API version (%d), upgrade it\n",plugin.c_str(),getPluginVersion(hLib));
			FreeLibrary(hLib);
		}
		else
		{
			lpProc = (int (__cdecl *)(const char*))GetProcAddress(hLib, "bz_Load");
			if (lpProc)
			{
				lpProc(config.c_str());
				DEBUG1("Plugin:%s loaded\n",plugin.c_str());

				trPluginRecord pluginRecord;
				pluginRecord.handle = hLib;
				pluginRecord.plugin = plugin;
				vPluginList.push_back(pluginRecord);
			}
			else
			{
				DEBUG1("Plugin:%s found but does not contain bz_Load method\n",plugin.c_str());
				FreeLibrary(hLib);
			}
		}
	}
	else
		DEBUG1("Plugin:%s not found\n",plugin.c_str());
}

void unload1Plugin ( int iPluginID )
{
	int (*lpProc)(void);

	trPluginRecord &plugin = vPluginList[iPluginID];

	lpProc = (int (__cdecl *)(void))GetProcAddress(plugin.handle, "bz_Unload");
	if (lpProc)
		lpProc();
	else
		DEBUG1("Plugin does not contain bz_UnLoad method\n");

	FreeLibrary(plugin.handle);
	plugin.handle = NULL;
}
#else

#include <dlfcn.h>
std::vector<void*>	vLibHandles;

int getPluginVersion ( void* hLib )
{
	int (*lpProc)(void);
	*(void**) &lpProc = dlsym(hLib,"bz_GetVersion");
	if (lpProc)
		return (*lpProc)();
	return 0;
}

void loadPlugin ( std::string plugin, std::string config )
{
	int (*lpProc)(const char*);

	std::string realPluginName = findPlugin(plugin);

	void *hLib = dlopen(realPluginName.c_str(), RTLD_LAZY | RTLD_GLOBAL);
	if (hLib)
	{
		if (getPluginVersion(hLib) < BZ_API_VERSION)
		{
			DEBUG1("Plugin:%s found but expects an older API version (%d), upgrade it\n",plugin.c_str(),getPluginVersion(hLib));
			dlclose(hLib);
		}
		else
		{
			*(void**) &lpProc = dlsym(hLib,"bz_Load");
			if (lpProc)
			{
				(*lpProc)(config.c_str());
				DEBUG1("Plugin:%s loaded\n",plugin.c_str());
				trPluginRecord pluginRecord;
				pluginRecord.handle = hLib;
				pluginRecord.plugin = plugin;
				vPluginList.push_back(pluginRecord);
			}
			else
			{
				DEBUG1("Plugin:%s found but does not contain bz_Load method, error %s\n",plugin.c_str(),dlerror());
				dlclose(hLib);
			}
		}
	}
	else
		DEBUG1("Plugin:%s not found, error %s\n",plugin.c_str(), dlerror());
}

void unload1Plugin ( int iPluginID )
{
	int (*lpProc)(void);
	trPluginRecord &plugin = vPluginList[iPluginID];

	*(void**) &lpProc = dlsym(plugin.handle, "bz_Unload");
	if (lpProc)
		(*lpProc)();
	else
		DEBUG1("Plugin does not contain bz_UnLoad method, error %s\n",dlerror());

	dlclose(plugin.handle);
	plugin.handle = NULL;
}
#endif

void unloadPlugin ( std::string plugin )
{
	// unload the first one of the name we find
	for (unsigned int i = 0; i < vPluginList.size();i++)
	{
		if ( vPluginList[i].plugin == plugin )
		{
			unload1Plugin(i);
			vPluginList.erase(vPluginList.begin()+i);
			return;
		}
	}
}

void unloadPlugins ( void )
{
	for (unsigned int i = 0; i < vPluginList.size();i++)
		unload1Plugin(i);
	vPluginList.clear();

	removeCustomSlashCommand("loadplugin");
	removeCustomSlashCommand("unloadplugin");
	removeCustomSlashCommand("listplugins");
}

std::vector<std::string> getPluginList ( void )
{
	std::vector<std::string> plugins;
	for (unsigned int i = 0; i < vPluginList.size();i++)
		plugins.push_back(vPluginList[i].plugin);

	return plugins;
}

void parseServerCommand(const char *message, int dstPlayerId);

class DynamicPluginCommands : public CustomSlashCommandHandler
{
public:
	virtual ~DynamicPluginCommands(){};
	virtual bool handle ( int playerID, std::string command, std::string message )
	{
		bz_PlayerRecord	record;

		bz_getPlayerByIndex(playerID,&record);

		if ( !record.admin )
		{
			bz_sendTextMessage(BZ_SERVER,playerID,"Permision denied: ADMIN");
			return true;
		}

		if ( !message.size() )
		{
			bz_sendTextMessage(BZ_SERVER,playerID,"Error: Command must have a plugin name");
			return true;
		}

		if ( TextUtils::tolower(command) == "loadplugin" )
		{
			std::vector<std::string> params = TextUtils::tokenize(message,std::string(","));

			std::string config;
			if ( params.size() >1)
				config = params[1];

			loadPlugin(params[0],config);

			bz_sendTextMessage(BZ_SERVER,playerID,"Plug-in loaded");
			return true;
		}

		if ( TextUtils::tolower(command) == "unloadplugin" )
		{
			unloadPlugin(message);

			bz_sendTextMessage(BZ_SERVER,playerID,"Plug-in unloaded");
			return true;
		}

		if ( TextUtils::tolower(command) == "listplugins" )
		{
			std::vector<std::string>	plugins = getPluginList();

			if (!plugins.size())
				bz_sendTextMessage(BZ_SERVER,playerID,"No Plug-ins loaded;");
			else
			{
				bz_sendTextMessage(BZ_SERVER,playerID,"Plug-isn loaded;");

				for ( unsigned int i = 0; i < plugins.size(); i++)
					bz_sendTextMessage(BZ_SERVER,playerID,plugins[i].c_str());
			}
			return true;
		}
		return true;
	}
};

DynamicPluginCommands	command;

void initPlugins ( void )
{
	registerCustomSlashCommand("loadplugin",&command);
	registerCustomSlashCommand("unloadplugin",&command);
	registerCustomSlashCommand("listplugins",&command);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>#include "ruler.hpp"
#include "measurement_utils.hpp"

#include "../platform/settings.hpp"

#include "../yg/overlay_renderer.hpp"
#include "../yg/skin.hpp"

#include "../indexer/mercator.hpp"
#include "../geometry/distance_on_sphere.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"
#include "../base/macros.hpp"

namespace
{

struct UnitValue
{
  char const * m_s;
  int m_i;
};

UnitValue g_arrFeets[] = {
  { "100 ft", 100 },
  { "200 ft", 200 },
  { "0.1 mi", 528 },
  { "0.2 mi", 528 * 2 },
  { "0.5 mi", 528 * 5 },
  { "1 mi", 5280 },
  { "2 mi", 2 * 5280 },
  { "5 mi", 5 * 5280 },
  { "10 mi", 10 * 5280 },
  { "20 mi", 20 * 5280 },
  { "50 mi", 50 * 5280 },
  { "100 mi", 100 * 5280 },
  { "200 mi", 200 * 5280 },
  { "500 mi", 500 * 5280 }
};

UnitValue g_arrYards[] = {
  { "50 yd", 50 },
  { "100 yd", 100 },
  { "200 yd", 200 },
  { "500 yd", 500 },
  { "0.5 mi", 0.5 * 1760 },
  { "1 mi", 1760 },
  { "2 mi", 2 * 1760 },
  { "5 mi", 5 * 1760 },
  { "10 mi", 10 * 1760 },
  { "20 mi", 20 * 1760 },
  { "50 mi", 50 * 1760 },
  { "100 mi", 100 * 1760 },
  { "200 mi", 200 * 1760 },
  { "500 mi", 500 * 1760 }
};

UnitValue g_arrMetres[] = {
  { "20 m", 20 },
  { "50 m", 50 },
  { "100 m", 100 },
  { "200 m", 200 },
  { "500 m", 500 },
  { "1 km", 1000 },
  { "2 km", 2000 },
  { "5 km", 5000 },
  { "10 km", 10000 },
  { "20 km", 20000 },
  { "50 km", 50000 },
  { "100 km", 100000 },
  { "200 km", 200000 },
  { "500 km", 500000 },
  { "1000 km", 1000000 }
};

  double identity(double val)
  {
    return val;
  }
}

void Ruler::setup()
{
  Settings::Units units = Settings::Metric;
  Settings::Get("Units", units);

  switch (units)
  {
  default:
    ASSERT_EQUAL ( units, Settings::Metric, () );
    m_currSystem = 0;
    m_conversionFn = &identity;
    break;

  case Settings::Foot:
    m_currSystem = 1;
    m_conversionFn = &MeasurementUtils::MetersToFeet;
    break;

  case Settings::Yard:
    m_currSystem = 2;
    m_conversionFn = &MeasurementUtils::MetersToYards;
    break;
  }

  m_isInitialized = true;
  if (m_hasPendingUpdate)
    update();
}

void Ruler::CalcMetresDiff(double v)
{
  UnitValue * arrU;
  int count;

  switch (m_currSystem)
  {
  default:
    ASSERT_EQUAL ( m_currSystem, 0, () );
    arrU = g_arrMetres;
    count = ARRAY_SIZE(g_arrMetres);
    break;

  case 1:
    arrU = g_arrFeets;
    count = ARRAY_SIZE(g_arrFeets);
    break;

  case 2:
    arrU = g_arrYards;
    count = ARRAY_SIZE(g_arrYards);
    break;
  }

  if (arrU[0].m_i > v)
  {
    m_scalerText = string("<") + arrU[0].m_s;
    m_metresDiff = m_minUnitsWidth - 1;
  }
  else if (arrU[count-1].m_i <= v)
  {
    m_scalerText = string(">") + arrU[count-1].m_s;
    m_metresDiff = m_maxUnitsWidth + 1;
  }
  else
    for (int i = 0; i < count; ++i)
    {
      if (arrU[i].m_i > v)
      {
        m_metresDiff = arrU[i].m_i / m_conversionFn(1);
        m_scalerText = arrU[i].m_s;
        break;
      }
    }
}

Ruler::Ruler(Params const & p)
  : base_t(p), m_boundRects(1), m_currSystem(0), m_isInitialized(false), m_hasPendingUpdate(false)
{
}

void Ruler::setScreen(ScreenBase const & screen)
{
  m_screen = screen;
}

ScreenBase const & Ruler::screen() const
{
  return m_screen;
}

void Ruler::setMinPxWidth(unsigned minPxWidth)
{
  m_minPxWidth = minPxWidth;
}

void Ruler::setMinUnitsWidth(double minUnitsWidth)
{
  m_minUnitsWidth = minUnitsWidth;
}

void Ruler::setMaxUnitsWidth(double maxUnitsWidth)
{
  m_maxUnitsWidth = maxUnitsWidth;
}

void Ruler::setVisualScale(double visualScale)
{
  m_visualScale = visualScale;
}

void Ruler::setFontDesc(yg::FontDesc const & fontDesc)
{
  m_fontDesc = fontDesc;
}

void Ruler::update()
{
  if (m_isInitialized)
  {
    m2::PointD glbPivot = m_screen.PtoG(pivot());

    int rulerHeight = static_cast<int>(3 * m_visualScale);
    unsigned minPxWidth = static_cast<unsigned>(m_minPxWidth * m_visualScale);

    m2::PointD pt0 = m_screen.PtoG(pivot() - m2::PointD(minPxWidth / 2, 0));
    m2::PointD pt1 = m_screen.PtoG(pivot() + m2::PointD(minPxWidth / 2, 0));

    double const distanceInMetres = ms::DistanceOnEarth(MercatorBounds::YToLat(pt0.y),
                                                  MercatorBounds::XToLon(pt0.x),
                                                  MercatorBounds::YToLat(pt1.y),
                                                  MercatorBounds::XToLon(pt1.x));

    /// converting into metres
    CalcMetresDiff(m_conversionFn(distanceInMetres));

    bool const higherThanMax = m_metresDiff > m_maxUnitsWidth;
    bool const lessThanMin = m_metresDiff < m_minUnitsWidth;

    double scalerWidthInPx = minPxWidth;

    if (!higherThanMax && !lessThanMin)
    {
      double a = ang::AngleTo(pt0, pt1);
      m2::RectD r = MercatorBounds::RectByCenterXYAndSizeInMeters(glbPivot.x,
                                                                  glbPivot.y,
                                                                  abs(cos(a) * m_metresDiff / 2),
                                                                  abs(sin(a) * m_metresDiff / 2));

      pt0 = m_screen.GtoP(m2::PointD(r.minX(), r.minY()));
      pt1 = m_screen.GtoP(m2::PointD(r.maxX(), r.maxY()));

      scalerWidthInPx = pt0.Length(pt1);
      scalerWidthInPx = abs(my::rounds(scalerWidthInPx));
    }

    m2::PointD scalerOrg = pivot() + m2::PointD(-scalerWidthInPx / 2, rulerHeight / 2);

    if (position() & yg::EPosLeft)
      scalerOrg.x -= scalerWidthInPx / 2;

    if (position() & yg::EPosRight)
      scalerOrg.x += scalerWidthInPx / 2;

    if (position() & yg::EPosAbove)
      scalerOrg.y -= rulerHeight / 2;

    if (position() & yg::EPosUnder)
      scalerOrg.y += rulerHeight / 2;

    m_path.clear();
    m_path.push_back(scalerOrg + m2::PointD(0, -rulerHeight));
    m_path.push_back(scalerOrg);
    m_path.push_back(scalerOrg + m2::PointD(scalerWidthInPx, 0));
    m_path.push_back(m_path[2] + m2::PointD(0, -rulerHeight));

    /// calculating bound rect

    m_boundRect = m2::RectD(m_path[0], m_path[0]);
    m_boundRect.Add(m_path[1]);
    m_boundRect.Add(m_path[2]);
    m_boundRect.Add(m_path[3]);
  }
  else
    m_hasPendingUpdate = true;
}

vector<m2::AnyRectD> const & Ruler::boundRects() const
{
  m_boundRects[0] = m2::AnyRectD(m_boundRect);
  return m_boundRects;
}

void Ruler::draw(yg::gl::OverlayRenderer * s, math::Matrix<double, 3, 3> const & m) const
{
  if (m_isInitialized)
  {
//    s->drawPath(
//        &m_path[0], m_path.size(), 0,
//          s->skin()->mapPenInfo(yg::PenInfo(m_fontDesc.m_color, 2 * m_visualScale, 0, 0, 0)),
//        depth() - 3);

    s->drawPath(
        &m_path[0], m_path.size(), 0,
          s->skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 0x99), 1 * m_visualScale, 0, 0, 0)),
        depth() - 2);

    if (position() & yg::EPosLeft)
      s->drawText(m_fontDesc,
                  m_path[2] + m2::PointD(-1, -3),
                  yg::EPosAboveLeft,
                  m_scalerText,
                  depth(),
                  false);
    else
      if (position() & yg::EPosRight)
        s->drawText(m_fontDesc,
                    m_path[1] + m2::PointD(1, -3),
                    yg::EPosAboveRight,
                    m_scalerText,
                    depth(),
                    false);
      else
        s->drawText(m_fontDesc,
                    (m_path[1] + m_path[2]) * 0.5 + m2::PointD(0, -3),
                    yg::EPosAbove,
                    m_scalerText,
                    depth(),
                    false);
  }
}

int Ruler::visualRank() const
{
  return 0;
}

yg::OverlayElement * Ruler::clone(math::Matrix<double, 3, 3> const & m) const
{
  return new Ruler(*this);
}

<commit_msg>Fix ruler intersections with "> 1000" text.<commit_after>#include "ruler.hpp"
#include "measurement_utils.hpp"

#include "../platform/settings.hpp"

#include "../yg/overlay_renderer.hpp"
#include "../yg/skin.hpp"

#include "../indexer/mercator.hpp"
#include "../geometry/distance_on_sphere.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"
#include "../base/macros.hpp"

namespace
{

struct UnitValue
{
  char const * m_s;
  int m_i;
};

UnitValue g_arrFeets[] = {
  { "100 ft", 100 },
  { "200 ft", 200 },
  { "0.1 mi", 528 },
  { "0.2 mi", 528 * 2 },
  { "0.5 mi", 528 * 5 },
  { "1 mi", 5280 },
  { "2 mi", 2 * 5280 },
  { "5 mi", 5 * 5280 },
  { "10 mi", 10 * 5280 },
  { "20 mi", 20 * 5280 },
  { "50 mi", 50 * 5280 },
  { "100 mi", 100 * 5280 },
  { "200 mi", 200 * 5280 },
  { "500 mi", 500 * 5280 }
};

UnitValue g_arrYards[] = {
  { "50 yd", 50 },
  { "100 yd", 100 },
  { "200 yd", 200 },
  { "500 yd", 500 },
  { "0.5 mi", 0.5 * 1760 },
  { "1 mi", 1760 },
  { "2 mi", 2 * 1760 },
  { "5 mi", 5 * 1760 },
  { "10 mi", 10 * 1760 },
  { "20 mi", 20 * 1760 },
  { "50 mi", 50 * 1760 },
  { "100 mi", 100 * 1760 },
  { "200 mi", 200 * 1760 },
  { "500 mi", 500 * 1760 }
};

UnitValue g_arrMetres[] = {
  { "20 m", 20 },
  { "50 m", 50 },
  { "100 m", 100 },
  { "200 m", 200 },
  { "500 m", 500 },
  { "1 km", 1000 },
  { "2 km", 2000 },
  { "5 km", 5000 },
  { "10 km", 10000 },
  { "20 km", 20000 },
  { "50 km", 50000 },
  { "100 km", 100000 },
  { "200 km", 200000 },
  { "500 km", 500000 },
  { "1000 km", 1000000 }
};

  double identity(double val)
  {
    return val;
  }
}

void Ruler::setup()
{
  Settings::Units units = Settings::Metric;
  Settings::Get("Units", units);

  switch (units)
  {
  default:
    ASSERT_EQUAL ( units, Settings::Metric, () );
    m_currSystem = 0;
    m_conversionFn = &identity;
    break;

  case Settings::Foot:
    m_currSystem = 1;
    m_conversionFn = &MeasurementUtils::MetersToFeet;
    break;

  case Settings::Yard:
    m_currSystem = 2;
    m_conversionFn = &MeasurementUtils::MetersToYards;
    break;
  }

  m_isInitialized = true;
  if (m_hasPendingUpdate)
    update();
}

void Ruler::CalcMetresDiff(double v)
{
  UnitValue * arrU;
  int count;

  switch (m_currSystem)
  {
  default:
    ASSERT_EQUAL ( m_currSystem, 0, () );
    arrU = g_arrMetres;
    count = ARRAY_SIZE(g_arrMetres);
    break;

  case 1:
    arrU = g_arrFeets;
    count = ARRAY_SIZE(g_arrFeets);
    break;

  case 2:
    arrU = g_arrYards;
    count = ARRAY_SIZE(g_arrYards);
    break;
  }

  if (arrU[0].m_i > v)
  {
    m_scalerText = string("<") + arrU[0].m_s;
    m_metresDiff = m_minUnitsWidth - 1;
  }
  else if (arrU[count-1].m_i <= v)
  {
    m_scalerText = string(">") + arrU[count-1].m_s;
    m_metresDiff = m_maxUnitsWidth + 1;
  }
  else
    for (int i = 0; i < count; ++i)
    {
      if (arrU[i].m_i > v)
      {
        m_metresDiff = arrU[i].m_i / m_conversionFn(1);
        m_scalerText = arrU[i].m_s;
        break;
      }
    }
}

Ruler::Ruler(Params const & p)
  : base_t(p), m_boundRects(1), m_currSystem(0), m_isInitialized(false), m_hasPendingUpdate(false)
{
}

void Ruler::setScreen(ScreenBase const & screen)
{
  m_screen = screen;
}

ScreenBase const & Ruler::screen() const
{
  return m_screen;
}

void Ruler::setMinPxWidth(unsigned minPxWidth)
{
  m_minPxWidth = minPxWidth;
}

void Ruler::setMinUnitsWidth(double minUnitsWidth)
{
  m_minUnitsWidth = minUnitsWidth;
}

void Ruler::setMaxUnitsWidth(double maxUnitsWidth)
{
  m_maxUnitsWidth = maxUnitsWidth;
}

void Ruler::setVisualScale(double visualScale)
{
  m_visualScale = visualScale;
}

void Ruler::setFontDesc(yg::FontDesc const & fontDesc)
{
  m_fontDesc = fontDesc;
}

void Ruler::update()
{
  if (m_isInitialized)
  {
    m2::PointD glbPivot = m_screen.PtoG(pivot());

    int rulerHeight = static_cast<int>(3 * m_visualScale);
    unsigned minPxWidth = static_cast<unsigned>(m_minPxWidth * m_visualScale);

    m2::PointD pt0 = m_screen.PtoG(pivot() - m2::PointD(minPxWidth / 2, 0));
    m2::PointD pt1 = m_screen.PtoG(pivot() + m2::PointD(minPxWidth / 2, 0));

    double const distanceInMetres = ms::DistanceOnEarth(MercatorBounds::YToLat(pt0.y),
                                                  MercatorBounds::XToLon(pt0.x),
                                                  MercatorBounds::YToLat(pt1.y),
                                                  MercatorBounds::XToLon(pt1.x));

    /// converting into metres
    CalcMetresDiff(m_conversionFn(distanceInMetres));

    bool const higherThanMax = m_metresDiff > m_maxUnitsWidth;
    bool const lessThanMin = m_metresDiff < m_minUnitsWidth;

    double scalerWidthInPx = minPxWidth;

    if (higherThanMax)
    {
      scalerWidthInPx = minPxWidth * 3 / 2;
    }
    else if (!lessThanMin)
    {
      double a = ang::AngleTo(pt0, pt1);
      m2::RectD r = MercatorBounds::RectByCenterXYAndSizeInMeters(glbPivot.x,
                                                                  glbPivot.y,
                                                                  abs(cos(a) * m_metresDiff / 2),
                                                                  abs(sin(a) * m_metresDiff / 2));

      pt0 = m_screen.GtoP(m2::PointD(r.minX(), r.minY()));
      pt1 = m_screen.GtoP(m2::PointD(r.maxX(), r.maxY()));

      scalerWidthInPx = pt0.Length(pt1);
      scalerWidthInPx = abs(my::rounds(scalerWidthInPx));
    }

    m2::PointD scalerOrg = pivot() + m2::PointD(-scalerWidthInPx / 2, rulerHeight / 2);

    if (position() & yg::EPosLeft)
      scalerOrg.x -= scalerWidthInPx / 2;

    if (position() & yg::EPosRight)
      scalerOrg.x += scalerWidthInPx / 2;

    if (position() & yg::EPosAbove)
      scalerOrg.y -= rulerHeight / 2;

    if (position() & yg::EPosUnder)
      scalerOrg.y += rulerHeight / 2;

    m_path.clear();
    m_path.push_back(scalerOrg + m2::PointD(0, -rulerHeight));
    m_path.push_back(scalerOrg);
    m_path.push_back(scalerOrg + m2::PointD(scalerWidthInPx, 0));
    m_path.push_back(m_path[2] + m2::PointD(0, -rulerHeight));

    /// calculating bound rect

    m_boundRect = m2::RectD(m_path[0], m_path[0]);
    m_boundRect.Add(m_path[1]);
    m_boundRect.Add(m_path[2]);
    m_boundRect.Add(m_path[3]);
  }
  else
    m_hasPendingUpdate = true;
}

vector<m2::AnyRectD> const & Ruler::boundRects() const
{
  m_boundRects[0] = m2::AnyRectD(m_boundRect);
  return m_boundRects;
}

void Ruler::draw(yg::gl::OverlayRenderer * s, math::Matrix<double, 3, 3> const & m) const
{
  if (m_isInitialized)
  {
//    s->drawPath(
//        &m_path[0], m_path.size(), 0,
//          s->skin()->mapPenInfo(yg::PenInfo(m_fontDesc.m_color, 2 * m_visualScale, 0, 0, 0)),
//        depth() - 3);

    s->drawPath(
        &m_path[0], m_path.size(), 0,
          s->skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 0x99), 1 * m_visualScale, 0, 0, 0)),
        depth() - 2);

    if (position() & yg::EPosLeft)
      s->drawText(m_fontDesc,
                  m_path[2] + m2::PointD(-1, -3),
                  yg::EPosAboveLeft,
                  m_scalerText,
                  depth(),
                  false);
    else
      if (position() & yg::EPosRight)
        s->drawText(m_fontDesc,
                    m_path[1] + m2::PointD(1, -3),
                    yg::EPosAboveRight,
                    m_scalerText,
                    depth(),
                    false);
      else
        s->drawText(m_fontDesc,
                    (m_path[1] + m_path[2]) * 0.5 + m2::PointD(0, -3),
                    yg::EPosAbove,
                    m_scalerText,
                    depth(),
                    false);
  }
}

int Ruler::visualRank() const
{
  return 0;
}

yg::OverlayElement * Ruler::clone(math::Matrix<double, 3, 3> const & m) const
{
  return new Ruler(*this);
}

<|endoftext|>


<commit_before>#ifndef ENTT_CORE_HASHED_STRING_HPP
#define ENTT_CORE_HASHED_STRING_HPP

#include <cstddef>
#include <cstdint>
#include "../config/config.h"
#include "fwd.hpp"

namespace entt {

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

template<typename>
struct fnv1a_traits;

template<>
struct fnv1a_traits<std::uint32_t> {
    using type = std::uint32_t;
    static constexpr std::uint32_t offset = 2166136261;
    static constexpr std::uint32_t prime = 16777619;
};

template<>
struct fnv1a_traits<std::uint64_t> {
    using type = std::uint64_t;
    static constexpr std::uint64_t offset = 14695981039346656037ull;
    static constexpr std::uint64_t prime = 1099511628211ull;
};

template<typename Char>
struct basic_hashed_string {
    using value_type = Char;
    using size_type = std::size_t;
    using hash_type = id_type;

    const value_type *repr;
    size_type length;
    hash_type hash;
};

} // namespace internal

/**
 * Internal details not to be documented.
 * @endcond
 */

/**
 * @brief Zero overhead unique identifier.
 *
 * A hashed string is a compile-time tool that allows users to use
 * human-readable identifers in the codebase while using their numeric
 * counterparts at runtime.

 * Because of that, a hashed string can also be used in constant expressions if
 * required.
 *
 * @warning
 * This class doesn't take ownership of user-supplied strings nor does it make a
 * copy of them.
 *
 * @tparam Char Character type.
 */
template<typename Char>
class basic_hashed_string: internal::basic_hashed_string<Char> {
    using base_type = internal::basic_hashed_string<Char>;
    using hs_traits = internal::fnv1a_traits<id_type>;

    struct const_wrapper {
        // non-explicit constructor on purpose
        constexpr const_wrapper(const Char *str) ENTT_NOEXCEPT: repr{str} {}
        const Char *repr;
    };

    // Fowler–Noll–Vo hash function v. 1a - the good
    [[nodiscard]] static constexpr auto helper(const Char *str) ENTT_NOEXCEPT {
        base_type base{str, 0u, hs_traits::offset};

        for(; str[base.length]; ++base.length) {
            base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
        }

        return base;
    }

    // Fowler–Noll–Vo hash function v. 1a - the good
    [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) ENTT_NOEXCEPT {
        base_type base{str, len, hs_traits::offset};

        for(size_type pos{}; pos < len; ++pos) {
            base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
        }

        return base;
    }

public:
    /*! @brief Character type. */
    using value_type = typename basic_hashed_string::value_type;
    /*! @brief Unsigned integer type. */
    using size_type = typename basic_hashed_string::size_type;
    /*! @brief Unsigned integer type. */
    using hash_type = typename basic_hashed_string::hash_type;

    /**
     * @brief Returns directly the numeric representation of a string view.
     * @param str Human-readable identifer.
     * @param len Length of the string to hash.
     * @return The numeric representation of the string.
     */
    [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) ENTT_NOEXCEPT {
        return basic_hashed_string{str, len};
    }

    /**
     * @brief Returns directly the numeric representation of a string.
     * @tparam N Number of characters of the identifier.
     * @param str Human-readable identifer.
     * @return The numeric representation of the string.
     */
    template<std::size_t N>
    [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_NOEXCEPT {
        return basic_hashed_string{str};
    }

    /**
     * @brief Returns directly the numeric representation of a string.
     * @param wrapper Helps achieving the purpose by relying on overloading.
     * @return The numeric representation of the string.
     */
    [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
        return basic_hashed_string{wrapper};
    }

    /*! @brief Constructs an empty hashed string. */
    constexpr basic_hashed_string() ENTT_NOEXCEPT
        : base_type{} {}

    /**
     * @brief Constructs a hashed string from a string view.
     * @param str Human-readable identifer.
     * @param len Length of the string to hash.
     */
    constexpr basic_hashed_string(const value_type *str, const size_type len) ENTT_NOEXCEPT
        : base_type{helper(str, len)} {}

    /**
     * @brief Constructs a hashed string from an array of const characters.
     * @tparam N Number of characters of the identifier.
     * @param str Human-readable identifer.
     */
    template<std::size_t N>
    constexpr basic_hashed_string(const value_type (&str)[N]) ENTT_NOEXCEPT
        : base_type{helper(str)} {}

    /**
     * @brief Explicit constructor on purpose to avoid constructing a hashed
     * string directly from a `const value_type *`.
     *
     * @warning
     * The lifetime of the string is not extended nor is it copied.
     *
     * @param wrapper Helps achieving the purpose by relying on overloading.
     */
    explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
        : base_type{helper(wrapper.repr)} {}

    /**
     * @brief Returns the size a hashed string.
     * @return The size of the hashed string.
     */
    [[nodiscard]] constexpr size_type size() const ENTT_NOEXCEPT {
        return base_type::length;
    }

    /**
     * @brief Returns the human-readable representation of a hashed string.
     * @return The string used to initialize the hashed string.
     */
    [[nodiscard]] constexpr const value_type *data() const ENTT_NOEXCEPT {
        return base_type::repr;
    }

    /**
     * @brief Returns the numeric representation of a hashed string.
     * @return The numeric representation of the hashed string.
     */
    [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
        return base_type::hash;
    }

    /*! @copydoc data */
    [[nodiscard]] constexpr operator const value_type *() const ENTT_NOEXCEPT {
        return data();
    }

    /**
     * @brief Returns the numeric representation of a hashed string.
     * @return The numeric representation of the hashed string.
     */
    [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT {
        return value();
    }
};

/**
 * @brief Deduction guide.
 * @tparam Char Character type.
 * @param str Human-readable identifer.
 * @param len Length of the string to hash.
 */
template<typename Char>
basic_hashed_string(const Char *str, const std::size_t len) -> basic_hashed_string<Char>;

/**
 * @brief Deduction guide.
 * @tparam Char Character type.
 * @tparam N Number of characters of the identifier.
 * @param str Human-readable identifer.
 */
template<typename Char, std::size_t N>
basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the two hashed strings are identical, false otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return lhs.value() == rhs.value();
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the two hashed strings differ, false otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return !(lhs == rhs);
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the first element is less than the second, false otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return lhs.value() < rhs.value();
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the first element is less than or equal to the second, false
 * otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return !(rhs < lhs);
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the first element is greater than the second, false
 * otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return rhs < lhs;
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the first element is greater than or equal to the second,
 * false otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return !(lhs < rhs);
}

/*! @brief Aliases for common character types. */
using hashed_string = basic_hashed_string<char>;

/*! @brief Aliases for common character types. */
using hashed_wstring = basic_hashed_string<wchar_t>;

inline namespace literals {

/**
 * @brief User defined literal for hashed strings.
 * @param str The literal without its suffix.
 * @return A properly initialized hashed string.
 */
[[nodiscard]] constexpr entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
    return entt::hashed_string{str};
}

/**
 * @brief User defined literal for hashed wstrings.
 * @param str The literal without its suffix.
 * @return A properly initialized hashed wstring.
 */
[[nodiscard]] constexpr entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
    return entt::hashed_wstring{str};
}

} // namespace literals

} // namespace entt

#endif
<commit_msg>hashed_string: I managed to crash clang but I remain humble and try to help it :)<commit_after>#ifndef ENTT_CORE_HASHED_STRING_HPP
#define ENTT_CORE_HASHED_STRING_HPP

#include <cstddef>
#include <cstdint>
#include "../config/config.h"
#include "fwd.hpp"

namespace entt {

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

template<typename>
struct fnv1a_traits;

template<>
struct fnv1a_traits<std::uint32_t> {
    using type = std::uint32_t;
    static constexpr std::uint32_t offset = 2166136261;
    static constexpr std::uint32_t prime = 16777619;
};

template<>
struct fnv1a_traits<std::uint64_t> {
    using type = std::uint64_t;
    static constexpr std::uint64_t offset = 14695981039346656037ull;
    static constexpr std::uint64_t prime = 1099511628211ull;
};

template<typename Char>
struct basic_hashed_string {
    using value_type = Char;
    using size_type = std::size_t;
    using hash_type = id_type;

    const value_type *repr;
    size_type length;
    hash_type hash;
};

} // namespace internal

/**
 * Internal details not to be documented.
 * @endcond
 */

/**
 * @brief Zero overhead unique identifier.
 *
 * A hashed string is a compile-time tool that allows users to use
 * human-readable identifers in the codebase while using their numeric
 * counterparts at runtime.

 * Because of that, a hashed string can also be used in constant expressions if
 * required.
 *
 * @warning
 * This class doesn't take ownership of user-supplied strings nor does it make a
 * copy of them.
 *
 * @tparam Char Character type.
 */
template<typename Char>
class basic_hashed_string: internal::basic_hashed_string<Char> {
    using base_type = internal::basic_hashed_string<Char>;
    using hs_traits = internal::fnv1a_traits<id_type>;

    struct const_wrapper {
        // non-explicit constructor on purpose
        constexpr const_wrapper(const Char *str) ENTT_NOEXCEPT: repr{str} {}
        const Char *repr;
    };

    // Fowler–Noll–Vo hash function v. 1a - the good
    [[nodiscard]] static constexpr auto helper(const Char *str) ENTT_NOEXCEPT {
        base_type base{str, 0u, hs_traits::offset};

        for(; str[base.length]; ++base.length) {
            base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
        }

        return base;
    }

    // Fowler–Noll–Vo hash function v. 1a - the good
    [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) ENTT_NOEXCEPT {
        base_type base{str, len, hs_traits::offset};

        for(size_type pos{}; pos < len; ++pos) {
            base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
        }

        return base;
    }

public:
    /*! @brief Character type. */
    using value_type = typename base_type::value_type;
    /*! @brief Unsigned integer type. */
    using size_type = typename base_type::size_type;
    /*! @brief Unsigned integer type. */
    using hash_type = typename base_type::hash_type;

    /**
     * @brief Returns directly the numeric representation of a string view.
     * @param str Human-readable identifer.
     * @param len Length of the string to hash.
     * @return The numeric representation of the string.
     */
    [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) ENTT_NOEXCEPT {
        return basic_hashed_string{str, len};
    }

    /**
     * @brief Returns directly the numeric representation of a string.
     * @tparam N Number of characters of the identifier.
     * @param str Human-readable identifer.
     * @return The numeric representation of the string.
     */
    template<std::size_t N>
    [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_NOEXCEPT {
        return basic_hashed_string{str};
    }

    /**
     * @brief Returns directly the numeric representation of a string.
     * @param wrapper Helps achieving the purpose by relying on overloading.
     * @return The numeric representation of the string.
     */
    [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
        return basic_hashed_string{wrapper};
    }

    /*! @brief Constructs an empty hashed string. */
    constexpr basic_hashed_string() ENTT_NOEXCEPT
        : base_type{} {}

    /**
     * @brief Constructs a hashed string from a string view.
     * @param str Human-readable identifer.
     * @param len Length of the string to hash.
     */
    constexpr basic_hashed_string(const value_type *str, const size_type len) ENTT_NOEXCEPT
        : base_type{helper(str, len)} {}

    /**
     * @brief Constructs a hashed string from an array of const characters.
     * @tparam N Number of characters of the identifier.
     * @param str Human-readable identifer.
     */
    template<std::size_t N>
    constexpr basic_hashed_string(const value_type (&str)[N]) ENTT_NOEXCEPT
        : base_type{helper(str)} {}

    /**
     * @brief Explicit constructor on purpose to avoid constructing a hashed
     * string directly from a `const value_type *`.
     *
     * @warning
     * The lifetime of the string is not extended nor is it copied.
     *
     * @param wrapper Helps achieving the purpose by relying on overloading.
     */
    explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
        : base_type{helper(wrapper.repr)} {}

    /**
     * @brief Returns the size a hashed string.
     * @return The size of the hashed string.
     */
    [[nodiscard]] constexpr size_type size() const ENTT_NOEXCEPT {
        return base_type::length;
    }

    /**
     * @brief Returns the human-readable representation of a hashed string.
     * @return The string used to initialize the hashed string.
     */
    [[nodiscard]] constexpr const value_type *data() const ENTT_NOEXCEPT {
        return base_type::repr;
    }

    /**
     * @brief Returns the numeric representation of a hashed string.
     * @return The numeric representation of the hashed string.
     */
    [[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
        return base_type::hash;
    }

    /*! @copydoc data */
    [[nodiscard]] constexpr operator const value_type *() const ENTT_NOEXCEPT {
        return data();
    }

    /**
     * @brief Returns the numeric representation of a hashed string.
     * @return The numeric representation of the hashed string.
     */
    [[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT {
        return value();
    }
};

/**
 * @brief Deduction guide.
 * @tparam Char Character type.
 * @param str Human-readable identifer.
 * @param len Length of the string to hash.
 */
template<typename Char>
basic_hashed_string(const Char *str, const std::size_t len) -> basic_hashed_string<Char>;

/**
 * @brief Deduction guide.
 * @tparam Char Character type.
 * @tparam N Number of characters of the identifier.
 * @param str Human-readable identifer.
 */
template<typename Char, std::size_t N>
basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the two hashed strings are identical, false otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return lhs.value() == rhs.value();
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the two hashed strings differ, false otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return !(lhs == rhs);
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the first element is less than the second, false otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return lhs.value() < rhs.value();
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the first element is less than or equal to the second, false
 * otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return !(rhs < lhs);
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the first element is greater than the second, false
 * otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return rhs < lhs;
}

/**
 * @brief Compares two hashed strings.
 * @tparam Char Character type.
 * @param lhs A valid hashed string.
 * @param rhs A valid hashed string.
 * @return True if the first element is greater than or equal to the second,
 * false otherwise.
 */
template<typename Char>
[[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
    return !(lhs < rhs);
}

/*! @brief Aliases for common character types. */
using hashed_string = basic_hashed_string<char>;

/*! @brief Aliases for common character types. */
using hashed_wstring = basic_hashed_string<wchar_t>;

inline namespace literals {

/**
 * @brief User defined literal for hashed strings.
 * @param str The literal without its suffix.
 * @return A properly initialized hashed string.
 */
[[nodiscard]] constexpr entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
    return entt::hashed_string{str};
}

/**
 * @brief User defined literal for hashed wstrings.
 * @param str The literal without its suffix.
 * @return A properly initialized hashed wstring.
 */
[[nodiscard]] constexpr entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
    return entt::hashed_wstring{str};
}

} // namespace literals

} // namespace entt

#endif
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "ElectromagneticsApp.h"
#include "Moose.h"
#include "AppFactory.h"
#include "MooseSyntax.h"

InputParameters
ElectromagneticsApp::validParams()
{
  InputParameters params = MooseApp::validParams();

  return params;
}

registerKnownLabel("ElectromagneticsApp");

ElectromagneticsApp::ElectromagneticsApp(InputParameters parameters) : MooseApp(parameters)
{
  ElectromagneticsApp::registerAll(_factory, _action_factory, _syntax);
}

ElectromagneticsApp::~ElectromagneticsApp() {}

void
ElectromagneticsApp::registerAll(Factory & f, ActionFactory & af, Syntax & /*s*/)
{
  Registry::registerObjectsTo(f, {"ElectromagneticsApp"});
  Registry::registerActionsTo(af, {"ElectromagneticsApp"});

  /* register custom execute flags, action syntax, etc. here */
}

void
ElectromagneticsApp::registerApps()
{
  registerApp(ElectromagneticsApp);
}

void
ElectromagneticsApp::registerObjects(Factory & factory)
{
  mooseDeprecated("use registerAll instead of registerObjects");
  Registry::registerObjectsTo(factory, {"ElectromagneticsApp"});
}

void
ElectromagneticsApp::associateSyntax(Syntax & /*syntax*/, ActionFactory & action_factory)
{
  mooseDeprecated("use registerAll instead of associateSyntax");
  Registry::registerActionsTo(action_factory, {"ElectromagneticsApp"});
}

void
ElectromagneticsApp::registerExecFlags(Factory & /*factory*/)
{
  mooseDeprecated("use registerAll instead of registerExecFlags");
}

/***************************************************************************************************
 *********************** Dynamic Library Entry Points - DO NOT MODIFY ******************************
 **************************************************************************************************/
extern "C" void
ElectromagneticsApp__registerAll(Factory & f, ActionFactory & af, Syntax & s)
{
  ElectromagneticsApp::registerAll(f, af, s);
}
extern "C" void
ElectromagneticsApp__registerApps()
{
  ElectromagneticsApp::registerApps();
}
<commit_msg>Use new material output settings in electromagnetics module<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "ElectromagneticsApp.h"
#include "Moose.h"
#include "AppFactory.h"
#include "MooseSyntax.h"

InputParameters
ElectromagneticsApp::validParams()
{
  InputParameters params = MooseApp::validParams();

  params.set<bool>("use_legacy_material_output") = false;

  return params;
}

registerKnownLabel("ElectromagneticsApp");

ElectromagneticsApp::ElectromagneticsApp(InputParameters parameters) : MooseApp(parameters)
{
  ElectromagneticsApp::registerAll(_factory, _action_factory, _syntax);
}

ElectromagneticsApp::~ElectromagneticsApp() {}

void
ElectromagneticsApp::registerAll(Factory & f, ActionFactory & af, Syntax & /*s*/)
{
  Registry::registerObjectsTo(f, {"ElectromagneticsApp"});
  Registry::registerActionsTo(af, {"ElectromagneticsApp"});

  /* register custom execute flags, action syntax, etc. here */
}

void
ElectromagneticsApp::registerApps()
{
  registerApp(ElectromagneticsApp);
}

void
ElectromagneticsApp::registerObjects(Factory & factory)
{
  mooseDeprecated("use registerAll instead of registerObjects");
  Registry::registerObjectsTo(factory, {"ElectromagneticsApp"});
}

void
ElectromagneticsApp::associateSyntax(Syntax & /*syntax*/, ActionFactory & action_factory)
{
  mooseDeprecated("use registerAll instead of associateSyntax");
  Registry::registerActionsTo(action_factory, {"ElectromagneticsApp"});
}

void
ElectromagneticsApp::registerExecFlags(Factory & /*factory*/)
{
  mooseDeprecated("use registerAll instead of registerExecFlags");
}

/***************************************************************************************************
 *********************** Dynamic Library Entry Points - DO NOT MODIFY ******************************
 **************************************************************************************************/
extern "C" void
ElectromagneticsApp__registerAll(Factory & f, ActionFactory & af, Syntax & s)
{
  ElectromagneticsApp::registerAll(f, af, s);
}
extern "C" void
ElectromagneticsApp__registerApps()
{
  ElectromagneticsApp::registerApps();
}
<|endoftext|>