<commit_before>#include "UtilTestFixture.h"

class InstrumentedAllocatorsTest : public UtilTestBase {
protected:
    InstrumentedAllocatorsTest() : UtilTestBase(FALSE) {
        SRAND(12345);
    }

    const SIZE_T TestAllocSize = 1000;
    const UINT32 TestIterationCount = 10000;
};

TEST_F(InstrumentedAllocatorsTest, set_reset_basic_test)
{
    memAlloc storedMemAlloc = globalMemAlloc;
    memAlignAlloc storedMemAlignAlloc = globalMemAlignAlloc;
    memCalloc storedMemCalloc = globalMemCalloc;
    memFree storedMemFree = globalMemFree;
    memRealloc storedMemRealloc = globalMemRealloc;
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

#ifndef INSTRUMENTED_ALLOCATORS
    SET_INSTRUMENTED_ALLOCATORS();

    // Check that we have not set anything actually
    EXPECT_EQ(storedMemAlloc, globalMemAlloc);
    EXPECT_EQ(storedMemAlignAlloc, globalMemAlignAlloc);
    EXPECT_EQ(storedMemCalloc, globalMemCalloc);
    EXPECT_EQ(storedMemFree, globalMemFree);
    EXPECT_EQ(storedMemRealloc, globalMemRealloc);

    RESET_INSTRUMENTED_ALLOCATORS();

    EXPECT_EQ(storedMemAlloc, globalMemAlloc);
    EXPECT_EQ(storedMemAlignAlloc, globalMemAlignAlloc);
    EXPECT_EQ(storedMemCalloc, globalMemCalloc);
    EXPECT_EQ(storedMemFree, globalMemFree);
    EXPECT_EQ(storedMemRealloc, globalMemRealloc);
#else
    SET_INSTRUMENTED_ALLOCATORS();

    // Check that the allocators have changed
    EXPECT_NE(storedMemAlloc, globalMemAlloc);
    EXPECT_NE(storedMemAlignAlloc, globalMemAlignAlloc);
    EXPECT_NE(storedMemCalloc, globalMemCalloc);
    EXPECT_NE(storedMemFree, globalMemFree);
    EXPECT_NE(storedMemRealloc, globalMemRealloc);

    RESET_INSTRUMENTED_ALLOCATORS();

    // Reset back to the stored ones
    EXPECT_EQ(storedMemAlloc, globalMemAlloc);
    EXPECT_EQ(storedMemAlignAlloc, globalMemAlignAlloc);
    EXPECT_EQ(storedMemCalloc, globalMemCalloc);
    EXPECT_EQ(storedMemFree, globalMemFree);
    EXPECT_EQ(storedMemRealloc, globalMemRealloc);
#endif

    // Force setting/resetting couple of times

    for (int i = 0; i < 100; i++) {
        EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());

        // Check that the allocators have changed
        EXPECT_NE(storedMemAlloc, globalMemAlloc);
        EXPECT_NE(storedMemAlignAlloc, globalMemAlignAlloc);
        EXPECT_NE(storedMemCalloc, globalMemCalloc);
        EXPECT_NE(storedMemFree, globalMemFree);
        EXPECT_NE(storedMemRealloc, globalMemRealloc);

        EXPECT_EQ(STATUS_SUCCESS, resetInstrumentedAllocators());

        // Reset back to the stored ones
        EXPECT_EQ(storedMemAlloc, globalMemAlloc);
        EXPECT_EQ(storedMemAlignAlloc, globalMemAlignAlloc);
        EXPECT_EQ(storedMemCalloc, globalMemCalloc);
        EXPECT_EQ(storedMemFree, globalMemFree);
        EXPECT_EQ(storedMemRealloc, globalMemRealloc);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_malloc)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize, getInstrumentedTotalAllocationSize());

    // Free the allocation as we are tripping ASAN
    MEMFREE((PSIZE_T) pAlloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_alignalloc)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALIGNALLOC(TestAllocSize, 16);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pAlloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_calloc)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMCALLOC(10, TestAllocSize);
    MEMCHK(pAlloc, 0x00, 10 * TestAllocSize);
    MEMSET(pAlloc, 0xFF, 10 * TestAllocSize);
    MEMCHK(pAlloc, 0xff, 10 * TestAllocSize);
    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + 10 * TestAllocSize, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pAlloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_realloc_larger_small_diff)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    PVOID pRealloc = MEMREALLOC(pAlloc, TestAllocSize + 1);
    MEMSET(pRealloc, 0xFF, TestAllocSize + 1);
    MEMCHK(pRealloc, 0xff, TestAllocSize + 1);

    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize + 1, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pRealloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_realloc_larger_large_diff)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    PVOID pRealloc = MEMREALLOC(pAlloc, 10 * TestAllocSize);
    MEMSET(pRealloc, 0xFF, 10 * TestAllocSize);
    MEMCHK(pRealloc, 0xff, 10 * TestAllocSize);

    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + 10 * TestAllocSize, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pRealloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_realloc_smaller_small_diff)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    PVOID pRealloc = MEMREALLOC(pAlloc, TestAllocSize - 1);
    MEMSET(pRealloc, 0xFF, TestAllocSize - 1);
    MEMCHK(pRealloc, 0xff, TestAllocSize - 1);

    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize - 1, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pRealloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_realloc_smaller_large_diff)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    PVOID pRealloc = MEMREALLOC(pAlloc, TestAllocSize / 10);
    MEMSET(pRealloc, 0xFF, TestAllocSize / 10);
    MEMCHK(pRealloc, 0xff, TestAllocSize / 10);

    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize / 10, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pRealloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, random_alloc_free)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

    for (UINT32 i = 0; i < TestIterationCount; i++) {
        SIZE_T size = RAND() % TestAllocSize + 100;
        PVOID pAlloc = MEMALLOC(size);
        // Touch beginning, mid and end for no no-op
        *(PBYTE) pAlloc = (BYTE) RAND();
        *((PBYTE) pAlloc + size / 2) = (BYTE) RAND();
        *((PBYTE) pAlloc + size - 1) = (BYTE) RAND();

        MEMFREE(pAlloc);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
    resetInstrumentedAllocators();
}

TEST_F(InstrumentedAllocatorsTest, random_alignalloc_free)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

    for (UINT32 i = 0; i < TestIterationCount; i++) {
        SIZE_T size = RAND() % TestAllocSize + 100;
        PVOID pAlloc = MEMALIGNALLOC(size, 16);
        *(PBYTE) pAlloc = (BYTE) RAND();
        *((PBYTE) pAlloc + size / 2) = (BYTE) RAND();
        *((PBYTE) pAlloc + size - 1) = (BYTE) RAND();

        MEMFREE(pAlloc);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
    resetInstrumentedAllocators();
}

TEST_F(InstrumentedAllocatorsTest, random_calloc_free)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

    for (UINT32 i = 0; i < TestIterationCount; i++) {
        SIZE_T size = RAND() % TestAllocSize + 100;
        PVOID pAlloc = MEMCALLOC(3, size);
        *(PBYTE) pAlloc = (BYTE) RAND();
        *((PBYTE) pAlloc + size / 2) = (BYTE) RAND();
        *((PBYTE) pAlloc + size - 1) = (BYTE) RAND();

        MEMFREE(pAlloc);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
    resetInstrumentedAllocators();
}

