<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * 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.
 */

#if !DEVICE_FLASH
    #error [NOT_SUPPORTED] Flash API not supported for this target
#endif

#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"

#include "mbed.h"
#include "flash_api.h"

using namespace utest::v1;

#define TEST_CYCLES         1000000
#define ALLOWED_DRIFT_PPM   1000         //0.1%

/*
    return values to be checked are documented at:
        http://arm-software.github.io/CMSIS_5/Pack/html/algorithmFunc.html#Verify
*/

#ifndef ALIGN_DOWN
#define ALIGN_DOWN(x, a) ((x)& ~((a) - 1))
#endif

static int timer_diff_start;

static void erase_range(flash_t *flash, uint32_t addr, uint32_t size)
{
    while (size > 0) {
        uint32_t sector_size = flash_get_sector_size(flash, addr);
        TEST_ASSERT_NOT_EQUAL(0, sector_size);
        int32_t ret = flash_erase_sector(flash, addr);
        TEST_ASSERT_EQUAL_INT32(0, ret);
        addr += sector_size;
        size = size > sector_size ? size - sector_size : 0;
    }
}
#ifdef __CC_ARM
MBED_NOINLINE
__asm static void delay_loop(uint32_t count)
{
1
  SUBS a1, a1, #1
  BCS  %BT1
  BX   lr
}
#elif defined (__ICCARM__)
MBED_NOINLINE
static void delay_loop(uint32_t count)
{
  __asm volatile(
    "loop: \n"
    " SUBS %0, %0, #1 \n"
    " BCS.n  loop\n"
    : "+r" (count)
    :
    : "cc"
  );
}
#else // GCC
MBED_NOINLINE
static void delay_loop(uint32_t count)
{
  __asm__ volatile (
    "%=:\n\t"
#if defined(__thumb__) && !defined(__thumb2__)
    "SUB  %0, #1\n\t"
#else
    "SUBS %0, %0, #1\n\t"
#endif
    "BCS  %=b\n\t"
    : "+l" (count)
    :
    : "cc"
  );
}
#endif

MBED_NOINLINE
static int time_cpu_cycles(uint32_t cycles)
{
    Timer timer;
    timer.start();

    int timer_start = timer.read_us();

    uint32_t delay = cycles;
    delay_loop(delay);
    int timer_end = timer.read_us();

    timer.stop();
    return timer_end - timer_start;
}

void flash_init_test()
{
    timer_diff_start = time_cpu_cycles(TEST_CYCLES);

    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
}

void flash_mapping_alignment_test()
{
    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    const uint32_t page_size = flash_get_page_size(&test_flash);
    const uint32_t flash_start = flash_get_start_address(&test_flash);
    const uint32_t flash_size = flash_get_size(&test_flash);
    TEST_ASSERT_TRUE(page_size != 0UL);

    uint32_t sector_size = flash_get_sector_size(&test_flash, flash_start);
    for (uint32_t offset = 0; offset < flash_size;  offset += sector_size) {
        const uint32_t sector_start = flash_start + offset;
        sector_size = flash_get_sector_size(&test_flash, sector_start);
        const uint32_t sector_end = sector_start + sector_size - 1;
        const uint32_t end_sector_size = flash_get_sector_size(&test_flash, sector_end);

        // Sector size must be a valid value
        TEST_ASSERT_NOT_EQUAL(MBED_FLASH_INVALID_SIZE, sector_size);
        // Sector size must be greater than zero
        TEST_ASSERT_NOT_EQUAL(0, sector_size);
        // All flash sectors must be a multiple of page size
        TEST_ASSERT_EQUAL(0, sector_size % page_size);
        // Sector address must be a multiple of sector size
        TEST_ASSERT_EQUAL(0, sector_start % sector_size);
        // All address in a sector must return the same sector size
        TEST_ASSERT_EQUAL(sector_size, end_sector_size);
    }

    // Make sure unmapped flash is reported correctly
    TEST_ASSERT_EQUAL(MBED_FLASH_INVALID_SIZE, flash_get_sector_size(&test_flash, flash_start - 1));
    TEST_ASSERT_EQUAL(MBED_FLASH_INVALID_SIZE, flash_get_sector_size(&test_flash, flash_start + flash_size));

    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
}

void flash_erase_sector_test()
{
    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    uint32_t addr_after_last = flash_get_start_address(&test_flash) + flash_get_size(&test_flash);
    uint32_t last_sector_size = flash_get_sector_size(&test_flash, addr_after_last - 1);
    uint32_t last_sector = addr_after_last - last_sector_size;
    TEST_ASSERT_EQUAL_INT32(0, last_sector % last_sector_size);
    ret = flash_erase_sector(&test_flash, last_sector);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
}

// Erase sector, write one page, erase sector and write new data
void flash_program_page_test()
{
    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    uint32_t test_size = flash_get_page_size(&test_flash);
    uint8_t *data = new uint8_t[test_size];
    uint8_t *data_flashed = new uint8_t[test_size];
    for (uint32_t i = 0; i < test_size; i++) {
        data[i] = 0xCE;
    }

    // the one before the last page in the system
    uint32_t address = flash_get_start_address(&test_flash) + flash_get_size(&test_flash) - (2*test_size);

    // sector size might not be same as page size
    uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address));
    ret = flash_erase_sector(&test_flash, erase_sector_boundary);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    ret = flash_program_page(&test_flash, address, data, test_size);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    ret = flash_read(&test_flash, address, data_flashed, test_size);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, test_size);

    // sector size might not be same as page size
    erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address));
    ret = flash_erase_sector(&test_flash, erase_sector_boundary);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    // write another data to be certain we are re-flashing
    for (uint32_t i = 0; i < test_size; i++) {
        data[i] = 0xAC;
    }
    ret = flash_program_page(&test_flash, address, data, test_size);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    ret = flash_read(&test_flash, address, data_flashed, test_size);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, test_size);

    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    delete[] data;
    delete[] data_flashed;
}

// make sure programming works with an unaligned data buffer
void flash_buffer_alignment_test()
{
    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    const uint32_t page_size = flash_get_page_size(&test_flash);
    const uint32_t buf_size = page_size + 4;
    uint8_t *data = new uint8_t[buf_size];
    uint8_t *data_flashed = new uint8_t[buf_size];
    for (uint32_t i = 0; i < buf_size; i++) {
        data[i] = i & 0xFF;
    }

    // use the last four pages for the alignment test
    const uint32_t flash_end = flash_get_start_address(&test_flash) + flash_get_size(&test_flash);
    const uint32_t test_addr = flash_end - page_size * 4;
    const uint32_t erase_sector_boundary = ALIGN_DOWN(test_addr, flash_get_sector_size(&test_flash, test_addr));
    erase_range(&test_flash, erase_sector_boundary, flash_end - erase_sector_boundary);

    // make sure page program works with an unaligned data buffer
    for (uint32_t i = 0; i < 4; i++) {
        const uint32_t addr = test_addr + i * page_size;
        ret = flash_program_page(&test_flash, addr, data + i, page_size);
        TEST_ASSERT_EQUAL_INT32(0, ret);

        ret = flash_read(&test_flash, addr, data_flashed, page_size);
        TEST_ASSERT_EQUAL_INT32(0, ret);
        TEST_ASSERT_EQUAL_UINT8_ARRAY(data + i, data_flashed, page_size);
    }

    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    delete[] data;
    delete[] data_flashed;
}

// check the execution speed at the start and end of the test to make sure
// cache settings weren't changed
void flash_clock_and_cache_test()
{
    const int timer_diff_end = time_cpu_cycles(TEST_CYCLES);
    const int acceptable_range = timer_diff_start / (1000000 / ALLOWED_DRIFT_PPM);
    TEST_ASSERT_UINT32_WITHIN(acceptable_range, timer_diff_start, timer_diff_end);
}

Case cases[] = {
    Case("Flash - init", flash_init_test),
    Case("Flash - mapping alignment", flash_mapping_alignment_test),
    Case("Flash - erase sector", flash_erase_sector_test),
    Case("Flash - program page", flash_program_page_test),
    Case("Flash - buffer alignment test", flash_buffer_alignment_test),
    Case("Flash - clock and cache test", flash_clock_and_cache_test),
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
    GREENTEA_SETUP(20, "default_auto");
    return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main() {
    Harness::run(specification);
}
<commit_msg>gaurd thumb instruction for amrc6<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * 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.
 */

#if !DEVICE_FLASH
    #error [NOT_SUPPORTED] Flash API not supported for this target
#endif

#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"

#include "mbed.h"
#include "flash_api.h"

using namespace utest::v1;

#define TEST_CYCLES         1000000
#define ALLOWED_DRIFT_PPM   1000         //0.1%

/*
    return values to be checked are documented at:
        http://arm-software.github.io/CMSIS_5/Pack/html/algorithmFunc.html#Verify
*/

#ifndef ALIGN_DOWN
#define ALIGN_DOWN(x, a) ((x)& ~((a) - 1))
#endif

static int timer_diff_start;

static void erase_range(flash_t *flash, uint32_t addr, uint32_t size)
{
    while (size > 0) {
        uint32_t sector_size = flash_get_sector_size(flash, addr);
        TEST_ASSERT_NOT_EQUAL(0, sector_size);
        int32_t ret = flash_erase_sector(flash, addr);
        TEST_ASSERT_EQUAL_INT32(0, ret);
        addr += sector_size;
        size = size > sector_size ? size - sector_size : 0;
    }
}
#ifdef __CC_ARM
MBED_NOINLINE
__asm static void delay_loop(uint32_t count)
{
1
  SUBS a1, a1, #1
  BCS  %BT1
  BX   lr
}
#elif defined (__ICCARM__)
MBED_NOINLINE
static void delay_loop(uint32_t count)
{
  __asm volatile(
    "loop: \n"
    " SUBS %0, %0, #1 \n"
    " BCS.n  loop\n"
    : "+r" (count)
    :
    : "cc"
  );
}
#else // GCC
MBED_NOINLINE
static void delay_loop(uint32_t count)
{
  __asm__ volatile (
    "%=:\n\t"
#if defined(__thumb__) && !defined(__thumb2__) && !defined(TOOLCHAIN_ARMC6)
    "SUB  %0, #1\n\t"
#else
    "SUBS %0, %0, #1\n\t"
#endif
    "BCS  %=b\n\t"
    : "+l" (count)
    :
    : "cc"
  );
}
#endif

MBED_NOINLINE
static int time_cpu_cycles(uint32_t cycles)
{
    Timer timer;
    timer.start();

    int timer_start = timer.read_us();

    uint32_t delay = cycles;
    delay_loop(delay);
    int timer_end = timer.read_us();

    timer.stop();
    return timer_end - timer_start;
}

void flash_init_test()
{
    timer_diff_start = time_cpu_cycles(TEST_CYCLES);

    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
}

void flash_mapping_alignment_test()
{
    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    const uint32_t page_size = flash_get_page_size(&test_flash);
    const uint32_t flash_start = flash_get_start_address(&test_flash);
    const uint32_t flash_size = flash_get_size(&test_flash);
    TEST_ASSERT_TRUE(page_size != 0UL);

    uint32_t sector_size = flash_get_sector_size(&test_flash, flash_start);
    for (uint32_t offset = 0; offset < flash_size;  offset += sector_size) {
        const uint32_t sector_start = flash_start + offset;
        sector_size = flash_get_sector_size(&test_flash, sector_start);
        const uint32_t sector_end = sector_start + sector_size - 1;
        const uint32_t end_sector_size = flash_get_sector_size(&test_flash, sector_end);

        // Sector size must be a valid value
        TEST_ASSERT_NOT_EQUAL(MBED_FLASH_INVALID_SIZE, sector_size);
        // Sector size must be greater than zero
        TEST_ASSERT_NOT_EQUAL(0, sector_size);
        // All flash sectors must be a multiple of page size
        TEST_ASSERT_EQUAL(0, sector_size % page_size);
        // Sector address must be a multiple of sector size
        TEST_ASSERT_EQUAL(0, sector_start % sector_size);
        // All address in a sector must return the same sector size
        TEST_ASSERT_EQUAL(sector_size, end_sector_size);
    }

    // Make sure unmapped flash is reported correctly
    TEST_ASSERT_EQUAL(MBED_FLASH_INVALID_SIZE, flash_get_sector_size(&test_flash, flash_start - 1));
    TEST_ASSERT_EQUAL(MBED_FLASH_INVALID_SIZE, flash_get_sector_size(&test_flash, flash_start + flash_size));

    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
}

void flash_erase_sector_test()
{
    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    uint32_t addr_after_last = flash_get_start_address(&test_flash) + flash_get_size(&test_flash);
    uint32_t last_sector_size = flash_get_sector_size(&test_flash, addr_after_last - 1);
    uint32_t last_sector = addr_after_last - last_sector_size;
    TEST_ASSERT_EQUAL_INT32(0, last_sector % last_sector_size);
    ret = flash_erase_sector(&test_flash, last_sector);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
}

// Erase sector, write one page, erase sector and write new data
void flash_program_page_test()
{
    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    uint32_t test_size = flash_get_page_size(&test_flash);
    uint8_t *data = new uint8_t[test_size];
    uint8_t *data_flashed = new uint8_t[test_size];
    for (uint32_t i = 0; i < test_size; i++) {
        data[i] = 0xCE;
    }

    // the one before the last page in the system
    uint32_t address = flash_get_start_address(&test_flash) + flash_get_size(&test_flash) - (2*test_size);

    // sector size might not be same as page size
    uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address));
    ret = flash_erase_sector(&test_flash, erase_sector_boundary);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    ret = flash_program_page(&test_flash, address, data, test_size);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    ret = flash_read(&test_flash, address, data_flashed, test_size);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, test_size);

    // sector size might not be same as page size
    erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address));
    ret = flash_erase_sector(&test_flash, erase_sector_boundary);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    // write another data to be certain we are re-flashing
    for (uint32_t i = 0; i < test_size; i++) {
        data[i] = 0xAC;
    }
    ret = flash_program_page(&test_flash, address, data, test_size);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    ret = flash_read(&test_flash, address, data_flashed, test_size);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, test_size);

    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    delete[] data;
    delete[] data_flashed;
}

// make sure programming works with an unaligned data buffer
void flash_buffer_alignment_test()
{
    flash_t test_flash;
    int32_t ret = flash_init(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);

    const uint32_t page_size = flash_get_page_size(&test_flash);
    const uint32_t buf_size = page_size + 4;
    uint8_t *data = new uint8_t[buf_size];
    uint8_t *data_flashed = new uint8_t[buf_size];
    for (uint32_t i = 0; i < buf_size; i++) {
        data[i] = i & 0xFF;
    }

    // use the last four pages for the alignment test
    const uint32_t flash_end = flash_get_start_address(&test_flash) + flash_get_size(&test_flash);
    const uint32_t test_addr = flash_end - page_size * 4;
    const uint32_t erase_sector_boundary = ALIGN_DOWN(test_addr, flash_get_sector_size(&test_flash, test_addr));
    erase_range(&test_flash, erase_sector_boundary, flash_end - erase_sector_boundary);

    // make sure page program works with an unaligned data buffer
    for (uint32_t i = 0; i < 4; i++) {
        const uint32_t addr = test_addr + i * page_size;
        ret = flash_program_page(&test_flash, addr, data + i, page_size);
        TEST_ASSERT_EQUAL_INT32(0, ret);

        ret = flash_read(&test_flash, addr, data_flashed, page_size);
        TEST_ASSERT_EQUAL_INT32(0, ret);
        TEST_ASSERT_EQUAL_UINT8_ARRAY(data + i, data_flashed, page_size);
    }

    ret = flash_free(&test_flash);
    TEST_ASSERT_EQUAL_INT32(0, ret);
    delete[] data;
    delete[] data_flashed;
}

// check the execution speed at the start and end of the test to make sure
// cache settings weren't changed
void flash_clock_and_cache_test()
{
    const int timer_diff_end = time_cpu_cycles(TEST_CYCLES);
    const int acceptable_range = timer_diff_start / (1000000 / ALLOWED_DRIFT_PPM);
    TEST_ASSERT_UINT32_WITHIN(acceptable_range, timer_diff_start, timer_diff_end);
}