TEST_F(InstrumentedAllocatorsTest, random_alloc_later_free)
{
    PBYTE allocations[TestIterationCount];
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

    for (UINT32 i = 0; i < TestIterationCount; i++) {
        SIZE_T size = RAND() % TestAllocSize + 100;
        allocations[i] = (PBYTE) MEMALLOC(size);
        // Touch beginning, mid and end for no no-op
        allocations[i][0] = (BYTE) RAND();
        allocations[i][size / 2] = (BYTE) RAND();
        allocations[i][size - 1] = (BYTE) RAND();
    }

    // Free all allocations
    for (UINT32 i = 0; i < TestIterationCount; i++) {
        MEMFREE(allocations[i]);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
    resetInstrumentedAllocators();
}
<commit_msg>Fix Windows build error<commit_after>#include "UtilTestFixture.h"

class InstrumentedAllocatorsTest : public UtilTestBase {
protected:
    InstrumentedAllocatorsTest() : UtilTestBase(FALSE) {
        SRAND(12345);
    }

    static const SIZE_T TestAllocSize = 1000;
    static const UINT32 TestIterationCount = 10000;
};

TEST_F(InstrumentedAllocatorsTest, set_reset_basic_test)
{
    memAlloc storedMemAlloc = globalMemAlloc;
    memAlignAlloc storedMemAlignAlloc = globalMemAlignAlloc;
    memCalloc storedMemCalloc = globalMemCalloc;
    memFree storedMemFree = globalMemFree;
    memRealloc storedMemRealloc = globalMemRealloc;
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

#ifndef INSTRUMENTED_ALLOCATORS
    SET_INSTRUMENTED_ALLOCATORS();

    // Check that we have not set anything actually
    EXPECT_EQ(storedMemAlloc, globalMemAlloc);
    EXPECT_EQ(storedMemAlignAlloc, globalMemAlignAlloc);
    EXPECT_EQ(storedMemCalloc, globalMemCalloc);
    EXPECT_EQ(storedMemFree, globalMemFree);
    EXPECT_EQ(storedMemRealloc, globalMemRealloc);

    RESET_INSTRUMENTED_ALLOCATORS();

    EXPECT_EQ(storedMemAlloc, globalMemAlloc);
    EXPECT_EQ(storedMemAlignAlloc, globalMemAlignAlloc);
    EXPECT_EQ(storedMemCalloc, globalMemCalloc);
    EXPECT_EQ(storedMemFree, globalMemFree);
    EXPECT_EQ(storedMemRealloc, globalMemRealloc);
#else
    SET_INSTRUMENTED_ALLOCATORS();

    // Check that the allocators have changed
    EXPECT_NE(storedMemAlloc, globalMemAlloc);
    EXPECT_NE(storedMemAlignAlloc, globalMemAlignAlloc);
    EXPECT_NE(storedMemCalloc, globalMemCalloc);
    EXPECT_NE(storedMemFree, globalMemFree);
    EXPECT_NE(storedMemRealloc, globalMemRealloc);

    RESET_INSTRUMENTED_ALLOCATORS();

    // Reset back to the stored ones
    EXPECT_EQ(storedMemAlloc, globalMemAlloc);
    EXPECT_EQ(storedMemAlignAlloc, globalMemAlignAlloc);
    EXPECT_EQ(storedMemCalloc, globalMemCalloc);
    EXPECT_EQ(storedMemFree, globalMemFree);
    EXPECT_EQ(storedMemRealloc, globalMemRealloc);
#endif

    // Force setting/resetting couple of times

    for (int i = 0; i < 100; i++) {
        EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());

        // Check that the allocators have changed
        EXPECT_NE(storedMemAlloc, globalMemAlloc);
        EXPECT_NE(storedMemAlignAlloc, globalMemAlignAlloc);
        EXPECT_NE(storedMemCalloc, globalMemCalloc);
        EXPECT_NE(storedMemFree, globalMemFree);
        EXPECT_NE(storedMemRealloc, globalMemRealloc);

        EXPECT_EQ(STATUS_SUCCESS, resetInstrumentedAllocators());

        // Reset back to the stored ones
        EXPECT_EQ(storedMemAlloc, globalMemAlloc);
        EXPECT_EQ(storedMemAlignAlloc, globalMemAlignAlloc);
        EXPECT_EQ(storedMemCalloc, globalMemCalloc);
        EXPECT_EQ(storedMemFree, globalMemFree);
        EXPECT_EQ(storedMemRealloc, globalMemRealloc);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_malloc)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize, getInstrumentedTotalAllocationSize());

    // Free the allocation as we are tripping ASAN
    MEMFREE((PSIZE_T) pAlloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_alignalloc)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALIGNALLOC(TestAllocSize, 16);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pAlloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_calloc)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMCALLOC(10, TestAllocSize);
    MEMCHK(pAlloc, 0x00, 10 * TestAllocSize);
    MEMSET(pAlloc, 0xFF, 10 * TestAllocSize);
    MEMCHK(pAlloc, 0xff, 10 * TestAllocSize);
    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + 10 * TestAllocSize, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pAlloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_realloc_larger_small_diff)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    PVOID pRealloc = MEMREALLOC(pAlloc, TestAllocSize + 1);
    MEMSET(pRealloc, 0xFF, TestAllocSize + 1);
    MEMCHK(pRealloc, 0xff, TestAllocSize + 1);

    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize + 1, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pRealloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_realloc_larger_large_diff)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    PVOID pRealloc = MEMREALLOC(pAlloc, 10 * TestAllocSize);
    MEMSET(pRealloc, 0xFF, 10 * TestAllocSize);
    MEMCHK(pRealloc, 0xff, 10 * TestAllocSize);

    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + 10 * TestAllocSize, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pRealloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_realloc_smaller_small_diff)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    PVOID pRealloc = MEMREALLOC(pAlloc, TestAllocSize - 1);
    MEMSET(pRealloc, 0xFF, TestAllocSize - 1);
    MEMCHK(pRealloc, 0xff, TestAllocSize - 1);

    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize - 1, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pRealloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, memory_leak_check_realloc_smaller_large_diff)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();
    PVOID pAlloc = MEMALLOC(TestAllocSize);
    MEMSET(pAlloc, 0xFF, TestAllocSize);
    MEMCHK(pAlloc, 0xff, TestAllocSize);
    PVOID pRealloc = MEMREALLOC(pAlloc, TestAllocSize / 10);
    MEMSET(pRealloc, 0xFF, TestAllocSize / 10);
    MEMCHK(pRealloc, 0xff, TestAllocSize / 10);

    EXPECT_EQ(STATUS_MEMORY_NOT_FREED, resetInstrumentedAllocators());
    EXPECT_EQ(totalAllocSize + TestAllocSize / 10, getInstrumentedTotalAllocationSize());

    MEMFREE((PSIZE_T) pRealloc - 1);
}

TEST_F(InstrumentedAllocatorsTest, random_alloc_free)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

    for (UINT32 i = 0; i < TestIterationCount; i++) {
        SIZE_T size = RAND() % TestAllocSize + 100;
        PVOID pAlloc = MEMALLOC(size);
        // Touch beginning, mid and end for no no-op
        *(PBYTE) pAlloc = (BYTE) RAND();
        *((PBYTE) pAlloc + size / 2) = (BYTE) RAND();
        *((PBYTE) pAlloc + size - 1) = (BYTE) RAND();

        MEMFREE(pAlloc);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
    resetInstrumentedAllocators();
}

TEST_F(InstrumentedAllocatorsTest, random_alignalloc_free)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

    for (UINT32 i = 0; i < TestIterationCount; i++) {
        SIZE_T size = RAND() % TestAllocSize + 100;
        PVOID pAlloc = MEMALIGNALLOC(size, 16);
        *(PBYTE) pAlloc = (BYTE) RAND();
        *((PBYTE) pAlloc + size / 2) = (BYTE) RAND();
        *((PBYTE) pAlloc + size - 1) = (BYTE) RAND();

        MEMFREE(pAlloc);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
    resetInstrumentedAllocators();
}