Case cases[] = {
    Case("Flash - init", flash_init_test),
    Case("Flash - mapping alignment", flash_mapping_alignment_test),
    Case("Flash - erase sector", flash_erase_sector_test),
    Case("Flash - program page", flash_program_page_test),
    Case("Flash - buffer alignment test", flash_buffer_alignment_test),
    Case("Flash - clock and cache test", flash_clock_and_cache_test),
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
    GREENTEA_SETUP(20, "default_auto");
    return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main() {
    Harness::run(specification);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2005 by Andrei Alexandrescu
// Permission to use, copy, modify, distribute, and sell this software for any
//     purpose is hereby granted without fee, provided that the above copyright
//     notice appear in all copies and that both that copyright notice and this
//     permission notice appear in supporting documentation.
// The author makes no representations about the suitability of this software
//     for any purpose. It is provided "as is" without express or implied
//     warranty.
////////////////////////////////////////////////////////////////////////////////

#include "loki/SafeFormat.h"
#include <iostream>
#include <cassert>
#include <utility>

using namespace std;

template <class Integral1, class Integral2>
Integral2 RandomInt(Integral1 low, Integral2 up)
{
    // From ``Accelerated C++'', page 135:
    // random integer in the range [0, n)
    // We adjust to generate in the range [0, n]
    const Integral2
    low2 = low,
           n = up - low;

    assert(n > 0);

    const unsigned int bucket_size = RAND_MAX / n;
    assert(bucket_size > 0);

    Integral2 r;
    do
        r = Integral2(rand() / bucket_size);
    while (r > n);

    r += low2;
    assert(r >= low2 && r <= up);
    return r;
}

string RandomString(unsigned int maxSize)
{
    string result(RandomInt(0, maxSize), '\0');
    unsigned int i = 0;
    for (; i != result.size(); ++i)
    {
        result[i] = RandomInt('a', 'z');
    }
    return result;
}

template <class T>
void TestCase(const string& fmt, T value)
{
    char buf[4096];
    std::string s;
    const int i1 = SPrintf(s, fmt.c_str())(value);

#ifdef _MSC_VER
    const int i2 = _snprintf(buf, sizeof(buf), fmt.c_str(), value);
#else
    const int i2 = snprintf(buf, sizeof(buf), fmt.c_str(), value);
#endif

    if (i1 != i2 || s != buf)
    {
        cout << endl
        << "Reference: " << i2 << "; Actual: " << i1 << ",  Difference = " << i2-i1 << endl
        << "V: [" << value << "]" << endl
        << "F: [" << fmt << "]" << endl
        << "R: [" << buf << "]" << endl
        << "A: [" << s.c_str() << "]" << endl;
        assert(false);
    }
}

template <class T, class U>
void TestCase2(const string& fmt, T value, U value2)
{
    char buf[4096];
    std::string s;
    const int i1 = SPrintf(s, fmt.c_str())(value)(value2);
    const int i2 = snprintf(buf, sizeof(buf), fmt.c_str(), value, value2);
    assert(i1 == i2);
    assert(s == buf);
}

int main(int argc, char** argv)
{
    if (argc == 3)
    {
        // test speed
        int i = atoi(argv[2]);
        switch (argv[1][0])
        {
        case 'p':
            for (; i > 0; --i)
            {
                printf("Hey, %u frobnicators and %u twiddlicators\n",
                       i, i);
            }
            break;
        case 's':
            for (; i > 0; --i)
            {
                cout << "Hey, " << i << " frobnicators and " << i <<
                " twiddlicators\n";
            }
            break;
        case 'n':
            for (; i > 0; --i)
            {
                Printf("Hey, %u frobnicators and %u twiddlicators\n")
                (i)(i);
            }
            break;
        }
        return 0;
    }

    //srand(time(0));
    srand(0);
    for (unsigned i = 0; ; ++i)
    {
        printf("%u\r", i);

        // Generate a random string for the head
        string lead = RandomString(100);
        // This string will hold a random format specification
        string formatSpec(lead + "|%");
        // Generate a random set of flags
        static const string flags("-+0 #");
        unsigned int maxFlags = RandomInt(0u, flags.length() - 1);
        for (unsigned int i = 0; i != maxFlags; ++i)
        {
            formatSpec += flags[RandomInt(0u, flags.length() - 1)];
        }
        // Generate an optional random width
        if (RandomInt(0, 1))
        {
            const unsigned int width = RandomInt(0, 100);
            char buf[4];
            sprintf(buf, "%u", width);
            formatSpec += buf;
        }
        // Generate an optional random precision
        if (RandomInt(0, 1))
        {
            const unsigned int prec = RandomInt(0, 100);
            char buf[4];
            sprintf(buf, "%u", prec);
            formatSpec += '.';
            formatSpec += buf;
        }
        // Generate a random type character
        static const string type("cdeEfgGinopsuxX");
        const char typeSpec = type[RandomInt(0, type.size() - 1)];
        // Generate an optional type prefix
        static const string prefix("hl");
        if (typeSpec != 's' && RandomInt(0, 1))
        {
            formatSpec += prefix[RandomInt(0, prefix.size() - 1)];
        }
        formatSpec += typeSpec;
        formatSpec += '|';
        formatSpec += RandomString(100);

        switch (typeSpec)
        {
        case 'c':
            TestCase(formatSpec, RandomInt(1, 127));
            break;
        case 'd':
        case 'i':
        case 'o':
        case 'u':
        case 'x':
        case 'X':
            TestCase(formatSpec, RandomInt(-10000, 10000));
            break;
        case 'e':
        case 'E':
        case 'f':
        case 'g':
        case 'G':
            TestCase(formatSpec,
                     RandomInt(-10000, 10000) / double(RandomInt(1, 100)));
            break;
        case 'n':
            break;
        case 'p':
            {
                void * p = malloc(RandomInt(1, 1000));
                TestCase(formatSpec, p);
                free(p);
            }
            break;
        case 's':
            TestCase(formatSpec, RandomString(100).c_str());
            break;
        default:
            assert(false);
            break;
        }
    }
}
<commit_msg>disable %p tests due to different snprintf implementations<commit_after>////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2005 by Andrei Alexandrescu
// Permission to use, copy, modify, distribute, and sell this software for any
//     purpose is hereby granted without fee, provided that the above copyright
//     notice appear in all copies and that both that copyright notice and this
//     permission notice appear in supporting documentation.
// The author makes no representations about the suitability of this software
//     for any purpose. It is provided "as is" without express or implied
//     warranty.
////////////////////////////////////////////////////////////////////////////////

#include "loki/SafeFormat.h"
#include <iostream>
#include <cassert>
#include <utility>

using namespace std;

template <class Integral1, class Integral2>
Integral2 RandomInt(Integral1 low, Integral2 up)
{
    // From ``Accelerated C++'', page 135:
    // random integer in the range [0, n)
    // We adjust to generate in the range [0, n]
    const Integral2
    low2 = low,
           n = up - low;

    assert(n > 0);

    const unsigned int bucket_size = RAND_MAX / n;
    assert(bucket_size > 0);

    Integral2 r;
    do
        r = Integral2(rand() / bucket_size);
    while (r > n);

    r += low2;
    assert(r >= low2 && r <= up);
    return r;
}

string RandomString(unsigned int maxSize)
{
    string result(RandomInt(0, maxSize), '\0');
    unsigned int i = 0;
    for (; i != result.size(); ++i)
    {
        result[i] = RandomInt('a', 'z');
    }
    return result;
}

template <class T>
void TestCase(const string& fmt, T value)
{
    char buf[4096];
    std::string s;
    const int i1 = SPrintf(s, fmt.c_str())(value);

#ifdef _MSC_VER
    const int i2 = _snprintf(buf, sizeof(buf), fmt.c_str(), value);
#else
    const int i2 = snprintf(buf, sizeof(buf), fmt.c_str(), value);
#endif

    if (i1 != i2 || s != buf)
    {
        cout << endl
        << "Reference: " << i2 << "; Actual: " << i1 << ",  Difference = " << i2-i1 << endl
        << "V: [" << value << "]" << endl
        << "F: [" << fmt << "]" << endl
        << "R: [" << buf << "]" << endl
        << "A: [" << s.c_str() << "]" << endl;
        assert(false);
    }
}

template <class T, class U>
void TestCase2(const string& fmt, T value, U value2)
{
    char buf[4096];
    std::string s;
    const int i1 = SPrintf(s, fmt.c_str())(value)(value2);
    const int i2 = snprintf(buf, sizeof(buf), fmt.c_str(), value, value2);
    assert(i1 == i2);
    assert(s == buf);
}

int main(int argc, char** argv)
{
    if (argc == 3)
    {
        // test speed
        int i = atoi(argv[2]);
        switch (argv[1][0])
        {
        case 'p':
            for (; i > 0; --i)
            {
                printf("Hey, %u frobnicators and %u twiddlicators\n",
                       i, i);
            }
            break;
        case 's':
            for (; i > 0; --i)
            {
                cout << "Hey, " << i << " frobnicators and " << i <<
                " twiddlicators\n";
            }
            break;
        case 'n':
            for (; i > 0; --i)
            {
                Printf("Hey, %u frobnicators and %u twiddlicators\n")
                (i)(i);
            }
            break;
        }
        return 0;
    }

    //srand(time(0));
    srand(0);
    for (unsigned i = 0; ; ++i)
    {
        printf("%u\r", i);

        // Generate a random string for the head
        string lead = RandomString(100);
        // This string will hold a random format specification
        string formatSpec(lead + "|%");
        // Generate a random set of flags
        static const string flags("-+0 #");
        unsigned int maxFlags = RandomInt(0u, flags.length() - 1);
        for (unsigned int i = 0; i != maxFlags; ++i)
        {
            formatSpec += flags[RandomInt(0u, flags.length() - 1)];
        }
        // Generate an optional random width
        if (RandomInt(0, 1))
        {
            const unsigned int width = RandomInt(0, 100);
            char buf[4];
            sprintf(buf, "%u", width);
            formatSpec += buf;
        }
        // Generate an optional random precision
        if (RandomInt(0, 1))
        {
            const unsigned int prec = RandomInt(0, 100);
            char buf[4];
            sprintf(buf, "%u", prec);
            formatSpec += '.';
            formatSpec += buf;
        }

        // Generate a random type character
        /* disable %p tests
        static const string type("cdeEfgGinopsuxX");*/
        static const string type("cdeEfgGinosuxX");

        const char typeSpec = type[RandomInt(0, type.size() - 1)];
        // Generate an optional type prefix
        static const string prefix("hl");
        if (typeSpec != 's' && RandomInt(0, 1))
        {
            formatSpec += prefix[RandomInt(0, prefix.size() - 1)];
        }
        formatSpec += typeSpec;
        formatSpec += '|';
        formatSpec += RandomString(100);

        switch (typeSpec)
        {
        case 'c':
            TestCase(formatSpec, RandomInt(1, 127));
            break;
        case 'd':
        case 'i':
        case 'o':
        case 'u':
        case 'x':
        case 'X':
            TestCase(formatSpec, RandomInt(-10000, 10000));
            break;
        case 'e':
        case 'E':
        case 'f':
        case 'g':
        case 'G':
            TestCase(formatSpec,
                     RandomInt(-10000, 10000) / double(RandomInt(1, 100)));
            break;
        case 'n':
            break;
        case 'p':
            {
                void * p = malloc(RandomInt(1, 1000));
                TestCase(formatSpec, p);
                free(p);
            }
            break;
        case 's':
            TestCase(formatSpec, RandomString(100).c_str());
            break;
        default:
            assert(false);
            break;
        }
    }
}
<|endoftext|>


<commit_before>#pragma once
/**
	@file
	@brief operator class
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/op.hpp>
#include <mcl/util.hpp>
#ifdef _MSC_VER
	#ifndef MCL_FORCE_INLINE
		#define MCL_FORCE_INLINE __forceinline
	#endif
	#pragma warning(push)
	#pragma warning(disable : 4714)
#else
	#ifndef MCL_FORCE_INLINE
		#define MCL_FORCE_INLINE __attribute__((always_inline))
	#endif
#endif

namespace mcl { namespace fp {

template<class T>
struct Empty {};

/*
	T must have add, sub, mul, inv, neg
*/
template<class T, class E = Empty<T> >
struct Operator : public E {
	template<class S> MCL_FORCE_INLINE T& operator+=(const S& rhs) { T::add(static_cast<T&>(*this), static_cast<const T&>(*this), rhs); return static_cast<T&>(*this); }
	template<class S> MCL_FORCE_INLINE T& operator-=(const S& rhs) { T::sub(static_cast<T&>(*this), static_cast<const T&>(*this), rhs); return static_cast<T&>(*this); }
	template<class S> friend MCL_FORCE_INLINE T operator+(const T& a, const S& b) { T c; T::add(c, a, b); return c; }
	template<class S> friend MCL_FORCE_INLINE T operator-(const T& a, const S& b) { T c; T::sub(c, a, b); return c; }
	template<class S> MCL_FORCE_INLINE T& operator*=(const S& rhs) { T::mul(static_cast<T&>(*this), static_cast<const T&>(*this), rhs); return static_cast<T&>(*this); }
	template<class S> friend MCL_FORCE_INLINE T operator*(const T& a, const S& b) { T c; T::mul(c, a, b); return c; }
	MCL_FORCE_INLINE T& operator/=(const T& rhs) { T c; T::inv(c, rhs); T::mul(static_cast<T&>(*this), static_cast<const T&>(*this), c); return static_cast<T&>(*this); }
	static MCL_FORCE_INLINE void div(T& c, const T& a, const T& b) { T t; T::inv(t, b); T::mul(c, a, t); }
	friend MCL_FORCE_INLINE T operator/(const T& a, const T& b) { T c; T::inv(c, b); c *= a; return c; }
	MCL_FORCE_INLINE T operator-() const { T c; T::neg(c, static_cast<const T&>(*this)); return c; }
	template<class tag2, size_t maxBitSize2, template<class _tag, size_t _maxBitSize> class FpT>
	static void pow(T& z, const T& x, const FpT<tag2, maxBitSize2>& y)
	{
		fp::Block b;
		y.getBlock(b);
		powArray(z, x, b.p, b.n, false, false);
	}
	template<class tag2, size_t maxBitSize2, template<class _tag, size_t _maxBitSize> class FpT>
	static void powGeneric(T& z, const T& x, const FpT<tag2, maxBitSize2>& y)
	{
		fp::Block b;
		y.getBlock(b);
		powArrayBase(z, x, b.p, b.n, false, false);
	}
	template<class tag2, size_t maxBitSize2, template<class _tag, size_t _maxBitSize> class FpT>
	static void powCT(T& z, const T& x, const FpT<tag2, maxBitSize2>& y)
	{
		fp::Block b;
		y.getBlock(b);
		powArray(z, x, b.p, b.n, false, true);
	}
	static void pow(T& z, const T& x, int64_t y)
	{
		const uint64_t u = fp::abs_(y);
#if MCL_SIZEOF_UNIT == 8
		powArray(z, x, &u, 1, y < 0, false);
#else
		uint32_t ua[2] = { uint32_t(u), uint32_t(u >> 32) };
		size_t un = ua[1] ? 2 : 1;
		powArray(z, x, ua, un, y < 0, false);
#endif
	}
	static void pow(T& z, const T& x, const mpz_class& y)
	{
		powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, false);
	}
	static void powGeneric(T& z, const T& x, const mpz_class& y)
	{
		powArrayBase(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, false);
	}
	static void powCT(T& z, const T& x, const mpz_class& y)
	{
		powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, true);
	}
	static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime), size_t g(T& z, const T *xVec, const mpz_class *yVec, size_t n) = 0)
	{
		powArrayGLV = f;
		powVecNGLV = g;
	}
	static const size_t powVecMaxN = 16;
	template<class tag, size_t maxBitSize, template<class _tag, size_t _maxBitSize>class FpT>
	static void powVec(T& z, const T* xVec, const FpT<tag, maxBitSize> *yVec, size_t n)
	{
		assert(powVecNGLV);
		T r;
		r.setOne();
		const size_t N = mcl::fp::maxMulVecNGLV;
		mpz_class myVec[N];
		while (n > 0) {
			T t;
			size_t tn = fp::min_(n, N);
			for (size_t i = 0; i < tn; i++) {
				bool b;
				yVec[i].getMpz(&b, myVec[i]);
				assert(b); (void)b;
			}
			size_t done = powVecNGLV(t, xVec, myVec, tn);
			r *= t;
			xVec += done;
			yVec += done;
			n -= done;
		}
		z = r;
	}
private:
	static void (*powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);
	static size_t (*powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n);
	static void powArray(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)
	{
		if (powArrayGLV && (constTime || yn > 1)) {
			powArrayGLV(z, x, y, yn, isNegative, constTime);
			return;
		}
		powArrayBase(z, x, y, yn, isNegative, constTime);
	}
	static void powArrayBase(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)
	{
		T tmp;
		const T *px = &x;
		if (&z == &x) {
			tmp = x;
			px = &tmp;
		}
		z = 1;
		fp::powGeneric(z, *px, y, yn, T::mul, T::sqr, (void (*)(T&, const T&))0, constTime ? T::BaseFp::getBitSize() : 0);
		if (isNegative) {
			T::inv(z, z);
		}
	}
};

template<class T, class E>
void (*Operator<T, E>::powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);

template<class T, class E>
size_t (*Operator<T, E>::powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n);

/*
	T must have save and load
*/
template<class T, class E = Empty<T> >
struct Serializable : public E {
	void setStr(bool *pb, const char *str, int ioMode = 0)
	{
		size_t len = strlen(str);
		size_t n = deserialize(str, len, ioMode);
		*pb = n > 0 && n == len;
	}
	// return strlen(buf) if success else 0
	size_t getStr(char *buf, size_t maxBufSize, int ioMode = 0) const
	{
		size_t n = serialize(buf, maxBufSize, ioMode);
		if (n == 0 || n == maxBufSize - 1) return 0;
		buf[n] = '\0';
		return n;
	}
#ifndef CYBOZU_DONT_USE_STRING
	void setStr(const std::string& str, int ioMode = 0)
	{
		cybozu::StringInputStream is(str);
		static_cast<T&>(*this).load(is, ioMode);
	}
	void getStr(std::string& str, int ioMode = 0) const
	{
		str.clear();
		cybozu::StringOutputStream os(str);
		static_cast<const T&>(*this).save(os, ioMode);
	}
	std::string getStr(int ioMode = 0) const
	{
		std::string str;
		getStr(str, ioMode);
		return str;
	}
	std::string serializeToHexStr() const
	{
		std::string str(sizeof(T) * 2, 0);
		size_t n = serialize(&str[0], str.size(), IoSerializeHexStr);
		str.resize(n);
		return str;
	}
#ifndef CYBOZU_DONT_USE_EXCEPTION
	void deserializeHexStr(const std::string& str)
	{
		size_t n = deserialize(str.c_str(), str.size(), IoSerializeHexStr);
		if (n == 0) throw cybozu::Exception("bad str") << str;
	}
#endif
#endif
	// return written bytes
	size_t serialize(void *buf, size_t maxBufSize, int ioMode = IoSerialize) const
	{
		cybozu::MemoryOutputStream os(buf, maxBufSize);
		bool b;
		static_cast<const T&>(*this).save(&b, os, ioMode);
		return b ? os.getPos() : 0;
	}
	// return read bytes
	size_t deserialize(const void *buf, size_t bufSize, int ioMode = IoSerialize)
	{
		cybozu::MemoryInputStream is(buf, bufSize);
		bool b;
		static_cast<T&>(*this).load(&b, is, ioMode);
		return b ? is.getPos() : 0;
	}
};

} } // mcl::fp

<commit_msg>[doc] add comment to setStr<commit_after>#pragma once
/**
	@file
	@brief operator class
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/op.hpp>
#include <mcl/util.hpp>
#ifdef _MSC_VER
	#ifndef MCL_FORCE_INLINE
		#define MCL_FORCE_INLINE __forceinline
	#endif
	#pragma warning(push)
	#pragma warning(disable : 4714)
#else
	#ifndef MCL_FORCE_INLINE
		#define MCL_FORCE_INLINE __attribute__((always_inline))
	#endif
#endif

namespace mcl { namespace fp {

template<class T>
struct Empty {};

/*
	T must have add, sub, mul, inv, neg
*/
template<class T, class E = Empty<T> >
struct Operator : public E {
	template<class S> MCL_FORCE_INLINE T& operator+=(const S& rhs) { T::add(static_cast<T&>(*this), static_cast<const T&>(*this), rhs); return static_cast<T&>(*this); }
	template<class S> MCL_FORCE_INLINE T& operator-=(const S& rhs) { T::sub(static_cast<T&>(*this), static_cast<const T&>(*this), rhs); return static_cast<T&>(*this); }
	template<class S> friend MCL_FORCE_INLINE T operator+(const T& a, const S& b) { T c; T::add(c, a, b); return c; }
	template<class S> friend MCL_FORCE_INLINE T operator-(const T& a, const S& b) { T c; T::sub(c, a, b); return c; }
	template<class S> MCL_FORCE_INLINE T& operator*=(const S& rhs) { T::mul(static_cast<T&>(*this), static_cast<const T&>(*this), rhs); return static_cast<T&>(*this); }
	template<class S> friend MCL_FORCE_INLINE T operator*(const T& a, const S& b) { T c; T::mul(c, a, b); return c; }
	MCL_FORCE_INLINE T& operator/=(const T& rhs) { T c; T::inv(c, rhs); T::mul(static_cast<T&>(*this), static_cast<const T&>(*this), c); return static_cast<T&>(*this); }
	static MCL_FORCE_INLINE void div(T& c, const T& a, const T& b) { T t; T::inv(t, b); T::mul(c, a, t); }
	friend MCL_FORCE_INLINE T operator/(const T& a, const T& b) { T c; T::inv(c, b); c *= a; return c; }
	MCL_FORCE_INLINE T operator-() const { T c; T::neg(c, static_cast<const T&>(*this)); return c; }
	template<class tag2, size_t maxBitSize2, template<class _tag, size_t _maxBitSize> class FpT>
	static void pow(T& z, const T& x, const FpT<tag2, maxBitSize2>& y)
	{
		fp::Block b;
		y.getBlock(b);
		powArray(z, x, b.p, b.n, false, false);
	}
	template<class tag2, size_t maxBitSize2, template<class _tag, size_t _maxBitSize> class FpT>
	static void powGeneric(T& z, const T& x, const FpT<tag2, maxBitSize2>& y)
	{
		fp::Block b;
		y.getBlock(b);
		powArrayBase(z, x, b.p, b.n, false, false);
	}
	template<class tag2, size_t maxBitSize2, template<class _tag, size_t _maxBitSize> class FpT>
	static void powCT(T& z, const T& x, const FpT<tag2, maxBitSize2>& y)
	{
		fp::Block b;
		y.getBlock(b);
		powArray(z, x, b.p, b.n, false, true);
	}
	static void pow(T& z, const T& x, int64_t y)
	{
		const uint64_t u = fp::abs_(y);
#if MCL_SIZEOF_UNIT == 8
		powArray(z, x, &u, 1, y < 0, false);
#else
		uint32_t ua[2] = { uint32_t(u), uint32_t(u >> 32) };
		size_t un = ua[1] ? 2 : 1;
		powArray(z, x, ua, un, y < 0, false);
#endif
	}
	static void pow(T& z, const T& x, const mpz_class& y)
	{
		powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, false);
	}
	static void powGeneric(T& z, const T& x, const mpz_class& y)
	{
		powArrayBase(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, false);
	}
	static void powCT(T& z, const T& x, const mpz_class& y)
	{
		powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, true);
	}
	static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime), size_t g(T& z, const T *xVec, const mpz_class *yVec, size_t n) = 0)
	{
		powArrayGLV = f;
		powVecNGLV = g;
	}
	static const size_t powVecMaxN = 16;
	template<class tag, size_t maxBitSize, template<class _tag, size_t _maxBitSize>class FpT>
	static void powVec(T& z, const T* xVec, const FpT<tag, maxBitSize> *yVec, size_t n)
	{
		assert(powVecNGLV);
		T r;
		r.setOne();
		const size_t N = mcl::fp::maxMulVecNGLV;
		mpz_class myVec[N];
		while (n > 0) {
			T t;
			size_t tn = fp::min_(n, N);
			for (size_t i = 0; i < tn; i++) {
				bool b;
				yVec[i].getMpz(&b, myVec[i]);
				assert(b); (void)b;
			}
			size_t done = powVecNGLV(t, xVec, myVec, tn);
			r *= t;
			xVec += done;
			yVec += done;
			n -= done;
		}
		z = r;
	}
private:
	static void (*powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);
	static size_t (*powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n);
	static void powArray(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)
	{
		if (powArrayGLV && (constTime || yn > 1)) {
			powArrayGLV(z, x, y, yn, isNegative, constTime);
			return;
		}
		powArrayBase(z, x, y, yn, isNegative, constTime);
	}
	static void powArrayBase(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)
	{
		T tmp;
		const T *px = &x;
		if (&z == &x) {
			tmp = x;
			px = &tmp;
		}
		z = 1;
		fp::powGeneric(z, *px, y, yn, T::mul, T::sqr, (void (*)(T&, const T&))0, constTime ? T::BaseFp::getBitSize() : 0);
		if (isNegative) {
			T::inv(z, z);
		}
	}
};

template<class T, class E>
void (*Operator<T, E>::powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);

template<class T, class E>
size_t (*Operator<T, E>::powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n);