TEST_F(InstrumentedAllocatorsTest, random_calloc_free)
{
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

    for (UINT32 i = 0; i < TestIterationCount; i++) {
        SIZE_T size = RAND() % TestAllocSize + 100;
        PVOID pAlloc = MEMCALLOC(3, size);
        *(PBYTE) pAlloc = (BYTE) RAND();
        *((PBYTE) pAlloc + size / 2) = (BYTE) RAND();
        *((PBYTE) pAlloc + size - 1) = (BYTE) RAND();

        MEMFREE(pAlloc);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
    resetInstrumentedAllocators();
}

TEST_F(InstrumentedAllocatorsTest, random_alloc_later_free)
{
    PBYTE allocations[TestIterationCount];
    EXPECT_EQ(STATUS_SUCCESS, setInstrumentedAllocators());
    SIZE_T totalAllocSize = getInstrumentedTotalAllocationSize();

    for (UINT32 i = 0; i < TestIterationCount; i++) {
        SIZE_T size = RAND() % TestAllocSize + 100;
        allocations[i] = (PBYTE) MEMALLOC(size);
        // Touch beginning, mid and end for no no-op
        allocations[i][0] = (BYTE) RAND();
        allocations[i][size / 2] = (BYTE) RAND();
        allocations[i][size - 1] = (BYTE) RAND();
    }

    // Free all allocations
    for (UINT32 i = 0; i < TestIterationCount; i++) {
        MEMFREE(allocations[i]);
    }

    EXPECT_EQ(totalAllocSize, getInstrumentedTotalAllocationSize());
    resetInstrumentedAllocators();
}
<|endoftext|>


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

#include "src/validator/error.h"
#include "src/validator/handlers/packed_handler.h"

using namespace std;
using namespace stoke;
using namespace x64asm;

Handler::SupportLevel PackedHandler::get_support(const x64asm::Instruction& instr) {

  auto opcode = get_opcode(instr);

  for(size_t i = 0; i < instr.arity(); ++i) {
    Operand o = instr.get_operand<Operand>(i);
    if(!o.is_gp_register() && !o.is_typical_memory() && !o.is_sse_register() &&
        !o.is_immediate())
      return Handler::NONE;
  }

  if(!opcodes_[opcode])
    return Handler::NONE;

  if(opcodes_[opcode]->get_uninterpreted()) {
    return Handler::BASIC;
  } else {
    return (Handler::SupportLevel)(Handler::BASIC | Handler::CEG | Handler::ANALYSIS);
  }

}

void PackedHandler::build_circuit(const x64asm::Instruction& instr, SymState& state) {

  error_ = "";

  if(!get_support(instr)) {
    error_ = "Instruction not supported.";
    return;
  }

  auto opcode = get_opcode(instr);

  // Figure out the arguments
  Operand dest = instr.get_operand<Operand>(0);
  Operand op1 = dest;
  Operand op2 = dest;

  size_t arity = instr.arity();

  if(arity == 2) {
    op1 = instr.get_operand<Operand>(0);
    op2 = instr.get_operand<Operand>(1);
  } else if (arity == 3) {
    op1 = instr.get_operand<Operand>(1);
    op2 = instr.get_operand<Operand>(2);
  } else {
    throw VALIDATOR_ERROR("Only arity 2/3 instructions supported by PackedHandler");
  }

  SymBitVector arg1 = state[op1];
  SymBitVector arg2 = state[op2];

  // Do the loop to build the result
  auto& entry = *opcodes_[opcode];
  uint16_t input_width = entry.get_input_width();
  if(input_width == 0)
    input_width = op1.size();
  uint16_t output_width = entry.get_output_width();
  if(output_width == 0)
    output_width = input_width;
  bool limit = entry.get_only_one();
  bool clear = entry.get_clear();
  bool avx_alignment = entry.get_avx_alignment();

  // Check for memory alignment problems
  if(avx_alignment) {
    for(size_t i = 0; i < arity; ++i) {
      Operand operand = instr.get_operand<Operand>(i);
      if(operand.is_typical_memory()) {
        auto addr = state.get_addr(*(reinterpret_cast<M8*>(&operand)));
        uint64_t bits = (dest.size() == 128 ? 4 : 5);
        state.set_sigsegv(addr[bits-1][0] != SymBitVector::constant(bits, 0));
      }
    }
  }

  // Compute the result
  SymBitVector result;

  if(limit) {
    // Only apply binop to lower bits.  Useful for scalar operations.
    auto arg1_bits = min(input_width, op1.size());
    auto arg2_bits = min(input_width, op2.size());

    result = entry(op1, arg1[arg1_bits-1][0], op2, arg2[arg2_bits-1][0], state);
    if(clear)
      result = SymBitVector::constant(dest.size() - output_width, 0) || result;
    else
      result = state[dest][dest.size() - 1][output_width] || result;

  } else {
    // Loop through sets of 'input_width' in the input and apply the binary
    // operator in a pairwise way.  Stop when we get to the end of the input/output
    // and clear or preserve the remaining bits.
    result = entry(op1, arg1[input_width-1][0], op2, arg2[input_width-1][0], state);

    size_t i,j;
    for(i = input_width, j = output_width;
        i < op1.size() && i < op2.size() && j < dest.size();
        i = i + input_width, j = j + output_width) {
      result = entry(op1, arg1[i + input_width - 1][i],
                     op2, arg2[i + input_width - 1][i], state) || result;
    }

    if(j + output_width < dest.size()) {
      if(clear)
        result = SymBitVector::constant(dest.size() - j, 0);
      else
        result = state[dest][dest.size() - 1][j] || result;
    }

  }

  // Store in the right place
  bool avx = instr.is_avx() || instr.is_avx2();
  state.set(instr.get_operand<Operand>(0), result, avx);

}

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

#include "src/validator/error.h"
#include "src/validator/handlers/packed_handler.h"

using namespace std;
using namespace stoke;
using namespace x64asm;

Handler::SupportLevel PackedHandler::get_support(const x64asm::Instruction& instr) {

  auto opcode = get_opcode(instr);

  for(size_t i = 0; i < instr.arity(); ++i) {
    Operand o = instr.get_operand<Operand>(i);
    if(!o.is_gp_register() && !o.is_typical_memory() && !o.is_sse_register() &&
        !o.is_immediate())
      return Handler::NONE;
  }

  if(!opcodes_[opcode])
    return Handler::NONE;

  if(opcodes_[opcode]->get_uninterpreted()) {
    return Handler::BASIC;
  } else {
    return (Handler::SupportLevel)(Handler::BASIC | Handler::CEG | Handler::ANALYSIS);
  }

}

void PackedHandler::build_circuit(const x64asm::Instruction& instr, SymState& state) {

  error_ = "";

  if(!get_support(instr)) {
    error_ = "Instruction not supported.";
    return;
  }

  auto opcode = get_opcode(instr);

  // Figure out the arguments
  Operand dest = instr.get_operand<Operand>(0);
  Operand op1 = dest;
  Operand op2 = dest;

  size_t arity = instr.arity();

  if(arity == 2) {
    op1 = instr.get_operand<Operand>(0);
    op2 = instr.get_operand<Operand>(1);
  } else if (arity == 3) {
    op1 = instr.get_operand<Operand>(1);
    op2 = instr.get_operand<Operand>(2);
  } else {
    throw VALIDATOR_ERROR("Only arity 2/3 instructions supported by PackedHandler");
  }

  SymBitVector arg1 = state[op1];
  SymBitVector arg2 = state[op2];

  // Do the loop to build the result
  auto& entry = *opcodes_[opcode];
  uint16_t input_width = entry.get_input_width();
  if(input_width == 0)
    input_width = op1.size();
  uint16_t output_width = entry.get_output_width();
  if(output_width == 0)
    output_width = input_width;
  bool limit = entry.get_only_one();
  bool clear = entry.get_clear();
  bool avx_alignment = entry.get_avx_alignment();

  // Check for memory alignment problems
  if(avx_alignment) {
    for(size_t i = 0; i < arity; ++i) {
      Operand operand = instr.get_operand<Operand>(i);
      if(operand.is_typical_memory()) {
        auto addr = state.get_addr(*(reinterpret_cast<M8*>(&operand)));
        uint64_t bits = (dest.size() == 128 ? 4 : 5);
        state.set_sigsegv(addr[bits-1][0] != SymBitVector::constant(bits, 0));
      }
    }
  }

  // Compute the result
  SymBitVector result;

  if(limit) {
    // Only apply binop to lower bits.  Useful for scalar operations.
    auto arg1_bits = min(input_width, op1.size());
    auto arg2_bits = min(input_width, op2.size());

    result = entry(op1, arg1[arg1_bits-1][0], op2, arg2[arg2_bits-1][0], state);
    if(clear)
      result = SymBitVector::constant(dest.size() - output_width, 0) || result;
    else
      result = state[dest][dest.size() - 1][output_width] || result;

  } else {
    // Loop through sets of 'input_width' in the input and apply the binary
    // operator in a pairwise way.  Stop when we get to the end of the input/output
    // and clear or preserve the remaining bits.
    result = entry(op1, arg1[input_width-1][0], op2, arg2[input_width-1][0], state);

    size_t i,j;
    for(i = input_width, j = output_width;
        i < op1.size() && i < op2.size() && j < dest.size();
        i = i + input_width, j = j + output_width) {
      result = entry(op1, arg1[i + input_width - 1][i],
                     op2, arg2[i + input_width - 1][i], state) || result;
    }

    if(j + output_width < dest.size()) {
      if(clear)
        result = SymBitVector::constant(dest.size() - j, 0) || result;
      else
        result = state[dest][dest.size() - 1][j] || result;
    }

  }

  // Store in the right place
  bool avx = instr.is_avx() || instr.is_avx2();
  state.set(instr.get_operand<Operand>(0), result, avx);

}

<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008-2009      Patrick Spendrin  <ps_ml@gmx.de>
//

#include "GeoRendererView.h"

// Marble
#include "GeoDataContainer.h"
#include "GeoDataCoordinates.h"
#include "GeoDataDocument.h"
#include "GeoDataFeature.h"
#include "GeoDataFolder.h"
#include "GeoDataLineStyle.h"
#include "GeoDataObject.h"
#include "GeoDataPlacemark.h"
#include "GeoDataPolygon.h"
#include "GeoDataPolyStyle.h"
#include "GeoDataStyle.h"
#include "GeoDataStyleMap.h"

#include "GeoPainter.h"

// Qt
#include <QtCore/QDebug>
#include <QtGui/QPaintEvent>

using namespace Marble;

GeoRendererView::GeoRendererView( QWidget * parent )
  : QAbstractItemView( parent )
{
}

void GeoRendererView::setGeoPainter( GeoPainter* painter )
{
    m_painter = painter;
    /* the paintEvent function has to called by hand as the view is not
     * connected to a widget (where you normally would get the event from) */
    if( model() ) paintEvent( 0 );
}

QRect GeoRendererView::visualRect( const QModelIndex &index ) const
{
    Q_UNUSED( index )

    return QRect();
}

void GeoRendererView::scrollTo( const QModelIndex &index, ScrollHint hint )
{
    Q_UNUSED( index )
    Q_UNUSED( hint )
}

QModelIndex GeoRendererView::indexAt( const QPoint &point ) const
{
    Q_UNUSED( point )

    return QModelIndex();
}

QModelIndex GeoRendererView::moveCursor( QAbstractItemView::CursorAction cursorAction,
                    Qt::KeyboardModifiers modifiers )
{
    Q_UNUSED( cursorAction )
    Q_UNUSED( modifiers )

    return QModelIndex();
}

bool GeoRendererView::isIndexHidden( const QModelIndex &index ) const
{
    Q_UNUSED( index )

    return false;
}

void GeoRendererView::setSelection( const QRect&, QItemSelectionModel::SelectionFlags command )
{
    Q_UNUSED( command )
}

void GeoRendererView::paintEvent( QPaintEvent *event )
{
    Q_UNUSED( event )

    QModelIndex index = rootIndex();
    renderIndex( index );
}

void GeoRendererView::renderIndex( QModelIndex &index )
{
    /*
     * "render" a specific index - this means going through all children and if
     * one can be rendered (if it is a Geometry object which is not a container)
     * then call the real render function. For the rest iterate through the
     * children and recurse.
     */
    GeoDataObject* indexObject = model()->data( rootIndex(), Qt::UserRole + 11 ).value<Marble::GeoDataObject*>();
    if( !( dynamic_cast<GeoDataFeature*>( indexObject ) && dynamic_cast<GeoDataFeature*>( indexObject )->isVisible() ) ) return;

    int rowCount = model()->rowCount( index );

    for ( int row = 0; row < rowCount; ++row )
    {
        QModelIndex childIndex = model()->index( row, 0, index );
        QString output = model()->data( childIndex ).toString();
        GeoDataObject* object = model()->data( childIndex, Qt::UserRole + 11 ).value<Marble::GeoDataObject*>();

        if( dynamic_cast<GeoDataGeometry*>( object ) ) {
            if( static_cast<GeoDataGeometry*>( object )->geometryId() != GeoDataMultiGeometryId ) {
                renderGeoDataGeometry( reinterpret_cast<GeoDataGeometry*>( object ), styleUrl );
            } else {
                if( childIndex.isValid() && model()->rowCount( childIndex ) > 0 ) {
                    renderIndex( childIndex );
                }
            }
        }
        else if( dynamic_cast<GeoDataFeature*>( object ) ) {
            if( dynamic_cast<GeoDataFeature*>( object )->featureId() == GeoDataPlacemarkId ) {
                GeoDataPlacemark placemark( *static_cast<GeoDataFeature*>( object ) );
                styleUrl = placemark.styleUrl();
            }

            if( childIndex.isValid() && model()->rowCount( childIndex ) > 0 ) {
                renderIndex( childIndex );
            }
        }
    }
}

QRegion GeoRendererView::visualRegionForSelection( const QItemSelection &selection ) const
{
    Q_UNUSED( selection )

    return QRegion();
}

void GeoRendererView::setBrushStyle( QString mapped )
{
    /* this part has to be reworked:
     * Currently the style has to be accessible from the root object of the
     * model. This might not be wanted. On the other hand - is a copy of the
     * style within every Placemark wanted and how should this be called here?
     */
    if( m_painter->brush().color() != m_root->style( mapped ).polyStyle().color() ) {
/*        qDebug() << "BrushColor:"
                 << m_root->style( mapped ).polyStyle().color()
                 << m_painter->brush().color();*/
        m_painter->setBrush( m_root->style( mapped ).polyStyle().color() );
    }
}

void GeoRendererView::setPenStyle( QString mapped )
{
    /*
     * see the note in the setBrushStyle function
     */
    if( m_currentPen.color() != m_root->style( mapped ).lineStyle().color() ||
        m_currentPen.widthF() != m_root->style( mapped ).lineStyle().width() ) {
/*            qDebug() << "PenColor:"
                 << m_root->style( mapped ).lineStyle().color()
                 << m_currentPen.color();
        qDebug() << "PenWidth:"
                 << m_root->style( mapped ).lineStyle().width()
                 << m_currentPen.widthF();*/
        m_currentPen.setColor( m_root->style( mapped ).lineStyle().color() );
        m_currentPen.setWidthF( m_root->style( mapped ).lineStyle().width() );
    }
    if ( m_painter->mapQuality() != Marble::High && m_painter->mapQuality() != Marble::Print )
    {
//            m_currentPen.setWidth( 0 );
        QColor penColor = m_currentPen.color();
        penColor.setAlpha( 255 );
        m_currentPen.setColor( penColor );
    }
    m_painter->setPen( m_currentPen );
}

bool GeoRendererView::renderGeoDataGeometry( GeoDataGeometry *object, QString styleUrl )
{
    m_painter->save();
    m_painter->autoMapQuality();

    m_root = dynamic_cast<GeoDataDocument*>( model()->data( rootIndex(),
                 Qt::UserRole + 11 ).value<Marble::GeoDataObject*>() );

    if( !m_root ) {
        qWarning() << "root seems to be 0!!!";
        return false;
    }

    /// hard coded to use only the "normal" style
    QString mapped = styleUrl;
    const GeoDataStyleMap& styleMap = m_root->styleMap( styleUrl.remove( '#' ) );

    mapped = styleMap.value( QString( "normal" ) );
    mapped.remove( '#' );

    if( object->geometryId() == GeoDataPolygonId ) {
        setBrushStyle( mapped );
        setPenStyle( mapped );
        // geometries are implicitly shared, this shouldn't hurt
        GeoDataPolygon polygon( *static_cast<GeoDataPolygon*>( object ) );
        m_painter->drawPolygon( polygon );
    }
    if( object->geometryId() == GeoDataLinearRingId ) {
        m_painter->setBrush( QColor( 0, 0, 0, 0 ) );
        setPenStyle( mapped );
        GeoDataLinearRing linearRing( *static_cast<GeoDataLinearRing*>( object ) );
        m_painter->drawPolygon( linearRing );
    }
    if( object->geometryId() == GeoDataLineStringId ) {
        setPenStyle( mapped );
        GeoDataLineString lineString( *static_cast<GeoDataLineString*>( object ) );
        m_painter->drawPolyline( lineString );
    }
    /* Note: GeoDataMultiGeometry is handled within the model */
    m_painter->restore();
    return true;
}
<commit_msg>fix display of "direct" styles BUG:190930<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008-2009      Patrick Spendrin  <ps_ml@gmx.de>
//

#include "GeoRendererView.h"

// Marble
#include "GeoDataContainer.h"
#include "GeoDataCoordinates.h"
#include "GeoDataDocument.h"
#include "GeoDataFeature.h"
#include "GeoDataFolder.h"
#include "GeoDataLineStyle.h"
#include "GeoDataObject.h"
#include "GeoDataPlacemark.h"
#include "GeoDataPolygon.h"
#include "GeoDataPolyStyle.h"
#include "GeoDataStyle.h"
#include "GeoDataStyleMap.h"

#include "GeoPainter.h"

// Qt
#include <QtCore/QDebug>
#include <QtGui/QPaintEvent>

using namespace Marble;

GeoRendererView::GeoRendererView( QWidget * parent )
  : QAbstractItemView( parent )
{
}

void GeoRendererView::setGeoPainter( GeoPainter* painter )
{
    m_painter = painter;
    /* the paintEvent function has to called by hand as the view is not
     * connected to a widget (where you normally would get the event from) */
    if( model() ) paintEvent( 0 );
}

QRect GeoRendererView::visualRect( const QModelIndex &index ) const
{
    Q_UNUSED( index )

    return QRect();
}

void GeoRendererView::scrollTo( const QModelIndex &index, ScrollHint hint )
{
    Q_UNUSED( index )
    Q_UNUSED( hint )
}

QModelIndex GeoRendererView::indexAt( const QPoint &point ) const
{
    Q_UNUSED( point )

    return QModelIndex();
}

QModelIndex GeoRendererView::moveCursor( QAbstractItemView::CursorAction cursorAction,
                    Qt::KeyboardModifiers modifiers )
{
    Q_UNUSED( cursorAction )
    Q_UNUSED( modifiers )

    return QModelIndex();
}

bool GeoRendererView::isIndexHidden( const QModelIndex &index ) const
{
    Q_UNUSED( index )

    return false;
}

void GeoRendererView::setSelection( const QRect&, QItemSelectionModel::SelectionFlags command )
{
    Q_UNUSED( command )
}

void GeoRendererView::paintEvent( QPaintEvent *event )
{
    Q_UNUSED( event )

    QModelIndex index = rootIndex();
    renderIndex( index );
}

void GeoRendererView::renderIndex( QModelIndex &index )
{
    /*
     * "render" a specific index - this means going through all children and if
     * one can be rendered (if it is a Geometry object which is not a container)
     * then call the real render function. For the rest iterate through the
     * children and recurse.
     */
    GeoDataObject* indexObject = model()->data( rootIndex(), Qt::UserRole + 11 ).value<Marble::GeoDataObject*>();
    if( !( dynamic_cast<GeoDataFeature*>( indexObject ) && dynamic_cast<GeoDataFeature*>( indexObject )->isVisible() ) ) return;

    int rowCount = model()->rowCount( index );

    for ( int row = 0; row < rowCount; ++row )
    {
        QModelIndex childIndex = model()->index( row, 0, index );
        QString output = model()->data( childIndex ).toString();
        GeoDataObject* object = model()->data( childIndex, Qt::UserRole + 11 ).value<Marble::GeoDataObject*>();

        if( dynamic_cast<GeoDataGeometry*>( object ) ) {
            if( static_cast<GeoDataGeometry*>( object )->geometryId() != GeoDataMultiGeometryId ) {
                renderGeoDataGeometry( reinterpret_cast<GeoDataGeometry*>( object ), styleUrl );
            } else {
                if( childIndex.isValid() && model()->rowCount( childIndex ) > 0 ) {
                    renderIndex( childIndex );
                }
            }
        }
        else if( dynamic_cast<GeoDataFeature*>( object ) ) {
            if( dynamic_cast<GeoDataFeature*>( object )->featureId() == GeoDataPlacemarkId ) {
                GeoDataPlacemark placemark( *static_cast<GeoDataFeature*>( object ) );
                styleUrl = placemark.styleUrl();
            }

            if( childIndex.isValid() && model()->rowCount( childIndex ) > 0 ) {
                renderIndex( childIndex );
            }
        }
    }
}

QRegion GeoRendererView::visualRegionForSelection( const QItemSelection &selection ) const
{
    Q_UNUSED( selection )

    return QRegion();
}

void GeoRendererView::setBrushStyle( QString mapped )
{
    /* this part has to be reworked:
     * Currently the style has to be accessible from the root object of the
     * model. This might not be wanted. On the other hand - is a copy of the
     * style within every Placemark wanted and how should this be called here?
     */
    if( m_painter->brush().color() != m_root->style( mapped ).polyStyle().color() ) {
/*        qDebug() << "BrushColor:"
                 << m_root->style( mapped ).polyStyle().color()
                 << m_painter->brush().color();*/
        m_painter->setBrush( m_root->style( mapped ).polyStyle().color() );
    }
}

void GeoRendererView::setPenStyle( QString mapped )
{
    /*
     * see the note in the setBrushStyle function
     */
    if( m_currentPen.color() != m_root->style( mapped ).lineStyle().color() ||
        m_currentPen.widthF() != m_root->style( mapped ).lineStyle().width() ) {
/*            qDebug() << "PenColor:"
                 << m_root->style( mapped ).lineStyle().color()
                 << m_currentPen.color();
        qDebug() << "PenWidth:"
                 << m_root->style( mapped ).lineStyle().width()
                 << m_currentPen.widthF();*/
        m_currentPen.setColor( m_root->style( mapped ).lineStyle().color() );
        m_currentPen.setWidthF( m_root->style( mapped ).lineStyle().width() );
    }
    if ( m_painter->mapQuality() != Marble::High && m_painter->mapQuality() != Marble::Print )
    {
//            m_currentPen.setWidth( 0 );
        QColor penColor = m_currentPen.color();
        penColor.setAlpha( 255 );
        m_currentPen.setColor( penColor );
    }
    m_painter->setPen( m_currentPen );
}

bool GeoRendererView::renderGeoDataGeometry( GeoDataGeometry *object, QString styleUrl )
{
    m_painter->save();
    m_painter->autoMapQuality();

    m_root = dynamic_cast<GeoDataDocument*>( model()->data( rootIndex(),
                 Qt::UserRole + 11 ).value<Marble::GeoDataObject*>() );

    if( !m_root ) {
        qWarning() << "root seems to be 0!!!";
        return false;
    }

    QString mapped = styleUrl;
    const GeoDataStyleMap& styleMap = m_root->styleMap( styleUrl.remove( '#' ) );

    /// hard coded to use only the "normal" style
    if( !styleMap.value( QString( "normal" ) ).isEmpty() ) {
        mapped = styleMap.value( QString( "normal" ) );
    }

    mapped.remove( '#' );

    if( object->geometryId() == GeoDataPolygonId ) {
        setBrushStyle( mapped );
        setPenStyle( mapped );
        // geometries are implicitly shared, this shouldn't hurt
        GeoDataPolygon polygon( *static_cast<GeoDataPolygon*>( object ) );
        m_painter->drawPolygon( polygon );
    }
    if( object->geometryId() == GeoDataLinearRingId ) {
        m_painter->setBrush( QColor( 0, 0, 0, 0 ) );
        setPenStyle( mapped );
        GeoDataLinearRing linearRing( *static_cast<GeoDataLinearRing*>( object ) );
        m_painter->drawPolygon( linearRing );
    }
    if( object->geometryId() == GeoDataLineStringId ) {
        setPenStyle( mapped );
        GeoDataLineString lineString( *static_cast<GeoDataLineString*>( object ) );
        m_painter->drawPolyline( lineString );
    }
    /* Note: GeoDataMultiGeometry is handled within the model */
    m_painter->restore();
    return true;
}
<|endoftext|>


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

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you 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.

*******************************************************************************/

//==============================================================================
// Viewer widget
//==============================================================================

#include "viewerwidget.h"

//==============================================================================

#include <QPainter>
#include <QPaintEvent>
#include <QPalette>
#include <QRectF>

//==============================================================================

#include "qwt_mathml_text_engine.h"

//==============================================================================

namespace OpenCOR {
namespace Viewer {

//==============================================================================

ViewerWidget::ViewerWidget(QWidget *pParent) :
    Widget(pParent),
    mMathmlDocument(QwtMathMLDocument()),
    mOneOverMathmlDocumentWidth(0),
    mOneOverMathmlDocumentHeight(0),
    mOptimiseFontSize(true)
{
//---GRY--- THE BELOW CODE IS JUST FOR TESTING THE WIDGET...
setContent("<math><mrow><msub><mi>i</mi><mi>Na</mi></msub><mo>=</mo><mfrac><mrow><msub><mi>g</mi><mi>Na</mi></msub><mo>·</mo><msup><mi>m</mi><mn>3</mn></msup><mo>·</mo><mi>h</mi><mo>·</mo><msub><mi>Na</mi><mi>o</mi></msub><mo>·</mo><mfrac><msup><mi>F</mi><mn>2</mn></msup><mrow><mi>R</mi><mo>·</mo><mi>T</mi></mrow></mfrac><mo>·</mo><mo>(</mo><mrow><msup><mi>e</mi><mrow><mo>(</mo><mi>V</mi><mo>-</mo><msub><mi>E</mi><mn>Na</mn></msub><mo>)</mo><mo>·</mo><mfrac><mrow><mi>F</mi></mrow><mrow><mi>R</mi><mo>·</mo><mi>T</mi></mrow></mfrac></mrow></msup><mo>-</mo><mn>1</mn></mrow><mo>)</mo></mrow><mrow><msup><mi>e</mi><mrow><mi>V</mi><mo>·</mo><mfrac><mrow><mi>F</mi></mrow><mrow><mi>R</mi><mo>·</mo><mi>T</mi></mrow></mfrac></mrow></msup><mo>-</mo><mn>1</mn></mrow></mfrac><mo>·</mo><mi>V</mi></mrow></math>");

// Basic elements

//setContent("<math><mrow><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow><mo>=</mo><mn>2</mn></mrow></math>");

// Fraction: mfrac

//setContent("<math><mfrac><mrow><mi>x</mi><mo>-</mo><mn>1</mn></mrow><mn>100</mn></mfrac></math>");
//setContent("<math><mfrac linethickness=\"150\"><mrow><mi>x</mi><mo>-</mo><mn>1</mn></mrow><mn>100</mn></mfrac></math>");
//setContent("<math><mfrac linethickness=\"0.00001\"><mrow><mi>x</mi><mo>-</mo><mn>1</mn></mrow><mn>100</mn></mfrac></math>");
//setContent("<math><mfrac linethickness=\"0\"><mrow><mi>x</mi><mo>-</mo><mn>1</mn></mrow><mn>100</mn></mfrac></math>");

// Radicals: msqrt and mroot

//setContent("<math><msqrt><mi>x</mi><mo>+</mo><mi>y</mi></msqrt></math>");
//setContent("<math><mroot><mi>x</mi><mn>3</mn></mroot></math>");

// Subscripts and superscripts: msub, msup and msubsup

//setContent("<math><msub><mi>x</mi><mi>i</mi></msub></math>");
//setContent("<math><msup><mi>x</mi><mi>j</mi></msup></math>");
//setContent("<math><msubsup><mi>x</mi><mi>i</mi><mi>j</mi></msubsup></math>");

// Underscripts and overscripts: munder, mover and munderover

//setContent("<math><munder><mi>x</mi><mo>─</mo></munder></math>");
//setContent("<math><mover><mi>v</mi><mo>→</mo></mover></math>");
//setContent("<math><munderover><mi>x</mi><mi>a</mi><mi>b</mi></munderover></math>");

// The ubiquitous mo element

//setContent("<math><mrow><munderover><mo>∫</mo><mn>-1</mn><mn>+1</mn></munderover><mfrac><mrow><mi>d</mi><mi>x</mi></mrow><mi>x</mi></mfrac></mrow></math>");
//setContent("<math><mrow><mi>x</mi><munder><mo>→</mo><mtext>maps to</mtext></munder><mi>y</mi></mrow></math>");

// Matrices

//setContent("<math><mrow><mo>[</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr></mtable><mo>]</mo></mrow></math>");

// Some equations

//setContent("<math><mrow><mo>{</mo><mtable><mtr><mtd><mrow><mrow><mrow><mn>2</mn><mo></mo><mi>x</mi></mrow><mo>+</mo><mi>y</mi></mrow><mo>=</mo><mn>8</mn></mrow></mtd></mtr><mtr><mtd><mrow><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow><mo>=</mo><mn>6</mn></mrow></mtd></mtr></mtable></mrow></math>");
//setContent("<math><mtable side=\"left\"><mlabeledtr><mtd><mtext>Gauss' law</mtext></mtd><mtd><mrow><mrow><mo>∇</mo><mo>∙</mo><mi mathvariant=\"normal\">E</mi></mrow><mo>=</mo><mfrac><mi>ρ</mi><msub><mi>ε</mi><mn>0</mn></msub></mfrac></mrow></mtd></mlabeledtr><mlabeledtr><mtd><mtext>Gauss's law for magnetism</mtext></mtd><mtd><mrow><mrow><mo>∇</mo><mo>∙</mo><mi mathvariant=\"normal\">B</mi></mrow><mo>=</mo><mn>0</mn></mrow></mtd></mlabeledtr></mtable></math>");

//setContent("<math><mstyle mathbackground=\"yellow\" mathcolor=\"navy\" mathsize=\"16pt\" mathvariant=\"bold\"><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow><mo>=</mo><mn mathcolor=\"red\">2</mn></mstyle></math>");
//setContent("<math><mstyle mathbackground=\"yellow\" mathcolor=\"navy\"><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow><mo>=</mo><mn mathcolor=\"red\">2</mn></mstyle></math>");

//setContent("<math><mfrac><mrow><mi> x </mi><mo> + </mo><mi> y </mi><mo> + </mo><mi> z </mi></mrow><mrow><mi> x </mi><mphantom><mo form=\"infix\"> + </mo><mi> y </mi></mphantom><mo> + </mo><mi> z </mi></mrow></mfrac></math>");
}

//==============================================================================

QString ViewerWidget::content() const
{
    // Return our content

    return mContent;
}

//==============================================================================

void ViewerWidget::setContent(const QString &pContent)
{
    // Set our content

    if (!pContent.compare(mContent))
        return;

    // Keep track of our content

    mContent = pContent;

    // Determine (the inverse of) the size of our content when rendered using a
    // font size of 100 points
    // Note: when setting the content, QwtMathMLDocument recomputes its layout.
    //       Now, because we want the content to be rendered as optimally as
    //       possible, we use a big font size, so that when we actually need to
    //       render the content (see paintEvent()), we can do so optimally...

    mMathmlDocument.setBaseFontPointSize(100);
    mMathmlDocument.setContent(mContent);

    QSizeF mathmlDocumentSize = mMathmlDocument.size();

    mOneOverMathmlDocumentWidth  = 1.0/mathmlDocumentSize.width();
    mOneOverMathmlDocumentHeight = 1.0/mathmlDocumentSize.height();
}

//==============================================================================

bool ViewerWidget::optimiseFontSize() const
{
    // Return whether we optimise our font size

    return mOptimiseFontSize;
}

//==============================================================================

void ViewerWidget::setOptimiseFontSize(const bool &pOptimiseFontSize)
{
    // Keep track of whether we should optimise our font size

    if (pOptimiseFontSize == mOptimiseFontSize)
        return;

    mOptimiseFontSize = pOptimiseFontSize;

    // Repaint ourselves

    repaint();
}

//==============================================================================

void ViewerWidget::paintEvent(QPaintEvent *pEvent)
{
    QPainter painter(this);

    // Clear our background

    QRectF rect = pEvent->rect();
    QColor backgroundColor = QColor(palette().color(QPalette::Base));

    painter.fillRect(rect, backgroundColor);

    // Customise our MathML document
    // Note: to go for 100% of the 'optimal' font size might result in the edges
    //       of the content being clipped on Windows (compared to Linux and OS
    //       X) or in some cases on Linux and OS X (e.g. if the content includes
    //       a square root), hence we go for 75% of the 'optimal' font size
    //       instead...

    mMathmlDocument.setBackgroundColor(backgroundColor);
    mMathmlDocument.setForegroundColor(QColor(palette().color(QPalette::Text)));

    mMathmlDocument.setBaseFontPointSize(mOptimiseFontSize?
                                             qRound(75.0*qMin(mOneOverMathmlDocumentWidth*width(),
                                                              mOneOverMathmlDocumentHeight*height())):
                                             font().pointSize());

    // Render our content

    QSizeF mathmlDocumentSize = mMathmlDocument.size();

    mMathmlDocument.paint(&painter, QPointF(0.5*(rect.width()-mathmlDocumentSize.width()),
                                            0.5*(rect.height()-mathmlDocumentSize.height())));

    // Accept the event

    pEvent->accept();
}

//==============================================================================

QSize ViewerWidget::minimumSizeHint() const
{
    // Suggest a default minimum size for our viewer widget

    return defaultSize(0.03);
}

//==============================================================================

QSize ViewerWidget::sizeHint() const
{
    // Suggest a default size for our viewer widget
    // Note: this is critical if we want a docked widget, with a viewer widget
    //       on it, to have a decent size when docked to the main window...

    return defaultSize(0.1);
}

//==============================================================================

}   // namespace Viewer
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Some minor cleaning up [ci skip].<commit_after>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you 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.

*******************************************************************************/

//==============================================================================
// Viewer widget
//==============================================================================

#include "viewerwidget.h"

//==============================================================================

#include <QPainter>
#include <QPaintEvent>
#include <QPalette>
#include <QRectF>

//==============================================================================

#include "qwt_mathml_text_engine.h"

//==============================================================================

namespace OpenCOR {
namespace Viewer {

//==============================================================================

ViewerWidget::ViewerWidget(QWidget *pParent) :
    Widget(pParent),
    mMathmlDocument(QwtMathMLDocument()),
    mOneOverMathmlDocumentWidth(0),
    mOneOverMathmlDocumentHeight(0),
    mOptimiseFontSize(true)
{
}

//==============================================================================

QString ViewerWidget::content() const
{
    // Return our content

    return mContent;
}

//==============================================================================

void ViewerWidget::setContent(const QString &pContent)
{
    // Set our content

    if (!pContent.compare(mContent))
        return;

    // Keep track of our content

    mContent = pContent;

    // Determine (the inverse of) the size of our content when rendered using a
    // font size of 100 points
    // Note: when setting the content, QwtMathMLDocument recomputes its layout.
    //       Now, because we want the content to be rendered as optimally as
    //       possible, we use a big font size, so that when we actually need to
    //       render the content (see paintEvent()), we can do so optimally...

    mMathmlDocument.setBaseFontPointSize(100);
    mMathmlDocument.setContent(mContent);

    QSizeF mathmlDocumentSize = mMathmlDocument.size();

    mOneOverMathmlDocumentWidth  = 1.0/mathmlDocumentSize.width();
    mOneOverMathmlDocumentHeight = 1.0/mathmlDocumentSize.height();
}

//==============================================================================

bool ViewerWidget::optimiseFontSize() const
{
    // Return whether we optimise our font size

    return mOptimiseFontSize;
}

//==============================================================================

void ViewerWidget::setOptimiseFontSize(const bool &pOptimiseFontSize)
{
    // Keep track of whether we should optimise our font size

    if (pOptimiseFontSize == mOptimiseFontSize)
        return;

    mOptimiseFontSize = pOptimiseFontSize;

    // Repaint ourselves

    repaint();
}

//==============================================================================

void ViewerWidget::paintEvent(QPaintEvent *pEvent)
{
    QPainter painter(this);

    // Clear our background

    QRectF rect = pEvent->rect();
    QColor backgroundColor = QColor(palette().color(QPalette::Base));

    painter.fillRect(rect, backgroundColor);

    // Customise our MathML document
    // Note: to go for 100% of the 'optimal' font size might result in the edges
    //       of the content being clipped on Windows (compared to Linux and OS
    //       X) or in some cases on Linux and OS X (e.g. if the content includes
    //       a square root), hence we go for 75% of the 'optimal' font size
    //       instead...

    mMathmlDocument.setBackgroundColor(backgroundColor);
    mMathmlDocument.setForegroundColor(QColor(palette().color(QPalette::Text)));

    mMathmlDocument.setBaseFontPointSize(mOptimiseFontSize?
                                             qRound(75.0*qMin(mOneOverMathmlDocumentWidth*width(),
                                                              mOneOverMathmlDocumentHeight*height())):
                                             font().pointSize());

    // Render our content

    QSizeF mathmlDocumentSize = mMathmlDocument.size();

    mMathmlDocument.paint(&painter, QPointF(0.5*(rect.width()-mathmlDocumentSize.width()),
                                            0.5*(rect.height()-mathmlDocumentSize.height())));

    // Accept the event

    pEvent->accept();
}

//==============================================================================

QSize ViewerWidget::minimumSizeHint() const
{
    // Suggest a default minimum size for our viewer widget

    return defaultSize(0.03);
}

//==============================================================================

QSize ViewerWidget::sizeHint() const
{
    // Suggest a default size for our viewer widget
    // Note: this is critical if we want a docked widget, with a viewer widget
    //       on it, to have a decent size when docked to the main window...

    return defaultSize(0.1);
}

//==============================================================================

}   // namespace Viewer
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>/*!
 * \file
 * \brief Class module::Reducer.
 */
#ifndef INCREMENTER_HPP_
#define INCREMENTER_HPP_

#include <cstdint>
#include <vector>

#include "Tools/Math/binaryop.h"
#include "Module/Module.hpp"

namespace aff3ct
{

namespace module
{
	namespace red
	{
		enum class tsk : size_t { reduce, SIZE };

		namespace sck
		{
			enum class reduce : size_t { in, out, status };
		}
	}

template <typename TI, typename TO, tools::proto_bop<TI,TO> BOP>
class Reducer : public Module
{
public:
	inline Task&   operator[](const red::tsk         t);
	inline Socket& operator[](const red::sck::reduce s);

protected:
	const size_t n_elmts;

public:
	Reducer(const size_t n_elmts);
	virtual ~Reducer() = default;
	virtual Reducer<TI,TO,BOP>* clone() const;

	size_t get_n_elmts() const;

	template <class AI = std::allocator<TI>, class AO = std::allocator<TO>>
	void reduce(const std::vector<TI,AI>& in,
	                  std::vector<TO,AO>& out,
	            const int frame_id = -1,
	            const bool managed_memory = true);

	void reduce(const TI *in, TO *out, const int frame_id = -1, const bool managed_memory = true);

protected:
	virtual void _reduce(const TI *in, TO *out, const size_t frame_id);
};

template <typename TI, typename TO = TI> using Reducer_add = Reducer<TI,TO,tools::bop_add<TI,TO>>;
template <typename TI, typename TO = TI> using Reducer_sub = Reducer<TI,TO,tools::bop_sub<TI,TO>>;
template <typename TI, typename TO = TI> using Reducer_mul = Reducer<TI,TO,tools::bop_mul<TI,TO>>;
template <typename TI, typename TO = TI> using Reducer_div = Reducer<TI,TO,tools::bop_div<TI,TO>>;
template <typename TI, typename TO = TI> using Reducer_or  = Reducer<TI,TO,tools::bop_or <TI,TO>>;
template <typename TI, typename TO = TI> using Reducer_xor = Reducer<TI,TO,tools::bop_xor<TI,TO>>;
template <typename TI, typename TO = TI> using Reducer_and = Reducer<TI,TO,tools::bop_and<TI,TO>>;
template <typename TI, typename TO = TI> using Reducer_min = Reducer<TI,TO,tools::bop_min<TI,TO>>;
template <typename TI, typename TO = TI> using Reducer_max = Reducer<TI,TO,tools::bop_max<TI,TO>>;

}
}

#ifndef DOXYGEN_SHOULD_SKIP_THIS
#include "Module/Reducer/Reducer.hxx"
#endif

#endif /* INCREMENTER_HPP_ */
<commit_msg>Fix link error on MSVC.<commit_after>/*!
 * \file
 * \brief Class module::Reducer.
 */
#ifndef INCREMENTER_HPP_
#define INCREMENTER_HPP_

#include <cstdint>
#include <vector>

#include "Tools/Math/binaryop.h"
#include "Module/Module.hpp"

namespace aff3ct
{

namespace module
{
	namespace red
	{
		enum class tsk : size_t { reduce, SIZE };

		namespace sck
		{
			enum class reduce : size_t { in, out, status };
		}
	}

template <typename TI, typename TO, tools::proto_bop<TI,TO> BOP>
class Reducer : public Module
{
public:
	inline Task&   operator[](const red::tsk         t);
	inline Socket& operator[](const red::sck::reduce s);

protected:
	const size_t n_elmts;

public:
	Reducer(const size_t n_elmts);
	virtual ~Reducer() = default;
	virtual Reducer<TI,TO,BOP>* clone() const;

	size_t get_n_elmts() const;

	template <class AI = std::allocator<TI>, class AO = std::allocator<TO>>
	void reduce(const std::vector<TI,AI>& in,
	                  std::vector<TO,AO>& out,
	            const int frame_id = -1,
	            const bool managed_memory = true);

	void reduce(const TI *in, TO *out, const int frame_id = -1, const bool managed_memory = true);

protected:
	virtual void _reduce(const TI *in, TO *out, const size_t frame_id);
};

template <typename TI, typename TO = TI, tools::proto_bop<TI, TO> BOP = tools::bop_add<TI, TO>> using Reducer_add = Reducer<TI, TO, BOP>;
template <typename TI, typename TO = TI, tools::proto_bop<TI, TO> BOP = tools::bop_sub<TI, TO>> using Reducer_sub = Reducer<TI, TO, BOP>;
template <typename TI, typename TO = TI, tools::proto_bop<TI, TO> BOP = tools::bop_mul<TI, TO>> using Reducer_mul = Reducer<TI, TO, BOP>;
template <typename TI, typename TO = TI, tools::proto_bop<TI, TO> BOP = tools::bop_div<TI, TO>> using Reducer_div = Reducer<TI, TO, BOP>;
template <typename TI, typename TO = TI, tools::proto_bop<TI, TO> BOP = tools::bop_or <TI, TO>> using Reducer_or  = Reducer<TI, TO, BOP>;
template <typename TI, typename TO = TI, tools::proto_bop<TI, TO> BOP = tools::bop_xor<TI, TO>> using Reducer_xor = Reducer<TI, TO, BOP>;
template <typename TI, typename TO = TI, tools::proto_bop<TI, TO> BOP = tools::bop_and<TI, TO>> using Reducer_and = Reducer<TI, TO, BOP>;
template <typename TI, typename TO = TI, tools::proto_bop<TI, TO> BOP = tools::bop_min<TI, TO>> using Reducer_min = Reducer<TI, TO, BOP>;
template <typename TI, typename TO = TI, tools::proto_bop<TI, TO> BOP = tools::bop_max<TI, TO>> using Reducer_max = Reducer<TI, TO, BOP>;

}
}

#ifndef DOXYGEN_SHOULD_SKIP_THIS
#include "Module/Reducer/Reducer.hxx"
#endif

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


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

#include "src/profiling/symbolizer/filesystem.h"

#define WIN32_MEAN_AND_LEAN
#include <Windows.h>

namespace perfetto {
namespace profiling {

bool WalkDirectories(std::vector<std::string> dirs, FileCallback fn) {
  std::vector<std::string> sub_dirs;
  for (const std::string& dir : dirs) {
    LPWIN32_FIND_DATAA file;
    HANDLE fh = FindFirstFileA((dir + "\\*").c_str(), &file);
    if (fh != INVALID_HANDLE_VALUE) {
      do {
        std::string file_path = dir + "\\" + file.cFileName;
        if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
          if (strcmp(file.cFileName, ".") != 0 &&
              strcmp(file.cFileName, "..") != 0) {
            sub_dirs.push_back(file_path);
          }
        } else {
          ULARGE_INTEGER size;
          size.HighPart = file.nFileSizeHigh;
          size.LowPart = file.nFileSizeLow;
          fn(file_path.c_str(), size.QuadPart);
        }
      } while (FindNextFileA(fh, &file));
    }
    CloseHandle(fh);
  }
  if (!sub_dirs.empty()) {
    WalkDirectories(sub_dirs, fn);
  }
  return true;
}

size_t GetFileSize(const std::string& file_path) {
  HANDLE file = CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ,
                            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (file == INVALID_HANDLE_VALUE) {
    PERFETTO_PLOG("Failed to get file size %s", file_path.c_str());
    return 0;
  }
  LARGE_INTEGER file_size;
  file_size.QuadPart = 0;
  if (!GetFileSizeEx(file, &file_size)) {
    PERFETTO_PLOG("Failed to get file size %s", file_path.c_str());
  }
  CloseHandle(file);
  return file_size.QuadPart;
}

}  // namespace profiling
}  // namespace perfetto<commit_msg>Actually fix Windows build.<commit_after>/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/profiling/symbolizer/filesystem.h"

#define WIN32_MEAN_AND_LEAN
#include <Windows.h>

namespace perfetto {
namespace profiling {

bool WalkDirectories(std::vector<std::string> dirs, FileCallback fn) {
  std::vector<std::string> sub_dirs;
  for (const std::string& dir : dirs) {
    WIN32_FIND_DATAA file;
    HANDLE fh = FindFirstFileA((dir + "\\*").c_str(), &file);
    if (fh != INVALID_HANDLE_VALUE) {
      do {
        std::string file_path = dir + "\\" + file.cFileName;
        if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
          if (strcmp(file.cFileName, ".") != 0 &&
              strcmp(file.cFileName, "..") != 0) {
            sub_dirs.push_back(file_path);
          }
        } else {
          ULARGE_INTEGER size;
          size.HighPart = file.nFileSizeHigh;
          size.LowPart = file.nFileSizeLow;
          fn(file_path.c_str(), size.QuadPart);
        }
      } while (FindNextFileA(fh, &file));
    }
    CloseHandle(fh);
  }
  if (!sub_dirs.empty()) {
    WalkDirectories(sub_dirs, fn);
  }
  return true;
}

size_t GetFileSize(const std::string& file_path) {
  HANDLE file = CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ,
                            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (file == INVALID_HANDLE_VALUE) {
    PERFETTO_PLOG("Failed to get file size %s", file_path.c_str());
    return 0;
  }
  LARGE_INTEGER file_size;
  file_size.QuadPart = 0;
  if (!GetFileSizeEx(file, &file_size)) {
    PERFETTO_PLOG("Failed to get file size %s", file_path.c_str());
  }
  CloseHandle(file);
  return file_size.QuadPart;
}

}  // namespace profiling
}  // namespace perfetto<|endoftext|>


<commit_before>#include <MemoryTable.h>
#include <Cursor.h>

#include <cassert>
#include <iostream>

using namespace std;
using namespace sqldb;

class sqldb::MemoryStorage {
public:
  MemoryStorage() { }

  std::unique_ptr<Cursor> seek(const std::string & key);
  std::unique_ptr<Cursor> seekBegin();
  std::unique_ptr<Cursor> addRow(const std::string & key);

  std::unique_ptr<Cursor> addRow() {
    return addRow(std::to_string(++auto_increment_));
  }

  std::unique_ptr<Cursor> incrementRow(const std::string & key);

  void removeRow(const std::string & key);

  void addColumn(std::string name, sqldb::ColumnType type, bool unique = false) {
    header_row_.push_back(std::tuple(type, std::move(name), unique));
  }

  int getNumFields() const { return static_cast<int>(header_row_.size()); }
  int getNumRows() const { return static_cast<int>(data_.size()); }

  ColumnType getColumnType(int column_index) const {
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row_.size() ? std::get<0>(header_row_[idx]) : ColumnType::UNDEF;
  }

  std::string getColumnName(int column_index) const {
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row_.size() ? std::get<1>(header_row_[idx]) : "";
  }

  bool isColumnUnique(int column_index) const {
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row_.size() ? std::get<2>(header_row_[idx]) : false;
  }

  void clear() {
    data_.clear();
  }

private:
  std::unordered_map<std::string, std::vector<std::string> > data_;
  std::vector<std::tuple<ColumnType, std::string, bool> > header_row_;
  long long auto_increment_ = 0;
};

class MemoryTableCursor : public Cursor {
public:
  MemoryTableCursor(std::unordered_map<std::string, std::vector<std::string> > * data,
		    std::vector<std::tuple<ColumnType, std::string, bool> > * header_row,
		    long long * auto_increment,
		    std::unordered_map<std::string, std::vector<std::string> >::iterator it,
		    bool is_increment_op = false)
    : data_(data), header_row_(header_row), auto_increment_(auto_increment), it_(it), is_increment_op_(is_increment_op) { }

  size_t execute() override {
    if (it_ != data_->end()) {
      if (is_increment_op_ && !it_->second.empty()) {
	for (size_t i = 0; i < it_->second.size(); i++) {
	  auto & v0 = it_->second[i];
	  if (v0.empty()) {
	    v0 = pending_row_[i];
	  } else if (getColumnType(i) != sqldb::ColumnType::FOREIGN_KEY && getColumnType(i) != sqldb::ColumnType::TEXT &&
		     getColumnType(i) != sqldb::ColumnType::VARCHAR) {
	    v0 = std::to_string(stoi(v0) + stoi(pending_row_[i]));
	  }
	}
      } else {
	it_->second = pending_row_;
      }
      pending_row_.clear();
      return 1;
    } else {
      return 0;
    }
  }

  void set(int column_idx, const std::string & value, bool is_defined = true) override {
    while (column_idx >= static_cast<int>(pending_row_.size())) pending_row_.push_back("");
    pending_row_[column_idx] = is_defined ? value : "";
  }

  void set(int column_idx, int value, bool is_defined = true) override { set(column_idx, std::to_string(value), is_defined); }
  void set(int column_idx, long long value, bool is_defined = true) override { set(column_idx, std::to_string(value), is_defined); }
  void set(int column_idx, double value, bool is_defined = true) override { set(column_idx, std::to_string(value), is_defined); }
  void set(int column_idx, const void * data, size_t len, bool is_defined = true) { set(column_idx, std::string(reinterpret_cast<const char *>(data), len), is_defined); }

  bool next() override {
    if (it_ != data_->end()) {
      return ++it_ != data_->end();
    } else {
      return false;
    }
  }

  std::string getRowKey() const override {
    if (it_ != data_->end()) return it_->first;
    else return "";
  }

  std::string getText(int column_index, std::string default_value) override {
    if (column_index >= 0 && it_ != data_->end()) {
      auto idx = static_cast<size_t>(column_index);
      auto & row = it_->second;
      if (idx < row.size()) return row[idx];
    }
    return std::move(default_value);
  }

  std::vector<uint8_t> getBlob(int column_index) override {
    std::vector<uint8_t> r;
    if (column_index >= 0 && it_ != data_->end()) {
      auto idx = static_cast<size_t>(column_index);
      auto & row = it_->second;
      if (idx < row.size()) {
	auto & v = row[idx];
	r.reserve(v.size());
	for (size_t i = 0; i < v.size(); i++) r.push_back(static_cast<uint8_t>(v[i]));
      }
    }
    return r;
  }

  int getNumFields() const override { return static_cast<int>(header_row_->size()); }

  ColumnType getColumnType(int column_index) const override {
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row_->size() ? std::get<0>((*header_row_)[idx]) : ColumnType::UNDEF;
  }

  std::string getColumnName(int column_index) const override {
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row_->size() ? std::get<1>((*header_row_)[idx]) : "";
  }

  bool isNull(int column_index) const override {
    if (column_index >= 0 && it_ != data_->end()) {
      auto idx = static_cast<size_t>(column_index);
      auto & row = it_->second;
      if (idx < row.size()) return row[idx].empty();
    }
    return true;
  }

  long long getLastInsertId() const override { return *auto_increment_; }

private:
  std::unordered_map<std::string, std::vector<std::string> > * data_;
  std::vector<std::tuple<ColumnType, std::string, bool> > * header_row_;
  long long * auto_increment_;
  std::unordered_map<std::string, std::vector<std::string> >::iterator it_;
  bool is_increment_op_;

  std::vector<std::string> pending_row_;
};

std::unique_ptr<Cursor>
MemoryStorage::seek(const std::string & key) {
  auto it = data_.find(key);
  if (it != data_.end()) {
    return std::make_unique<MemoryTableCursor>(&data_, &header_row_, &auto_increment_, move(it));
  } else {
    return std::unique_ptr<Cursor>(nullptr);
  }
}

std::unique_ptr<Cursor>
MemoryStorage::seekBegin() {
  auto it = data_.begin();
  if (it != data_.end()) {
    return std::make_unique<MemoryTableCursor>(&data_, &header_row_, &auto_increment_, move(it));
  } else {
    return std::unique_ptr<Cursor>(nullptr);
  }
}

std::unique_ptr<Cursor>
MemoryStorage::addRow(const std::string & key) {
  assert(!key.empty());
  auto it = data_.find(key);
  if (it == data_.end()) {
    data_[key] = std::vector<std::string>();
    it = data_.find(key);
  }

  assert(it != data_.end());
  return std::make_unique<MemoryTableCursor>(&data_, &header_row_, &auto_increment_, move(it));
}

std::unique_ptr<Cursor>
MemoryStorage::incrementRow(const std::string & key) {
  assert(!key.empty());
  auto it = data_.find(key);
  if (it == data_.end()) {
    data_[key] = std::vector<std::string>();
    it = data_.find(key);
  }

  assert(it != data_.end());
  return std::make_unique<MemoryTableCursor>(&data_, &header_row_, &auto_increment_, move(it), true);
}

void
MemoryStorage::removeRow(const std::string & key) {
  data_.erase(key);
}

MemoryTable::MemoryTable(bool numeric_key)
  : numeric_key_(numeric_key), storage_(make_shared<MemoryStorage>()) { }

void
MemoryTable::addColumn(std::string name, sqldb::ColumnType type, bool unique) {
  storage_->addColumn(name, type, unique);
}

std::unique_ptr<Cursor>
MemoryTable::addRow(const std::string & key) {
  return storage_->addRow(key);
}

std::unique_ptr<Cursor>
MemoryTable::addRow() {
  return storage_->addRow();
}

std::unique_ptr<Cursor>
MemoryTable::incrementRow(const std::string & key) {
  return storage_->incrementRow(key);
}

void
MemoryTable::removeRow(const std::string & key) {
  return storage_->removeRow(key);
}

std::unique_ptr<Cursor>
MemoryTable::seekBegin() {
  return storage_->seekBegin();
}

std::unique_ptr<Cursor>
MemoryTable::seek(const std::string & key) {
  return storage_->seek(key);
}

int
MemoryTable::getNumFields() const {
  return storage_->getNumFields();
}

int
MemoryTable::getNumRows() const {
  return storage_->getNumRows();
}

ColumnType
MemoryTable::getColumnType(int column_index) const {
  return storage_->getColumnType(column_index);
}

std::string
MemoryTable::getColumnName(int column_index) const {
  return storage_->getColumnName(column_index);
}

bool
MemoryTable::isColumnUnique(int column_index) const {
  return storage_->isColumnUnique(column_index);
}

void
MemoryTable::append(Table & other) {
  if (!getNumFields()) { // FIXME
    for (int i = 0; i < other.getNumFields(); i++) {
      addColumn(other.getColumnName(i), other.getColumnType(i), other.isColumnUnique(i));
    }
  }

  if (auto cursor = other.seekBegin()) {
    do {
      auto my_cursor = addRow(cursor->getRowKey());
      for (int i = 0; i < cursor->getNumFields(); i++) {
	my_cursor->set(i, cursor->getText(i));
      }
      my_cursor->execute();
    } while (cursor->next());
  }
}

void
MemoryTable::clear() {
  storage_->clear();
}
<commit_msg>add mutexes<commit_after>#include <MemoryTable.h>
#include <Cursor.h>

#include <cassert>
#include <iostream>
#include <mutex>

using namespace std;
using namespace sqldb;

namespace sqldb {
  class MemoryTableCursor;
};

class sqldb::MemoryStorage {
public:
  friend class sqldb::MemoryTableCursor;

  MemoryStorage() { }

  std::unique_ptr<Cursor> seek(const std::string & key);
  std::unique_ptr<Cursor> seekBegin();
  std::unique_ptr<Cursor> addRow(const std::string & key);

  std::unique_ptr<Cursor> addRow() {
    int id;
    {
      std::lock_guard<std::mutex> guard(mutex_);
      id = ++auto_increment_;
    }
    return addRow(std::to_string(id));
  }

  std::unique_ptr<Cursor> incrementRow(const std::string & key);

  void removeRow(const std::string & key);

  void addColumn(std::string name, sqldb::ColumnType type, bool unique = false) {
    std::lock_guard<std::mutex> guard(mutex_);
    header_row_.push_back(std::tuple(type, std::move(name), unique));
  }

  int getNumFields() const {
    std::lock_guard<std::mutex> guard(mutex_);
    return static_cast<int>(header_row_.size());
  }
  int getNumRows() const {
    std::lock_guard<std::mutex> guard(mutex_);
    return static_cast<int>(data_.size());
  }

  ColumnType getColumnType(int column_index) const {
    std::lock_guard<std::mutex> guard(mutex_);
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row_.size() ? std::get<0>(header_row_[idx]) : ColumnType::UNDEF;
  }

  std::string getColumnName(int column_index) const {
    std::lock_guard<std::mutex> guard(mutex_);
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row_.size() ? std::get<1>(header_row_[idx]) : "";
  }

  bool isColumnUnique(int column_index) const {
    std::lock_guard<std::mutex> guard(mutex_);
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row_.size() ? std::get<2>(header_row_[idx]) : false;
  }

  void clear() {
    std::lock_guard<std::mutex> guard(mutex_);
    data_.clear();
  }

private:
  std::unordered_map<std::string, std::vector<std::string> > data_;
  std::vector<std::tuple<ColumnType, std::string, bool> > header_row_;
  long long auto_increment_ = 0;
  mutable std::mutex mutex_;
};

class sqldb::MemoryTableCursor : public Cursor {
public:
  MemoryTableCursor(MemoryStorage * storage,
		    std::unordered_map<std::string, std::vector<std::string> >::iterator it,
		    bool is_increment_op = false)
    : storage_(storage), it_(it), is_increment_op_(is_increment_op) { }

  size_t execute() override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);
    auto & data = storage_->data_;
    if (it_ != data.end()) {
      if (is_increment_op_ && !it_->second.empty()) {
	for (size_t i = 0; i < it_->second.size(); i++) {
	  auto & v0 = it_->second[i];
	  if (v0.empty()) {
	    v0 = pending_row_[i];
	  } else if (getColumnType(i) != sqldb::ColumnType::FOREIGN_KEY && getColumnType(i) != sqldb::ColumnType::TEXT &&
		     getColumnType(i) != sqldb::ColumnType::VARCHAR) {
	    v0 = std::to_string(stoi(v0) + stoi(pending_row_[i]));
	  }
	}
      } else {
	it_->second = pending_row_;
      }
      pending_row_.clear();
      return 1;
    } else {
      return 0;
    }
  }

  void set(int column_idx, const std::string & value, bool is_defined = true) override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    while (column_idx >= static_cast<int>(pending_row_.size())) pending_row_.push_back("");
    pending_row_[column_idx] = is_defined ? value : "";
  }

  void set(int column_idx, int value, bool is_defined = true) override { set(column_idx, std::to_string(value), is_defined); }
  void set(int column_idx, long long value, bool is_defined = true) override { set(column_idx, std::to_string(value), is_defined); }
  void set(int column_idx, double value, bool is_defined = true) override { set(column_idx, std::to_string(value), is_defined); }
  void set(int column_idx, const void * data, size_t len, bool is_defined = true) { set(column_idx, std::string(reinterpret_cast<const char *>(data), len), is_defined); }

  bool next() override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    auto & data = storage_->data_;
    if (it_ != data.end()) {
      return ++it_ != data.end();
    } else {
      return false;
    }
  }

  std::string getRowKey() const override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    auto & data = storage_->data_;
    if (it_ != data.end()) return it_->first;
    else return "";
  }

  std::string getText(int column_index, std::string default_value) override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    auto & data = storage_->data_;
    if (column_index >= 0 && it_ != data.end()) {
      auto idx = static_cast<size_t>(column_index);
      auto & row = it_->second;
      if (idx < row.size()) return row[idx];
    }
    return std::move(default_value);
  }

  std::vector<uint8_t> getBlob(int column_index) override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    auto & data = storage_->data_;
    std::vector<uint8_t> r;
    if (column_index >= 0 && it_ != data.end()) {
      auto idx = static_cast<size_t>(column_index);
      auto & row = it_->second;
      if (idx < row.size()) {
	auto & v = row[idx];
	r.reserve(v.size());
	for (size_t i = 0; i < v.size(); i++) r.push_back(static_cast<uint8_t>(v[i]));
      }
    }
    return r;
  }

  int getNumFields() const override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    auto & header_row = storage_->header_row_;
    return static_cast<int>(header_row.size());
  }

  ColumnType getColumnType(int column_index) const override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    auto & header_row = storage_->header_row_;
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row.size() ? std::get<0>(header_row[idx]) : ColumnType::UNDEF;
  }

  std::string getColumnName(int column_index) const override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    auto & header_row = storage_->header_row_;
    auto idx = static_cast<size_t>(column_index);
    return idx < header_row.size() ? std::get<1>(header_row[idx]) : "";
  }

  bool isNull(int column_index) const override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    auto & data = storage_->data_;
    if (column_index >= 0 && it_ != data.end()) {
      auto idx = static_cast<size_t>(column_index);
      auto & row = it_->second;
      if (idx < row.size()) return row[idx].empty();
    }
    return true;
  }

  long long getLastInsertId() const override {
    std::lock_guard<std::mutex> guard(storage_->mutex_);

    return storage_->auto_increment_;
  }