/*
	T must have save and load
*/
template<class T, class E = Empty<T> >
struct Serializable : public E {
	// may set *pb = false if the size of str is too large.
	void setStr(bool *pb, const char *str, int ioMode = 0)
	{
		size_t len = strlen(str);
		size_t n = deserialize(str, len, ioMode);
		*pb = n > 0 && n == len;
	}
	// return strlen(buf) if success else 0
	size_t getStr(char *buf, size_t maxBufSize, int ioMode = 0) const
	{
		size_t n = serialize(buf, maxBufSize, ioMode);
		if (n == 0 || n == maxBufSize - 1) return 0;
		buf[n] = '\0';
		return n;
	}
#ifndef CYBOZU_DONT_USE_STRING
	// may throw exception if the size of str is too large.
	void setStr(const std::string& str, int ioMode = 0)
	{
		cybozu::StringInputStream is(str);
		static_cast<T&>(*this).load(is, ioMode);
	}
	void getStr(std::string& str, int ioMode = 0) const
	{
		str.clear();
		cybozu::StringOutputStream os(str);
		static_cast<const T&>(*this).save(os, ioMode);
	}
	std::string getStr(int ioMode = 0) const
	{
		std::string str;
		getStr(str, ioMode);
		return str;
	}
	std::string serializeToHexStr() const
	{
		std::string str(sizeof(T) * 2, 0);
		size_t n = serialize(&str[0], str.size(), IoSerializeHexStr);
		str.resize(n);
		return str;
	}
#ifndef CYBOZU_DONT_USE_EXCEPTION
	void deserializeHexStr(const std::string& str)
	{
		size_t n = deserialize(str.c_str(), str.size(), IoSerializeHexStr);
		if (n == 0) throw cybozu::Exception("bad str") << str;
	}
#endif
#endif
	// return written bytes
	size_t serialize(void *buf, size_t maxBufSize, int ioMode = IoSerialize) const
	{
		cybozu::MemoryOutputStream os(buf, maxBufSize);
		bool b;
		static_cast<const T&>(*this).save(&b, os, ioMode);
		return b ? os.getPos() : 0;
	}
	// return read bytes
	size_t deserialize(const void *buf, size_t bufSize, int ioMode = IoSerialize)
	{
		cybozu::MemoryInputStream is(buf, bufSize);
		bool b;
		static_cast<T&>(*this).load(&b, is, ioMode);
		return b ? is.getPos() : 0;
	}
};

} } // mcl::fp

<|endoftext|>


<commit_before>#include <iostream>

#include <easycoco.h>
#include <easycomplex.h>
#include <easyanim.h>
#include <easyscale9.h>
#include <easymesh.h>
#include <easyterrain2d.h>
#include <easytexture.h>
#include <easyicon.h>

#define CHARACTER

std::vector<const d2d::ISymbol*> SYMBOLS;

libcoco::TextureMgr TEX_MGR;

std::set<std::string> IGNORE_LIST;

static void InitSymbolCreators()
{
	d2d::SymbolFactory::RegisterCreator(ecomplex::FILE_TAG, &ecomplex::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(ecomplex::FILE_TAG, &ecomplex::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(libanim::FILE_TAG, &libanim::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(libanim::FILE_TAG, &libanim::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(escale9::FILE_TAG, &escale9::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(escale9::FILE_TAG, &escale9::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(emesh::FILE_TAG, &emesh::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(emesh::FILE_TAG, &emesh::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(eterrain2d::FILE_TAG, &eterrain2d::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(eterrain2d::FILE_TAG, &eterrain2d::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(etexture::FILE_TAG, &etexture::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(etexture::FILE_TAG, &etexture::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(eicon::FILE_TAG, &eicon::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(eicon::FILE_TAG, &eicon::Sprite::Create);
}

void LoadAllFilesSorted(const std::string& dir, std::set<std::string>& files_sorted)
{
	wxArrayString files;
	d2d::FilenameTools::fetchAllFiles(dir, files);

	for (int i = 0, n = files.size(); i < n; ++i)
	{
		wxFileName filename(files[i]);
		filename.Normalize();
		wxString filepath = filename.GetFullPath();
		files_sorted.insert(filepath.ToStdString());
	}
}

void LoadFromDir(const std::string& dir)
{
	std::set<std::string> files_sorted;
	LoadAllFilesSorted(dir, files_sorted);

	try {
		std::set<std::string>::iterator itr = files_sorted.begin();
		for ( ; itr != files_sorted.end(); ++itr)
		{
			if (d2d::FileNameParser::isType(*itr, d2d::FileNameParser::e_complex)
				|| d2d::FileNameParser::isType(*itr, d2d::FileNameParser::e_anim))
			{
				// todo release symbol
				d2d::ISymbol* symbol = d2d::SymbolMgr::Instance()->FetchSymbol(*itr);
				SYMBOLS.push_back(symbol);
			}
		}
	} catch (d2d::Exception& e) {
		std::cerr << e.what() << std::endl;
	}
}

void LoadFromList(const std::string& list)
{
	std::set<std::string> names;

	wxString ext = d2d::FilenameTools::getExtension(list).Lower();
	if (ext == "txt")
	{
		std::locale::global(std::locale(""));
		std::ifstream fin(list.c_str());
		std::locale::global(std::locale("C"));

		std::string str;
		while (getline(fin, str)) {
			names.insert(str);
		}

		fin.close();
	}
	else if (ext == "json")
	{
		Json::Value value;
		Json::Reader reader;
		std::locale::global(std::locale(""));
		std::ifstream fin(list.c_str());
		std::locale::global(std::locale("C"));
		reader.parse(fin, value);
		fin.close();

		int i = 0;
		Json::Value itemValue = value["items"][i++];
		while (!itemValue.isNull()) {
			std::string name = itemValue["name"].asString();
			names.insert(name);
			itemValue = value["items"][i++];
		}
	}
	else
	{
		std::cerr << "unsupported format " << ext << std::endl;
		return;
	}

	wxString dir = d2d::FilenameTools::getFileDir(list);

	std::set<std::string> files_sorted;
	LoadAllFilesSorted(dir.ToStdString(), files_sorted);

	try {
		std::set<std::string>::iterator itr = files_sorted.begin();
		for ( ; itr != files_sorted.end(); ++itr)
		{
			if (d2d::FileNameParser::isType(*itr, d2d::FileNameParser::e_complex)
				|| d2d::FileNameParser::isType(*itr, d2d::FileNameParser::e_anim))
			{
				// todo release symbol
				d2d::ISymbol* symbol = d2d::SymbolMgr::Instance()->FetchSymbol(*itr);
				std::set<std::string>::iterator itr = names.find(symbol->name);
				if (itr == names.end()) {
//					symbol->release();
				} else {
					SYMBOLS.push_back(symbol);
				}
			}
		}
	} catch (d2d::Exception& e) {
		std::cerr << e.what() << std::endl;
	}
}

void LoadTexturePacker(std::string texpackerpath)
{
	size_t i = 1;
	while (true)
	{
		std::string path = texpackerpath + wxString::FromDouble(i) + ".json";
		if (wxFileName::FileExists(path))
			TEX_MGR.Add(path, i-1);
		else
			break;
		++i;
	}
}

void DetectScale(int idx, char *argv[], float& scale)
{
	std::string opt = argv[idx];
	if (opt == "-s" || opt == "--scale") {
		scale = atof(argv[idx+1]);
	}
}

void DetectIgnoreFile(int idx, char *argv[], std::string& ignore_file)
{
	std::string opt = argv[idx];
	if (opt == "-i" || opt == "--ignore") {
		ignore_file = argv[idx+1];
	}
}

void ParamsDetection(int argc, char *argv[], float& scale, std::string& ignore_file)
{
	for (int i = 4; i < argc; i += 2)
	{
		DetectScale(i, argv, scale);
		DetectIgnoreFile(i, argv, ignore_file);
	}
}

void LoadIgnoreList(const std::string& filename)
{
	wxString ext = d2d::FilenameTools::getExtension(filename).Lower();

	std::set<std::string> list;

	std::locale::global(std::locale(""));
	std::ifstream fin(filename.c_str());
	std::locale::global(std::locale("C"));

	std::string str;
	while (getline(fin, str)) {
		list.insert(str);
	}

	fin.close();

	IGNORE_LIST = list;
}

int main(int argc, char *argv[])
{
	wxInitializer initializer;
	if ( !initializer )
	{
		fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
		return -1;
	}

	if (argc < 4) {
		std::cerr << "Need Resource Dir & Texture Packer Filepath & Output filepath !" << std::endl;
		return 1;
	}

	InitSymbolCreators();

	float gscale = 1.0f;
	std::string ignore_file;
	if (argc > 4) {
		ParamsDetection(argc, argv, gscale, ignore_file);
	}
	if (!ignore_file.empty()) {
		LoadIgnoreList(ignore_file);
	}

	std::string texpackerpath = argv[2];
	d2d::SearcherPathMgr::Instance()->ResetPackRes(texpackerpath);

	std::string path = argv[1];
	bool is_dir = false;
	int pos_dot = path.find_last_of('.');
	int pos_divide = std::max((int)path.find_last_of('/'), (int)path.find_last_of('\\'));
	if (pos_dot == std::string::npos || pos_dot < pos_divide) {
		is_dir = true;
	}

	std::cout << "Load json data \n";
	if (is_dir) {
		LoadFromDir(path);
	} else {
		LoadFromList(path);
	}

	std::cout << "Load tp data \n";

	LoadTexturePacker(texpackerpath);

	try {
		libcoco::CocoPacker packer(SYMBOLS, TEX_MGR);
		packer.Parser();
		packer.Output(argv[3]);
	} catch (d2d::Exception& e) {
		std::cerr << e.what() << std::endl;
	}

	return 0;
}<commit_msg>[FIXED] coco pack 关闭render<commit_after>#include <iostream>

#include <easycoco.h>
#include <easycomplex.h>
#include <easyanim.h>
#include <easyscale9.h>
#include <easymesh.h>
#include <easyterrain2d.h>
#include <easytexture.h>
#include <easyicon.h>

#define CHARACTER

std::vector<const d2d::ISymbol*> SYMBOLS;

libcoco::TextureMgr TEX_MGR;

std::set<std::string> IGNORE_LIST;

static void InitSymbolCreators()
{
	d2d::SymbolFactory::RegisterCreator(ecomplex::FILE_TAG, &ecomplex::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(ecomplex::FILE_TAG, &ecomplex::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(libanim::FILE_TAG, &libanim::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(libanim::FILE_TAG, &libanim::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(escale9::FILE_TAG, &escale9::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(escale9::FILE_TAG, &escale9::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(emesh::FILE_TAG, &emesh::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(emesh::FILE_TAG, &emesh::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(eterrain2d::FILE_TAG, &eterrain2d::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(eterrain2d::FILE_TAG, &eterrain2d::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(etexture::FILE_TAG, &etexture::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(etexture::FILE_TAG, &etexture::Sprite::Create);

	d2d::SymbolFactory::RegisterCreator(eicon::FILE_TAG, &eicon::Symbol::Create);
	d2d::SpriteFactory::Instance()->RegisterCreator(eicon::FILE_TAG, &eicon::Sprite::Create);
}

void LoadAllFilesSorted(const std::string& dir, std::set<std::string>& files_sorted)
{
	wxArrayString files;
	d2d::FilenameTools::fetchAllFiles(dir, files);

	for (int i = 0, n = files.size(); i < n; ++i)
	{
		wxFileName filename(files[i]);
		filename.Normalize();
		wxString filepath = filename.GetFullPath();
		files_sorted.insert(filepath.ToStdString());
	}
}

void LoadFromDir(const std::string& dir)
{
	std::set<std::string> files_sorted;
	LoadAllFilesSorted(dir, files_sorted);

	try {
		std::set<std::string>::iterator itr = files_sorted.begin();
		for ( ; itr != files_sorted.end(); ++itr)
		{
			if (d2d::FileNameParser::isType(*itr, d2d::FileNameParser::e_complex)
				|| d2d::FileNameParser::isType(*itr, d2d::FileNameParser::e_anim))
			{
				// todo release symbol
				d2d::ISymbol* symbol = d2d::SymbolMgr::Instance()->FetchSymbol(*itr);
				SYMBOLS.push_back(symbol);
			}
		}
	} catch (d2d::Exception& e) {
		std::cerr << e.what() << std::endl;
	}
}

void LoadFromList(const std::string& list)
{
	std::set<std::string> names;

	wxString ext = d2d::FilenameTools::getExtension(list).Lower();
	if (ext == "txt")
	{
		std::locale::global(std::locale(""));
		std::ifstream fin(list.c_str());
		std::locale::global(std::locale("C"));

		std::string str;
		while (getline(fin, str)) {
			names.insert(str);
		}

		fin.close();
	}
	else if (ext == "json")
	{
		Json::Value value;
		Json::Reader reader;
		std::locale::global(std::locale(""));
		std::ifstream fin(list.c_str());
		std::locale::global(std::locale("C"));
		reader.parse(fin, value);
		fin.close();

		int i = 0;
		Json::Value itemValue = value["items"][i++];
		while (!itemValue.isNull()) {
			std::string name = itemValue["name"].asString();
			names.insert(name);
			itemValue = value["items"][i++];
		}
	}
	else
	{
		std::cerr << "unsupported format " << ext << std::endl;
		return;
	}

	wxString dir = d2d::FilenameTools::getFileDir(list);

	std::set<std::string> files_sorted;
	LoadAllFilesSorted(dir.ToStdString(), files_sorted);

	try {
		std::set<std::string>::iterator itr = files_sorted.begin();
		for ( ; itr != files_sorted.end(); ++itr)
		{
			if (d2d::FileNameParser::isType(*itr, d2d::FileNameParser::e_complex)
				|| d2d::FileNameParser::isType(*itr, d2d::FileNameParser::e_anim))
			{
				// todo release symbol
				d2d::ISymbol* symbol = d2d::SymbolMgr::Instance()->FetchSymbol(*itr);
				std::set<std::string>::iterator itr = names.find(symbol->name);
				if (itr == names.end()) {
//					symbol->release();
				} else {
					SYMBOLS.push_back(symbol);
				}
			}
		}
	} catch (d2d::Exception& e) {
		std::cerr << e.what() << std::endl;
	}
}

void LoadTexturePacker(std::string texpackerpath)
{
	size_t i = 1;
	while (true)
	{
		std::string path = texpackerpath + wxString::FromDouble(i) + ".json";
		if (wxFileName::FileExists(path))
			TEX_MGR.Add(path, i-1);
		else
			break;
		++i;
	}
}

void DetectScale(int idx, char *argv[], float& scale)
{
	std::string opt = argv[idx];
	if (opt == "-s" || opt == "--scale") {
		scale = atof(argv[idx+1]);
	}
}

void DetectIgnoreFile(int idx, char *argv[], std::string& ignore_file)
{
	std::string opt = argv[idx];
	if (opt == "-i" || opt == "--ignore") {
		ignore_file = argv[idx+1];
	}
}

void ParamsDetection(int argc, char *argv[], float& scale, std::string& ignore_file)
{
	for (int i = 4; i < argc; i += 2)
	{
		DetectScale(i, argv, scale);
		DetectIgnoreFile(i, argv, ignore_file);
	}
}

void LoadIgnoreList(const std::string& filename)
{
	wxString ext = d2d::FilenameTools::getExtension(filename).Lower();

	std::set<std::string> list;

	std::locale::global(std::locale(""));
	std::ifstream fin(filename.c_str());
	std::locale::global(std::locale("C"));

	std::string str;
	while (getline(fin, str)) {
		list.insert(str);
	}

	fin.close();

	IGNORE_LIST = list;
}

int main(int argc, char *argv[])
{
	wxInitializer initializer;
	if ( !initializer )
	{
		fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
		return -1;
	}

	if (argc < 4) {
		std::cerr << "Need Resource Dir & Texture Packer Filepath & Output filepath !" << std::endl;
		return 1;
	}

	d2d::Config::Instance()->EnableRender(false);

	InitSymbolCreators();

	float gscale = 1.0f;
	std::string ignore_file;
	if (argc > 4) {
		ParamsDetection(argc, argv, gscale, ignore_file);
	}
	if (!ignore_file.empty()) {
		LoadIgnoreList(ignore_file);
	}

	std::string texpackerpath = argv[2];
	d2d::SearcherPathMgr::Instance()->ResetPackRes(texpackerpath);

	std::string path = argv[1];
	bool is_dir = false;
	int pos_dot = path.find_last_of('.');
	int pos_divide = std::max((int)path.find_last_of('/'), (int)path.find_last_of('\\'));
	if (pos_dot == std::string::npos || pos_dot < pos_divide) {
		is_dir = true;
	}

	std::cout << "Load json data \n";
	if (is_dir) {
		LoadFromDir(path);
	} else {
		LoadFromList(path);
	}

	std::cout << "Load tp data \n";

	LoadTexturePacker(texpackerpath);

	try {
		libcoco::CocoPacker packer(SYMBOLS, TEX_MGR);
		packer.Parser();
		packer.Output(argv[3]);
	} catch (d2d::Exception& e) {
		std::cerr << e.what() << std::endl;
	}

	return 0;
}<|endoftext|>


<commit_before><commit_msg>fix Qt4 build failure<commit_after><|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /fs/turing/cvs/copasi_dev/cvs_admin/addHeader,v $
//   $Revision: 1.11 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2009/07/14 11:09:51 $
// End CVS Header
// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include "CQExpressionMmlStackedWidget.h"

#include "utilities/CCopasiException.h"

#include "CQMessageBox.h"
#include "qtUtilities.h" // for UTF8
#include "CopasiFileDialog.h"
#include "tex/CMathMLToTeX.h"

#include <QtDebug>

/*
 *  Constructs a CQExpressionMmlWidget as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
CQExpressionMmlStackedWidget::CQExpressionMmlStackedWidget(QWidget* parent)
    : QStackedWidget(parent)
{
  setupUi(this);

  const QIcon icon = qt_get_icon(image0_ID);
  mpBtnExpressionObject->setIcon(icon);

  const QIcon icon1 = qt_get_icon(image1_ID);
  mpBtnViewExpression->setIcon(icon1);

  const QIcon icon2 = qt_get_icon(image2_ID);
  mpBtnEditExpression->setIcon(icon2);

  const QIcon icon3 = qt_get_icon(image3_ID);
  mpBtnSaveExpression->setIcon(icon3);

  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CQExpressionMmlStackedWidget::~CQExpressionMmlStackedWidget()
{
  // no need to delete child widgets, Qt does it all for us
}

/*
 *  Sets the strings of the subwidgets using the current
 *  language.
 */
void CQExpressionMmlStackedWidget::languageChange()
{
  retranslateUi(this);
}

void CQExpressionMmlStackedWidget::slotGoExpressionWidget()
{
#ifdef DEBUG_UI
  qDebug() << "- here on CQExpressionMmlStackedWidget::slotGoExpressionWidget() -";
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
#endif

  setCurrentWidget(mpExpressionPage);

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::slotGoMmlWidget()
{
#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
#endif

  setCurrentWidget(mpMmlPage);

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::updateWidget()
{
#ifdef DEBUG_UI
  qDebug() << "- here on CQExpressionMmlStackedWidget::updateWidget() -";
#endif

#ifdef HAVE_MML

  std::ostringstream mml;
  std::vector<std::vector<std::string> > params;

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif

  if (mpExpressionWidget->text().isEmpty() ||
      !mpExpressionWidget->isValid())
    setCurrentWidget(mpExpressionPage);
  else
    {
      mpExpressionWidget->mpValidator->getExpression()->writeMathML(mml, false, 0);

#ifdef DEBUG_UI
      qDebug() << "mml.str() = " << FROM_UTF8(mml.str());
#endif

      setCurrentWidget(mpMmlPage);
      mpMmlScrollView->updateWidget(mml);
      MMLStr = FROM_UTF8(mml.str());
    }

#endif /* HAVE_MML */

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::init()
{
#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget = " << currentIndex();
#endif

#ifndef HAVE_MML
  mpBtnViewExpression->hide();
#endif // not HAVE_MML
}

void CQExpressionMmlStackedWidget::slotSaveExpression()
{
  QString filter;
  QString outfilename;

  C_INT32 Answer = QMessageBox::No;

  while (Answer == QMessageBox::No)
    {
      outfilename =
        CopasiFileDialog::getSaveFileName(this,
                                          "Save File Dialog",
                                          "untitled.mml",
                                          "MathML (*.mml);;TeX (*.tex)",
                                          "Save Expression to Disk", new QString);

      if (outfilename.isEmpty()) return;

      // Checks whether the file exists
      Answer = checkSelection(outfilename);

      if (Answer == QMessageBox::Cancel)
        return;
    }

  if (filter.contains("tex"))
    saveTeX(outfilename);
  else
    saveMML(outfilename);
}

void CQExpressionMmlStackedWidget::saveMML(const QString outfilename)
{
  std::ofstream ofile;
  ofile.open(utf8ToLocale(TO_UTF8(outfilename)).c_str(), std::ios::trunc);

  ofile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
  ofile << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"HTMLFiles/xhtml-math11-f.dtd\">" << std::endl;
  ofile << "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">" << std::endl;

  mpExpressionWidget->mpValidator->getExpression()->writeMathML(ofile, false, 0);

  ofile << "</math>" << std::endl;

  ofile.close();
}

void CQExpressionMmlStackedWidget::saveTeX(const QString outfilename)
{
  std::ostringstream mml;
  mpExpressionWidget->mpValidator->getExpression()->writeMathML(mml, false, 0);

  QString latexStr(FROM_UTF8(mml.str()));

  CMathMLToTeX::convert(latexStr);

  std::ofstream ofile;
  ofile.open(utf8ToLocale(TO_UTF8(outfilename)).c_str(), std::ios::trunc);

  ofile << TO_UTF8(latexStr);

  ofile.close();
}
<commit_msg>Take user's selected filter from saving action.<commit_after>// Begin CVS Header
//   $Source: /fs/turing/cvs/copasi_dev/copasi/UI/CQExpressionMmlStackedWidget.cpp,v $
//   $Revision: 1.2 $
//   $Name: HEAD $
//   $Author: pwilly $
//   $Date: 2009/10/01 12:58:00 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include "CQExpressionMmlStackedWidget.h"

#include "utilities/CCopasiException.h"

#include "CQMessageBox.h"
#include "qtUtilities.h" // for UTF8
#include "CopasiFileDialog.h"
#include "tex/CMathMLToTeX.h"

#include <QtDebug>

/*
 *  Constructs a CQExpressionMmlWidget as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
CQExpressionMmlStackedWidget::CQExpressionMmlStackedWidget(QWidget* parent)
    : QStackedWidget(parent)
{
  setupUi(this);

  const QIcon icon = qt_get_icon(image0_ID);
  mpBtnExpressionObject->setIcon(icon);

  const QIcon icon1 = qt_get_icon(image1_ID);
  mpBtnViewExpression->setIcon(icon1);

  const QIcon icon2 = qt_get_icon(image2_ID);
  mpBtnEditExpression->setIcon(icon2);

  const QIcon icon3 = qt_get_icon(image3_ID);
  mpBtnSaveExpression->setIcon(icon3);

  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CQExpressionMmlStackedWidget::~CQExpressionMmlStackedWidget()
{
  // no need to delete child widgets, Qt does it all for us
}

/*
 *  Sets the strings of the subwidgets using the current
 *  language.
 */
void CQExpressionMmlStackedWidget::languageChange()
{
  retranslateUi(this);
}

void CQExpressionMmlStackedWidget::slotGoExpressionWidget()
{
#ifdef DEBUG_UI
  qDebug() << "- here on CQExpressionMmlStackedWidget::slotGoExpressionWidget() -";
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
#endif

  setCurrentWidget(mpExpressionPage);

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::slotGoMmlWidget()
{
#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
#endif

  setCurrentWidget(mpMmlPage);

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::updateWidget()
{
#ifdef DEBUG_UI
  qDebug() << "- here on CQExpressionMmlStackedWidget::updateWidget() -";
#endif

#ifdef HAVE_MML

  std::ostringstream mml;
  std::vector<std::vector<std::string> > params;

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif

  if (mpExpressionWidget->text().isEmpty() ||
      !mpExpressionWidget->isValid())
    setCurrentWidget(mpExpressionPage);
  else
    {
      mpExpressionWidget->mpValidator->getExpression()->writeMathML(mml, false, 0);

#ifdef DEBUG_UI
      qDebug() << "mml.str() = " << FROM_UTF8(mml.str());
#endif

      setCurrentWidget(mpMmlPage);
      mpMmlScrollView->updateWidget(mml);
      MMLStr = FROM_UTF8(mml.str());
    }

#endif /* HAVE_MML */

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::init()
{
#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget = " << currentIndex();
#endif

#ifndef HAVE_MML
  mpBtnViewExpression->hide();
#endif // not HAVE_MML
}

void CQExpressionMmlStackedWidget::slotSaveExpression()
{
  QString *filter = new QString;
  QString outfilename;

  C_INT32 Answer = QMessageBox::No;

  while (Answer == QMessageBox::No)
    {
      outfilename =
        CopasiFileDialog::getSaveFileName(this,
                                          "Save File Dialog",
                                          "untitled.mml",
                                          "MathML (*.mml);;TeX (*.tex)",
//                                          "Save Expression to Disk", new QString);
                                          "Save Expression to Disk", filter);

      if (outfilename.isEmpty()) return;

      // Checks whether the file exists
      Answer = checkSelection(outfilename);

      if (Answer == QMessageBox::Cancel)
        return;
    }

  QString suffix = FROM_UTF8(CDirEntry::suffix(TO_UTF8(outfilename)));

#ifdef DEBUG_UI
  qDebug() << "\non CQEMSW::slotSaveExpression -> outfilename = " << outfilename;
  qDebug() << "\non CQEMSW::slotSaveExpression -> suffix = " << suffix;
  qDebug() << "\non CQEMSW::slotSaveExpression -> filter = " << *filter << "\n";
#endif

  if (filter->contains("tex"))
    saveTeX(outfilename);
  else
    saveMML(outfilename);
}

void CQExpressionMmlStackedWidget::saveMML(const QString outfilename)
{
  std::ofstream ofile;
  ofile.open(utf8ToLocale(TO_UTF8(outfilename)).c_str(), std::ios::trunc);

  ofile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
  ofile << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"HTMLFiles/xhtml-math11-f.dtd\">" << std::endl;
  ofile << "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">" << std::endl;

  mpExpressionWidget->mpValidator->getExpression()->writeMathML(ofile, false, 0);

  ofile << "</math>" << std::endl;

  ofile.close();
}

void CQExpressionMmlStackedWidget::saveTeX(const QString outfilename)
{
  std::ostringstream mml;
  mpExpressionWidget->mpValidator->getExpression()->writeMathML(mml, false, 0);

  QString latexStr(FROM_UTF8(mml.str()));

  CMathMLToTeX::convert(latexStr);

  std::ofstream ofile;
  ofile.open(utf8ToLocale(TO_UTF8(outfilename)).c_str(), std::ios::trunc);

  ofile << TO_UTF8(latexStr);

  ofile.close();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012-2014 Open Source Robotics Foundation
 *
 * 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.
 *
*/
/*
 * Desc: Contact plugin
 * Author: Nate Koenig mod by John Hsu
 */

#include "gazebo/physics/physics.hh"
#include "gazebo_lidar_plugin.h"

#include <gazebo/common/common.hh>
#include <gazebo/common/Plugin.hh>
#include <gazebo/gazebo.hh>
#include <gazebo/physics/physics.hh>
#include "gazebo/transport/transport.hh"
#include "gazebo/msgs/msgs.hh"

#include <chrono>
#include <cmath>
#include <iostream>
#include <memory>
#include <stdio.h>

using namespace gazebo;

// Register this plugin with the simulator
GZ_REGISTER_SENSOR_PLUGIN(RayPlugin)

/////////////////////////////////////////////////
RayPlugin::RayPlugin()
{
}

/////////////////////////////////////////////////
RayPlugin::~RayPlugin()
{
  this->parentSensor->GetLaserShape()->DisconnectNewLaserScans(
      this->newLaserScansConnection);
  this->newLaserScansConnection.reset();

  this->parentSensor.reset();
  this->world.reset();
}

/////////////////////////////////////////////////
void RayPlugin::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf)
{
  // Get then name of the parent sensor
  this->parentSensor =
#if GAZEBO_MAJOR_VERSION >= 7
    std::dynamic_pointer_cast<sensors::RaySensor>(_parent);
#else
    boost::dynamic_pointer_cast<sensors::RaySensor>(_parent);
#endif

  if (!this->parentSensor)
    gzthrow("RayPlugin requires a Ray Sensor as its parent");

  this->world = physics::get_world(this->parentSensor->GetWorldName());

  this->newLaserScansConnection =
    this->parentSensor->GetLaserShape()->ConnectNewLaserScans(
      boost::bind(&RayPlugin::OnNewLaserScans, this));

  if (_sdf->HasElement("robotNamespace"))
    namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>();
  else
    gzwarn << "[gazebo_lidar_plugin] Please specify a robotNamespace.\n";

  node_handle_ = transport::NodePtr(new transport::Node());
  node_handle_->Init(namespace_);

  lidar_pub_ = node_handle_->Advertise<lidar_msgs::msgs::lidar>("lidar", 10);
}

/////////////////////////////////////////////////
void RayPlugin::OnNewLaserScans()
{
  lidar_message.set_time_msec(0);
  lidar_message.set_min_distance(parentSensor->GetRangeMin());
  lidar_message.set_max_distance(parentSensor->GetRangeMax());
  lidar_message.set_current_distance(parentSensor->GetRange(0));

  lidar_pub_->Publish(lidar_message);
}

<commit_msg>gazebo_lidar_plugin: fix compilation warnings against Gazebo 7<commit_after>/*
 * Copyright (C) 2012-2014 Open Source Robotics Foundation
 *
 * 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.
 *
*/
/*
 * Desc: Contact plugin
 * Author: Nate Koenig mod by John Hsu
 */

#include "gazebo/physics/physics.hh"
#include "gazebo_lidar_plugin.h"

#include <gazebo/common/common.hh>
#include <gazebo/common/Plugin.hh>
#include <gazebo/gazebo.hh>
#include <gazebo/physics/physics.hh>
#include "gazebo/transport/transport.hh"
#include "gazebo/msgs/msgs.hh"

#include <chrono>
#include <cmath>
#include <iostream>
#include <memory>
#include <stdio.h>

using namespace gazebo;

// Register this plugin with the simulator
GZ_REGISTER_SENSOR_PLUGIN(RayPlugin)

/////////////////////////////////////////////////
RayPlugin::RayPlugin()
{
}

/////////////////////////////////////////////////
RayPlugin::~RayPlugin()
{
#if GAZEBO_MAJOR_VERSION >= 7
  this->parentSensor->LaserShape()->DisconnectNewLaserScans(
#else
  this->parentSensor->GetLaserShape()->DisconnectNewLaserScans(
#endif
      this->newLaserScansConnection);
  this->newLaserScansConnection.reset();

  this->parentSensor.reset();
  this->world.reset();
}

/////////////////////////////////////////////////
void RayPlugin::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf)
{
  // Get then name of the parent sensor
  this->parentSensor =
#if GAZEBO_MAJOR_VERSION >= 7
    std::dynamic_pointer_cast<sensors::RaySensor>(_parent);
#else
    boost::dynamic_pointer_cast<sensors::RaySensor>(_parent);
#endif

  if (!this->parentSensor)
    gzthrow("RayPlugin requires a Ray Sensor as its parent");

#if GAZEBO_MAJOR_VERSION >= 7
  this->world = physics::get_world(this->parentSensor->WorldName());
#else
  this->world = physics::get_world(this->parentSensor->GetWorldName());
#endif

  this->newLaserScansConnection =
#if GAZEBO_MAJOR_VERSION >= 7
    this->parentSensor->LaserShape()->ConnectNewLaserScans(
#else
    this->parentSensor->GetLaserShape()->ConnectNewLaserScans(
#endif
      boost::bind(&RayPlugin::OnNewLaserScans, this));

  if (_sdf->HasElement("robotNamespace"))
    namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>();
  else
    gzwarn << "[gazebo_lidar_plugin] Please specify a robotNamespace.\n";

  node_handle_ = transport::NodePtr(new transport::Node());
  node_handle_->Init(namespace_);

  lidar_pub_ = node_handle_->Advertise<lidar_msgs::msgs::lidar>("lidar", 10);
}

/////////////////////////////////////////////////
void RayPlugin::OnNewLaserScans()
{
  lidar_message.set_time_msec(0);
#if GAZEBO_MAJOR_VERSION >= 7
  lidar_message.set_min_distance(parentSensor->RangeMin());
  lidar_message.set_max_distance(parentSensor->RangeMax());
  lidar_message.set_current_distance(parentSensor->Range(0));
#else
  lidar_message.set_min_distance(parentSensor->GetRangeMin());
  lidar_message.set_max_distance(parentSensor->GetRangeMax());
  lidar_message.set_current_distance(parentSensor->GetRange(0));
#endif

  lidar_pub_->Publish(lidar_message);
}

<|endoftext|>


<commit_before>/***********************************************************************
    filename:   GeometryBufferBase.cpp
    created:    Tue Apr 30 2013
    authors:    Paul D Turner <paul@cegui.org.uk>
                Lukas E Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include <GL/glew.h>

#include "glm/glm.hpp"
#include "glm/gtc/quaternion.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"
#include "CEGUI/RenderEffect.h"
#include "CEGUI/RendererModules/OpenGL/Texture.h"
#include "CEGUI/Vertex.h"
#include "CEGUI/RendererModules/OpenGL/GlmPimpl.h"
#include "CEGUI/ShaderParameterBindings.h"

namespace CEGUI
{
//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase::OpenGLGeometryBufferBase(OpenGLRendererBase& owner, CEGUI::RefCounted<RenderMaterial> renderMaterial) :
    GeometryBuffer(renderMaterial),
    d_owner(&owner),
    d_clipRect(0, 0, 0, 0),
    d_clippingActive(true),
    d_translation(0, 0, 0),
    d_rotation(Quaternion::IDENTITY),
    d_scale(1.0f, 1.0f, 1.0f),
    d_pivot(0, 0, 0),
    d_customTransform(1.0f),
    d_effect(0),
    d_matrix(new mat4Pimpl()),
    d_matrixValid(false),
    d_vertexCount(0)
{
}

//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase::~OpenGLGeometryBufferBase()
{
    delete d_matrix;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setTranslation(const Vector3f& v)
{
    if(d_translation != v)
    {
        d_translation = v;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setRotation(const Quaternion& r)
{
    if(d_rotation != r)
    {
        d_rotation = r;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setScale(const Vector3f& v)
{
    if(d_scale != v)
    {
        d_scale = v;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setPivot(const Vector3f& p)
{
    if(d_pivot != p)
    {
        d_pivot = Vector3f(p.d_x, p.d_y, p.d_z);
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setCustomTransform(const glm::mat4x4& transformation)
{
    if(d_customTransform != transformation)
    {
        d_customTransform = transformation;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setClippingRegion(const Rectf& region)
{
    d_clipRect.top(ceguimax(0.0f, region.top()));
    d_clipRect.left(ceguimax(0.0f, region.left()));
    d_clipRect.bottom(ceguimax(0.0f, region.bottom()));
    d_clipRect.right(ceguimax(0.0f, region.right()));
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setTexture(Texture* texture)
{
    CEGUI::ShaderParameterBindings* shaderParameterBindings = (*d_renderMaterial).getShaderParamBindings();
    shaderParameterBindings->setParameter("texture0", texture);
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::reset()
{
    d_vertexData.clear();
    d_clippingActive = true;
}

//----------------------------------------------------------------------------//
uint OpenGLGeometryBufferBase::getVertexCount() const
{
    return d_vertexData.size();
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setRenderEffect(RenderEffect* effect)
{
    d_effect = effect;
}

//----------------------------------------------------------------------------//
RenderEffect* OpenGLGeometryBufferBase::getRenderEffect()
{
    return d_effect;
}

//----------------------------------------------------------------------------//
const mat4Pimpl* OpenGLGeometryBufferBase::getMatrix() const
{
    if (!d_matrixValid)
        updateMatrix();

    return d_matrix;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::updateMatrix() const
{
    glm::mat4& model_matrix = d_matrix->d_matrix;

    const glm::vec3 final_trans(d_translation.d_x + d_pivot.d_x,
                                d_translation.d_y + d_pivot.d_y,
                                d_translation.d_z + d_pivot.d_z);

    model_matrix = glm::translate(glm::mat4(1.0f), final_trans);

    glm::quat rotationQuat = glm::quat(d_rotation.d_w, d_rotation.d_x, d_rotation.d_y, d_rotation.d_z);
    glm::mat4 rotation_matrix = glm::mat4_cast(rotationQuat);

    glm::mat4 scale_matrix(glm::scale(glm::mat4(1.0f), glm::vec3(d_scale.d_x, d_scale.d_y, d_scale.d_z)));

    model_matrix *= rotation_matrix * scale_matrix;

    glm::vec3 transl = glm::vec3(-d_pivot.d_x, -d_pivot.d_y, -d_pivot.d_z);
    glm::mat4 translMatrix = glm::translate(glm::mat4(1.f), transl);
    model_matrix *=  translMatrix * d_customTransform;

    d_matrixValid = true;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setClippingActive(const bool active)
{
    d_clippingActive = active;
}

//----------------------------------------------------------------------------//
bool OpenGLGeometryBufferBase::isClippingActive() const
{
    return d_clippingActive;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::appendGeometry(const std::vector<float>& vertex_data)
{
    d_vertexData.insert(d_vertexData.end(), vertex_data.begin(), vertex_data.end());
    // Update size of geometry buffer
    d_vertexCount = d_vertexData.size() / getVertexAttributeElementCount();
}

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

}

<commit_msg>MOD: Fixed getter return value<commit_after>/***********************************************************************
    filename:   GeometryBufferBase.cpp
    created:    Tue Apr 30 2013
    authors:    Paul D Turner <paul@cegui.org.uk>
                Lukas E Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include <GL/glew.h>

#include "glm/glm.hpp"
#include "glm/gtc/quaternion.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"
#include "CEGUI/RenderEffect.h"
#include "CEGUI/RendererModules/OpenGL/Texture.h"
#include "CEGUI/Vertex.h"
#include "CEGUI/RendererModules/OpenGL/GlmPimpl.h"
#include "CEGUI/ShaderParameterBindings.h"

namespace CEGUI
{
//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase::OpenGLGeometryBufferBase(OpenGLRendererBase& owner, CEGUI::RefCounted<RenderMaterial> renderMaterial) :
    GeometryBuffer(renderMaterial),
    d_owner(&owner),
    d_clipRect(0, 0, 0, 0),
    d_clippingActive(true),
    d_translation(0, 0, 0),
    d_rotation(Quaternion::IDENTITY),
    d_scale(1.0f, 1.0f, 1.0f),
    d_pivot(0, 0, 0),
    d_customTransform(1.0f),
    d_effect(0),
    d_matrix(new mat4Pimpl()),
    d_matrixValid(false),
    d_vertexCount(0)
{
}

//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase::~OpenGLGeometryBufferBase()
{
    delete d_matrix;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setTranslation(const Vector3f& v)
{
    if(d_translation != v)
    {
        d_translation = v;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setRotation(const Quaternion& r)
{
    if(d_rotation != r)
    {
        d_rotation = r;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setScale(const Vector3f& v)
{
    if(d_scale != v)
    {
        d_scale = v;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setPivot(const Vector3f& p)
{
    if(d_pivot != p)
    {
        d_pivot = Vector3f(p.d_x, p.d_y, p.d_z);
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setCustomTransform(const glm::mat4x4& transformation)
{
    if(d_customTransform != transformation)
    {
        d_customTransform = transformation;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setClippingRegion(const Rectf& region)
{
    d_clipRect.top(ceguimax(0.0f, region.top()));
    d_clipRect.left(ceguimax(0.0f, region.left()));
    d_clipRect.bottom(ceguimax(0.0f, region.bottom()));
    d_clipRect.right(ceguimax(0.0f, region.right()));
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setTexture(Texture* texture)
{
    CEGUI::ShaderParameterBindings* shaderParameterBindings = (*d_renderMaterial).getShaderParamBindings();
    shaderParameterBindings->setParameter("texture0", texture);
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::reset()
{
    d_vertexData.clear();
    d_clippingActive = true;
}

//----------------------------------------------------------------------------//
uint OpenGLGeometryBufferBase::getVertexCount() const
{
    return d_vertexCount;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setRenderEffect(RenderEffect* effect)
{
    d_effect = effect;
}

//----------------------------------------------------------------------------//
RenderEffect* OpenGLGeometryBufferBase::getRenderEffect()
{
    return d_effect;
}

//----------------------------------------------------------------------------//
const mat4Pimpl* OpenGLGeometryBufferBase::getMatrix() const
{
    if (!d_matrixValid)
        updateMatrix();

    return d_matrix;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::updateMatrix() const
{
    glm::mat4& model_matrix = d_matrix->d_matrix;

    const glm::vec3 final_trans(d_translation.d_x + d_pivot.d_x,
                                d_translation.d_y + d_pivot.d_y,
                                d_translation.d_z + d_pivot.d_z);

    model_matrix = glm::translate(glm::mat4(1.0f), final_trans);

    glm::quat rotationQuat = glm::quat(d_rotation.d_w, d_rotation.d_x, d_rotation.d_y, d_rotation.d_z);
    glm::mat4 rotation_matrix = glm::mat4_cast(rotationQuat);

    glm::mat4 scale_matrix(glm::scale(glm::mat4(1.0f), glm::vec3(d_scale.d_x, d_scale.d_y, d_scale.d_z)));

    model_matrix *= rotation_matrix * scale_matrix;

    glm::vec3 transl = glm::vec3(-d_pivot.d_x, -d_pivot.d_y, -d_pivot.d_z);
    glm::mat4 translMatrix = glm::translate(glm::mat4(1.f), transl);
    model_matrix *=  translMatrix * d_customTransform;

    d_matrixValid = true;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setClippingActive(const bool active)
{
    d_clippingActive = active;
}

//----------------------------------------------------------------------------//
bool OpenGLGeometryBufferBase::isClippingActive() const
{
    return d_clippingActive;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::appendGeometry(const std::vector<float>& vertex_data)
{
    d_vertexData.insert(d_vertexData.end(), vertex_data.begin(), vertex_data.end());
    // Update size of geometry buffer
    d_vertexCount = d_vertexData.size() / getVertexAttributeElementCount();
}

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

}

<|endoftext|>


<commit_before><commit_msg>Do not try to compute sub-meshes if the main shape is already meshed<commit_after><|endoftext|>