private:
  MemoryStorage * storage_;
  std::unordered_map<std::string, std::vector<std::string> >::iterator it_;
  bool is_increment_op_;

  std::vector<std::string> pending_row_;
};

std::unique_ptr<Cursor>
MemoryStorage::seek(const std::string & key) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto it = data_.find(key);
  if (it != data_.end()) {
    return std::make_unique<MemoryTableCursor>(this, move(it));
  } else {
    return std::unique_ptr<Cursor>(nullptr);
  }
}

std::unique_ptr<Cursor>
MemoryStorage::seekBegin() {
  std::lock_guard<std::mutex> guard(mutex_);
  auto it = data_.begin();
  if (it != data_.end()) {
    return std::make_unique<MemoryTableCursor>(this, move(it));
  } else {
    return std::unique_ptr<Cursor>(nullptr);
  }
}

std::unique_ptr<Cursor>
MemoryStorage::addRow(const std::string & key) {
  std::lock_guard<std::mutex> guard(mutex_);
  assert(!key.empty());
  auto it = data_.find(key);
  if (it == data_.end()) {
    data_[key] = std::vector<std::string>();
    it = data_.find(key);
  }

  assert(it != data_.end());
  return std::make_unique<MemoryTableCursor>(this, move(it));
}

std::unique_ptr<Cursor>
MemoryStorage::incrementRow(const std::string & key) {
  std::lock_guard<std::mutex> guard(mutex_);

  assert(!key.empty());
  auto it = data_.find(key);
  if (it == data_.end()) {
    data_[key] = std::vector<std::string>();
    it = data_.find(key);
  }

  assert(it != data_.end());
  return std::make_unique<MemoryTableCursor>(this, move(it), true);
}

void
MemoryStorage::removeRow(const std::string & key) {
  data_.erase(key);
}

MemoryTable::MemoryTable(bool numeric_key)
  : numeric_key_(numeric_key), storage_(make_shared<MemoryStorage>()) { }

void
MemoryTable::addColumn(std::string name, sqldb::ColumnType type, bool unique) {
  storage_->addColumn(name, type, unique);
}

std::unique_ptr<Cursor>
MemoryTable::addRow(const std::string & key) {
  return storage_->addRow(key);
}

std::unique_ptr<Cursor>
MemoryTable::addRow() {
  return storage_->addRow();
}

std::unique_ptr<Cursor>
MemoryTable::incrementRow(const std::string & key) {
  return storage_->incrementRow(key);
}

void
MemoryTable::removeRow(const std::string & key) {
  return storage_->removeRow(key);
}

std::unique_ptr<Cursor>
MemoryTable::seekBegin() {
  return storage_->seekBegin();
}

std::unique_ptr<Cursor>
MemoryTable::seek(const std::string & key) {
  return storage_->seek(key);
}

int
MemoryTable::getNumFields() const {
  return storage_->getNumFields();
}

int
MemoryTable::getNumRows() const {
  return storage_->getNumRows();
}

ColumnType
MemoryTable::getColumnType(int column_index) const {
  return storage_->getColumnType(column_index);
}

std::string
MemoryTable::getColumnName(int column_index) const {
  return storage_->getColumnName(column_index);
}

bool
MemoryTable::isColumnUnique(int column_index) const {
  return storage_->isColumnUnique(column_index);
}

void
MemoryTable::append(Table & other) {
  if (!getNumFields()) { // FIXME
    for (int i = 0; i < other.getNumFields(); i++) {
      addColumn(other.getColumnName(i), other.getColumnType(i), other.isColumnUnique(i));
    }
  }

  if (auto cursor = other.seekBegin()) {
    do {
      auto my_cursor = addRow(cursor->getRowKey());
      for (int i = 0; i < cursor->getNumFields(); i++) {
	my_cursor->set(i, cursor->getText(i));
      }
      my_cursor->execute();
    } while (cursor->next());
  }
}

void
MemoryTable::clear() {
  storage_->clear();
}
<|endoftext|>