<commit_before>/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * This file is part of libgpiod.
 *
 * Copyright (C) 2019 Bartosz Golaszewski <bgolaszewski@baylibre.com>
 */

#include <catch.hpp>
#include <gpiod.hpp>

#include "gpio-mockup.hpp"

using ::gpiod::test::mockup;

namespace {

const ::std::string consumer = "line-test";

} /* namespace */

TEST_CASE("Global find_line() function works", "[line]")
{
	mockup::probe_guard mockup_chips({ 8, 8, 8, 8, 8 }, mockup::FLAG_NAMED_LINES);

	auto line = ::gpiod::find_line("gpio-mockup-C-5");
	REQUIRE(line.offset() == 5);
	REQUIRE(line.name() == "gpio-mockup-C-5");
	REQUIRE(line.get_chip().label() == "gpio-mockup-C");
}

TEST_CASE("Line information can be correctly retrieved", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 }, mockup::FLAG_NAMED_LINES);
	::gpiod::chip chip(mockup::instance().chip_name(0));
	auto line = chip.get_line(4);

	SECTION("unexported line")
	{
		REQUIRE(line.offset() == 4);
		REQUIRE(line.name() == "gpio-mockup-A-4");
		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_INPUT);
		REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH);
		REQUIRE(line.consumer().empty());
		REQUIRE_FALSE(line.is_requested());
		REQUIRE_FALSE(line.is_used());
	}

	SECTION("exported line")
	{
		::gpiod::line_request config;

		config.consumer = consumer.c_str();
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		line.request(config);

		REQUIRE(line.offset() == 4);
		REQUIRE(line.name() == "gpio-mockup-A-4");
		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
		REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH);
		REQUIRE(line.is_requested());
		REQUIRE(line.is_used());
	}

	SECTION("exported line with flags")
	{
		::gpiod::line_request config;

		config.consumer = consumer.c_str();
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW |
			       ::gpiod::line_request::FLAG_OPEN_DRAIN;
		line.request(config);

		REQUIRE(line.offset() == 4);
		REQUIRE(line.name() == "gpio-mockup-A-4");
		/* FIXME Uncomment the line below once this issue is fixed in the kernel. */
		//REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
		REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_LOW);
		REQUIRE(line.is_requested());
		REQUIRE(line.is_used());
		REQUIRE(line.is_open_drain());
		REQUIRE_FALSE(line.is_open_source());
	}
}

TEST_CASE("Line bulk object works correctly", "[line][bulk]")
{
	mockup::probe_guard mockup_chips({ 8 }, mockup::FLAG_NAMED_LINES);
	::gpiod::chip chip(mockup::instance().chip_name(0));

	SECTION("lines can be added, accessed and cleared")
	{
		::gpiod::line_bulk lines;

		REQUIRE(lines.empty());

		lines.append(chip.get_line(0));
		lines.append(chip.get_line(1));
		lines.append(chip.get_line(2));

		REQUIRE(lines.size() == 3);
		REQUIRE(lines.get(1).name() == "gpio-mockup-A-1");
		REQUIRE(lines[2].name() == "gpio-mockup-A-2");

		lines.clear();

		REQUIRE(lines.empty());
	}

	SECTION("bulk iterator works")
	{
		auto lines = chip.get_all_lines();
		int count = 0;

		for (auto& it: lines)
			REQUIRE(it.offset() == count++);

		REQUIRE(count == chip.num_lines());
	}

	SECTION("accessing lines out of range throws exception")
	{
		auto lines = chip.get_all_lines();

		REQUIRE_THROWS_AS(lines.get(11), ::std::out_of_range&);
	}
}

TEST_CASE("Line values can be set and read", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	::gpiod::line_request config;

	config.consumer = consumer.c_str();

	SECTION("get value (single line)")
	{
		auto line = chip.get_line(3);
		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
		line.request(config);
		REQUIRE(line.get_value() == 0);
		mockup::instance().chip_set_pull(0, 3, 1);
		REQUIRE(line.get_value() == 1);
	}

	SECTION("set value (single line)")
	{
		auto line = chip.get_line(3);
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		line.request(config);
		line.set_value(1);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
		line.set_value(0);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 0);
	}

	SECTION("set value with default value parameter")
	{
		auto line = chip.get_line(3);
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		line.request(config, 1);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
	}

	SECTION("get multiple values at once")
	{
		auto lines = chip.get_lines({ 0, 1, 2, 3, 4 });
		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
		lines.request(config);
		REQUIRE(lines.get_values() == ::std::vector<int>({ 0, 0, 0, 0, 0 }));
		mockup::instance().chip_set_pull(0, 1, 1);
		mockup::instance().chip_set_pull(0, 3, 1);
		mockup::instance().chip_set_pull(0, 4, 1);
		REQUIRE(lines.get_values() == ::std::vector<int>({ 0, 1, 0, 1, 1 }));
	}

	SECTION("set multiple values at once")
	{
		auto lines = chip.get_lines({ 0, 1, 2, 6, 7 });
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		lines.request(config);
		lines.set_values({ 1, 1, 0, 1, 0 });
		REQUIRE(mockup::instance().chip_get_value(0, 0) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 1) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 2) == 0);
		REQUIRE(mockup::instance().chip_get_value(0, 6) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 7) == 0);
	}

	SECTION("set multiple values with default values paramter")
	{
		auto lines = chip.get_lines({ 1, 2, 4, 6, 7 });
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		lines.request(config, { 1, 1, 0, 1, 0 });
		REQUIRE(mockup::instance().chip_get_value(0, 1) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 2) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 4) == 0);
		REQUIRE(mockup::instance().chip_get_value(0, 6) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 7) == 0);
	}

	SECTION("get value (single line, active-low")
	{
		auto line = chip.get_line(4);
		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW;
		line.request(config);
		REQUIRE(line.get_value() == 1);
		mockup::instance().chip_set_pull(0, 4, 1);
		REQUIRE(line.get_value() == 0);
	}

	SECTION("set value (single line, active-low)")
	{
		auto line = chip.get_line(3);
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW;
		line.request(config);
		line.set_value(1);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 0);
		line.set_value(0);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
	}
}

TEST_CASE("Exported line can be released", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	auto line = chip.get_line(4);
	::gpiod::line_request config;

	config.consumer = consumer.c_str();
	config.request_type = ::gpiod::line_request::DIRECTION_INPUT;

	line.request(config);

	REQUIRE(line.is_requested());
	REQUIRE(line.get_value() == 0);

	line.release();

	REQUIRE_FALSE(line.is_requested());
	REQUIRE_THROWS_AS(line.get_value(), ::std::system_error&);
}

TEST_CASE("Uninitialized GPIO line behaves correctly", "[line]")
{
	::gpiod::line line;

	SECTION("uninitialized line is 'false'")
	{
		REQUIRE_FALSE(line);
	}

	SECTION("using uninitialized line throws logic_error")
	{
		REQUIRE_THROWS_AS(line.name(), ::std::logic_error&);
	}
}

TEST_CASE("Uninitialized GPIO line_bulk behaves correctly", "[line][bulk]")
{
	::gpiod::line_bulk bulk;

	SECTION("uninitialized line_bulk is 'false'")
	{
		REQUIRE_FALSE(bulk);
	}

	SECTION("using uninitialized line_bulk throws logic_error")
	{
		REQUIRE_THROWS_AS(bulk.get(0), ::std::logic_error&);
	}
}

TEST_CASE("Cannot request the same line twice", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	::gpiod::line_request config;

	config.consumer = consumer.c_str();
	config.request_type = ::gpiod::line_request::DIRECTION_INPUT;

	SECTION("two separate calls to request()")
	{
		auto line = chip.get_line(3);

		REQUIRE_NOTHROW(line.request(config));
		REQUIRE_THROWS_AS(line.request(config), ::std::system_error&);
	}

	SECTION("request the same line twice in line_bulk")
	{
		/*
		 * While a line_bulk object can hold two or more line objects
		 * representing the same line - requesting it will fail.
		 */
		auto lines = chip.get_lines({ 2, 3, 4, 4 });

		REQUIRE_THROWS_AS(lines.request(config), ::std::system_error&);
	}
}

TEST_CASE("Cannot get/set values of unrequested lines", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	auto line = chip.get_line(3);

	SECTION("get value")
	{
		REQUIRE_THROWS_AS(line.get_value(), ::std::system_error&);
	}

	SECTION("set value")
	{
		REQUIRE_THROWS_AS(line.set_value(1), ::std::system_error&);
	}
}

TEST_CASE("Line objects can be compared")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	auto line1 = chip.get_line(3);
	auto line2 = chip.get_line(3);
	auto line3 = chip.get_line(4);

	REQUIRE(line1 == line2);
	REQUIRE(line2 != line3);
}
<commit_msg>bindings: cxx: tests: extend the test case for global find_line()<commit_after>/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * This file is part of libgpiod.
 *
 * Copyright (C) 2019 Bartosz Golaszewski <bgolaszewski@baylibre.com>
 */

#include <catch.hpp>
#include <gpiod.hpp>

#include "gpio-mockup.hpp"

using ::gpiod::test::mockup;

namespace {

const ::std::string consumer = "line-test";

} /* namespace */

TEST_CASE("Global find_line() function works", "[line]")
{
	mockup::probe_guard mockup_chips({ 8, 8, 8, 8, 8 }, mockup::FLAG_NAMED_LINES);

	SECTION("line found")
	{
		auto line = ::gpiod::find_line("gpio-mockup-C-5");
		REQUIRE(line.offset() == 5);
		REQUIRE(line.name() == "gpio-mockup-C-5");
		REQUIRE(line.get_chip().label() == "gpio-mockup-C");
	}

	SECTION("line not found")
	{
		auto line = ::gpiod::find_line("nonexistent-line");
		REQUIRE_FALSE(line);
	}
}

TEST_CASE("Line information can be correctly retrieved", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 }, mockup::FLAG_NAMED_LINES);
	::gpiod::chip chip(mockup::instance().chip_name(0));
	auto line = chip.get_line(4);

	SECTION("unexported line")
	{
		REQUIRE(line.offset() == 4);
		REQUIRE(line.name() == "gpio-mockup-A-4");
		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_INPUT);
		REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH);
		REQUIRE(line.consumer().empty());
		REQUIRE_FALSE(line.is_requested());
		REQUIRE_FALSE(line.is_used());
	}

	SECTION("exported line")
	{
		::gpiod::line_request config;

		config.consumer = consumer.c_str();
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		line.request(config);

		REQUIRE(line.offset() == 4);
		REQUIRE(line.name() == "gpio-mockup-A-4");
		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
		REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH);
		REQUIRE(line.is_requested());
		REQUIRE(line.is_used());
	}

	SECTION("exported line with flags")
	{
		::gpiod::line_request config;

		config.consumer = consumer.c_str();
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW |
			       ::gpiod::line_request::FLAG_OPEN_DRAIN;
		line.request(config);

		REQUIRE(line.offset() == 4);
		REQUIRE(line.name() == "gpio-mockup-A-4");
		/* FIXME Uncomment the line below once this issue is fixed in the kernel. */
		//REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
		REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_LOW);
		REQUIRE(line.is_requested());
		REQUIRE(line.is_used());
		REQUIRE(line.is_open_drain());
		REQUIRE_FALSE(line.is_open_source());
	}
}

TEST_CASE("Line bulk object works correctly", "[line][bulk]")
{
	mockup::probe_guard mockup_chips({ 8 }, mockup::FLAG_NAMED_LINES);
	::gpiod::chip chip(mockup::instance().chip_name(0));

	SECTION("lines can be added, accessed and cleared")
	{
		::gpiod::line_bulk lines;

		REQUIRE(lines.empty());

		lines.append(chip.get_line(0));
		lines.append(chip.get_line(1));
		lines.append(chip.get_line(2));

		REQUIRE(lines.size() == 3);
		REQUIRE(lines.get(1).name() == "gpio-mockup-A-1");
		REQUIRE(lines[2].name() == "gpio-mockup-A-2");

		lines.clear();

		REQUIRE(lines.empty());
	}

	SECTION("bulk iterator works")
	{
		auto lines = chip.get_all_lines();
		int count = 0;

		for (auto& it: lines)
			REQUIRE(it.offset() == count++);

		REQUIRE(count == chip.num_lines());
	}

	SECTION("accessing lines out of range throws exception")
	{
		auto lines = chip.get_all_lines();

		REQUIRE_THROWS_AS(lines.get(11), ::std::out_of_range&);
	}
}

TEST_CASE("Line values can be set and read", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	::gpiod::line_request config;

	config.consumer = consumer.c_str();

	SECTION("get value (single line)")
	{
		auto line = chip.get_line(3);
		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
		line.request(config);
		REQUIRE(line.get_value() == 0);
		mockup::instance().chip_set_pull(0, 3, 1);
		REQUIRE(line.get_value() == 1);
	}

	SECTION("set value (single line)")
	{
		auto line = chip.get_line(3);
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		line.request(config);
		line.set_value(1);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
		line.set_value(0);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 0);
	}

	SECTION("set value with default value parameter")
	{
		auto line = chip.get_line(3);
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		line.request(config, 1);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
	}

	SECTION("get multiple values at once")
	{
		auto lines = chip.get_lines({ 0, 1, 2, 3, 4 });
		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
		lines.request(config);
		REQUIRE(lines.get_values() == ::std::vector<int>({ 0, 0, 0, 0, 0 }));
		mockup::instance().chip_set_pull(0, 1, 1);
		mockup::instance().chip_set_pull(0, 3, 1);
		mockup::instance().chip_set_pull(0, 4, 1);
		REQUIRE(lines.get_values() == ::std::vector<int>({ 0, 1, 0, 1, 1 }));
	}

	SECTION("set multiple values at once")
	{
		auto lines = chip.get_lines({ 0, 1, 2, 6, 7 });
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		lines.request(config);
		lines.set_values({ 1, 1, 0, 1, 0 });
		REQUIRE(mockup::instance().chip_get_value(0, 0) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 1) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 2) == 0);
		REQUIRE(mockup::instance().chip_get_value(0, 6) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 7) == 0);
	}

	SECTION("set multiple values with default values paramter")
	{
		auto lines = chip.get_lines({ 1, 2, 4, 6, 7 });
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		lines.request(config, { 1, 1, 0, 1, 0 });
		REQUIRE(mockup::instance().chip_get_value(0, 1) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 2) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 4) == 0);
		REQUIRE(mockup::instance().chip_get_value(0, 6) == 1);
		REQUIRE(mockup::instance().chip_get_value(0, 7) == 0);
	}

	SECTION("get value (single line, active-low")
	{
		auto line = chip.get_line(4);
		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW;
		line.request(config);
		REQUIRE(line.get_value() == 1);
		mockup::instance().chip_set_pull(0, 4, 1);
		REQUIRE(line.get_value() == 0);
	}

	SECTION("set value (single line, active-low)")
	{
		auto line = chip.get_line(3);
		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW;
		line.request(config);
		line.set_value(1);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 0);
		line.set_value(0);
		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
	}
}

TEST_CASE("Exported line can be released", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	auto line = chip.get_line(4);
	::gpiod::line_request config;

	config.consumer = consumer.c_str();
	config.request_type = ::gpiod::line_request::DIRECTION_INPUT;

	line.request(config);

	REQUIRE(line.is_requested());
	REQUIRE(line.get_value() == 0);

	line.release();

	REQUIRE_FALSE(line.is_requested());
	REQUIRE_THROWS_AS(line.get_value(), ::std::system_error&);
}

TEST_CASE("Uninitialized GPIO line behaves correctly", "[line]")
{
	::gpiod::line line;

	SECTION("uninitialized line is 'false'")
	{
		REQUIRE_FALSE(line);
	}

	SECTION("using uninitialized line throws logic_error")
	{
		REQUIRE_THROWS_AS(line.name(), ::std::logic_error&);
	}
}

TEST_CASE("Uninitialized GPIO line_bulk behaves correctly", "[line][bulk]")
{
	::gpiod::line_bulk bulk;

	SECTION("uninitialized line_bulk is 'false'")
	{
		REQUIRE_FALSE(bulk);
	}

	SECTION("using uninitialized line_bulk throws logic_error")
	{
		REQUIRE_THROWS_AS(bulk.get(0), ::std::logic_error&);
	}
}

TEST_CASE("Cannot request the same line twice", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	::gpiod::line_request config;

	config.consumer = consumer.c_str();
	config.request_type = ::gpiod::line_request::DIRECTION_INPUT;

	SECTION("two separate calls to request()")
	{
		auto line = chip.get_line(3);

		REQUIRE_NOTHROW(line.request(config));
		REQUIRE_THROWS_AS(line.request(config), ::std::system_error&);
	}

	SECTION("request the same line twice in line_bulk")
	{
		/*
		 * While a line_bulk object can hold two or more line objects
		 * representing the same line - requesting it will fail.
		 */
		auto lines = chip.get_lines({ 2, 3, 4, 4 });

		REQUIRE_THROWS_AS(lines.request(config), ::std::system_error&);
	}
}

TEST_CASE("Cannot get/set values of unrequested lines", "[line]")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	auto line = chip.get_line(3);

	SECTION("get value")
	{
		REQUIRE_THROWS_AS(line.get_value(), ::std::system_error&);
	}

	SECTION("set value")
	{
		REQUIRE_THROWS_AS(line.set_value(1), ::std::system_error&);
	}
}

TEST_CASE("Line objects can be compared")
{
	mockup::probe_guard mockup_chips({ 8 });
	::gpiod::chip chip(mockup::instance().chip_name(0));
	auto line1 = chip.get_line(3);
	auto line2 = chip.get_line(3);
	auto line3 = chip.get_line(4);

	REQUIRE(line1 == line2);
	REQUIRE(line2 != line3);
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2016,2017 Rodrigo Jose Hernandez Cordoba

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <iostream>
#include <fstream>
#include <png.h>
#include <algorithm>
#include <exception>
#include <stdexcept>
#include <cstring>
#include "PngImage.h"

namespace AeonGames
{
    struct png_read_memory_struct
    {
        uint8_t* buffer;
        uint8_t* pointer;
        png_size_t size;
    };

    static void png_read_memory_data ( png_structp png_ptr, png_bytep data, png_size_t length )
    {
        if ( png_ptr == nullptr )
        {
            std::cout << __FUNCTION__ << " got NULL png_ptr pointer." << std::endl;
            png_warning ( png_ptr, "Got NULL png_ptr pointer." );
            return;
        }
        png_read_memory_struct* read_struct = static_cast<png_read_memory_struct*> ( png_get_io_ptr ( png_ptr ) );
        // Clip lenght not to get passed the end of the buffer.
        png_size_t real_length = std::min<png_size_t> ( ( ( read_struct->buffer + read_struct->size ) - read_struct->pointer ), length );
        if ( length < 1 )
        {
            std::cout << __FUNCTION__ << " tried to read past end of file" << std::endl;
            png_warning ( png_ptr, "Tried to read past end of file" );
            return;
        }
        memcpy ( data, read_struct->pointer, real_length );
        if ( real_length < length )
        {
            std::cout << __FUNCTION__ << " Returning " << real_length << " bytes instead of requested " << length << " because of end of memory" << std::endl;
            memset ( data + real_length, 0, length - real_length );
        }
        read_struct->pointer += real_length;
    }

    PngImage::PngImage ( const std::string & aFileName )
    {
        //--------------------------------------------------------
        // File loading code
        std::ifstream file ( aFileName, std::ios::binary );
        std::vector<uint8_t> buffer ( (
                                          std::istreambuf_iterator<char> ( file ) ),
                                      ( std::istreambuf_iterator<char>() ) );
        file.close();
        //--------------------------------------------------------

        if ( png_sig_cmp ( buffer.data(), 0, 8 ) == 0 )
        {
            png_structp png_ptr =
                png_create_read_struct ( PNG_LIBPNG_VER_STRING,
                                         nullptr, nullptr, nullptr );
            if ( png_ptr == nullptr )
            {
                throw std::runtime_error ( "png_create_read_struct failed." );
            }
            png_infop info_ptr = png_create_info_struct ( png_ptr );
            if ( info_ptr == nullptr )
            {
                throw std::runtime_error ( "png_create_info_struct failed." );
            }
            if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
            {
                throw std::runtime_error ( "Error during init_io." );
            }
            png_read_memory_struct read_memory_struct = {buffer.data(), buffer.data() + 8,
                                                         static_cast<png_size_t> ( buffer.size() *sizeof ( uint8_t ) )
                                                        };
            png_set_read_fn ( png_ptr, &read_memory_struct, png_read_memory_data );
            png_set_sig_bytes ( png_ptr, 8 );

            png_read_info ( png_ptr, info_ptr );

            mWidth = png_get_image_width ( png_ptr, info_ptr );
            mHeight = png_get_image_height ( png_ptr, info_ptr );
            png_byte color_type = png_get_color_type ( png_ptr, info_ptr );
            png_byte bit_depth = png_get_bit_depth ( png_ptr, info_ptr );

            if ( ( color_type == PNG_COLOR_TYPE_RGB ) || ( color_type == PNG_COLOR_TYPE_RGBA ) )
            {
                mFormat = ( color_type == PNG_COLOR_TYPE_RGB ) ? ImageFormat::RGB : ImageFormat::RGBA;
                mType   = ( bit_depth == 8 ) ? ImageType::UNSIGNED_BYTE : ImageType::UNSIGNED_SHORT;
            }
            else
            {
                throw std::runtime_error ( "PNG image color type not supported...yet" );
            }

            /*int number_of_passes =*/ png_set_interlace_handling ( png_ptr );
            png_read_update_info ( png_ptr, info_ptr );

            /* read file */
            if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
            {
                throw std::runtime_error ( "Error during read_image." );
            }
            // --------------------------------------
            // This has to be changed to create a single buffer to which all row_pointers point at.
            // See http://www.piko3d.com/tutorials/libpng-tutorial-loading-png-files-from-streams
            png_size_t rowbytes = png_get_rowbytes ( png_ptr, info_ptr );
            std::vector<uint8_t*> row_pointers ( sizeof ( png_bytep ) * mHeight );
            mData.resize ( rowbytes * mHeight );
            for ( png_uint_32 y = 0; y < mHeight; ++y )
            {
                row_pointers[y] = mData.data() + ( rowbytes * y );
            }
            // --------------------------------------
            png_read_image ( png_ptr, row_pointers.data() );
            png_destroy_read_struct ( &png_ptr, &info_ptr, ( png_infopp ) nullptr );
        }
        else
        {
            throw std::runtime_error ( "Image format not supported...yet" );
        }
    }
    PngImage::~PngImage()
        = default;
    uint32_t PngImage::Width() const
    {
        return mWidth;
    }
    uint32_t PngImage::Height() const
    {
        return mHeight;
    }
    Image::ImageFormat PngImage::Format() const
    {
        return mFormat;
    }
    Image::ImageType PngImage::Type() const
    {
        return mType;
    }
    const uint8_t* PngImage::Data() const
    {
        return mData.data();
    }
    const size_t PngImage::DataSize() const
    {
        return mData.size();
    }
}
<commit_msg>Added exception check when opening PNG images.<commit_after>/*
Copyright (C) 2016,2017 Rodrigo Jose Hernandez Cordoba

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <iostream>
#include <fstream>
#include <png.h>
#include <algorithm>
#include <exception>
#include <stdexcept>
#include <cstring>
#include "PngImage.h"

namespace AeonGames
{
    struct png_read_memory_struct
    {
        uint8_t* buffer;
        uint8_t* pointer;
        png_size_t size;
    };

    static void png_read_memory_data ( png_structp png_ptr, png_bytep data, png_size_t length )
    {
        if ( png_ptr == nullptr )
        {
            std::cout << __FUNCTION__ << " got NULL png_ptr pointer." << std::endl;
            png_warning ( png_ptr, "Got NULL png_ptr pointer." );
            return;
        }
        png_read_memory_struct* read_struct = static_cast<png_read_memory_struct*> ( png_get_io_ptr ( png_ptr ) );
        // Clip lenght not to get passed the end of the buffer.
        png_size_t real_length = std::min<png_size_t> ( ( ( read_struct->buffer + read_struct->size ) - read_struct->pointer ), length );
        if ( length < 1 )
        {
            std::cout << __FUNCTION__ << " tried to read past end of file" << std::endl;
            png_warning ( png_ptr, "Tried to read past end of file" );
            return;
        }
        memcpy ( data, read_struct->pointer, real_length );
        if ( real_length < length )
        {
            std::cout << __FUNCTION__ << " Returning " << real_length << " bytes instead of requested " << length << " because of end of memory" << std::endl;
            memset ( data + real_length, 0, length - real_length );
        }
        read_struct->pointer += real_length;
    }

    PngImage::PngImage ( const std::string & aFileName )
    {
        //--------------------------------------------------------
        // File loading code
        std::ifstream file;
        file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
        file.open ( aFileName, std::ios::binary );
        std::vector<uint8_t> buffer ( (
                                          std::istreambuf_iterator<char> ( file ) ),
                                      ( std::istreambuf_iterator<char>() ) );
        file.close();
        //--------------------------------------------------------

        if ( png_sig_cmp ( buffer.data(), 0, 8 ) == 0 )
        {
            png_structp png_ptr =
                png_create_read_struct ( PNG_LIBPNG_VER_STRING,
                                         nullptr, nullptr, nullptr );
            if ( png_ptr == nullptr )
            {
                throw std::runtime_error ( "png_create_read_struct failed." );
            }
            png_infop info_ptr = png_create_info_struct ( png_ptr );
            if ( info_ptr == nullptr )
            {
                throw std::runtime_error ( "png_create_info_struct failed." );
            }
            if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
            {
                throw std::runtime_error ( "Error during init_io." );
            }
            png_read_memory_struct read_memory_struct = {buffer.data(), buffer.data() + 8,
                                                         static_cast<png_size_t> ( buffer.size() *sizeof ( uint8_t ) )
                                                        };
            png_set_read_fn ( png_ptr, &read_memory_struct, png_read_memory_data );
            png_set_sig_bytes ( png_ptr, 8 );

            png_read_info ( png_ptr, info_ptr );

            mWidth = png_get_image_width ( png_ptr, info_ptr );
            mHeight = png_get_image_height ( png_ptr, info_ptr );
            png_byte color_type = png_get_color_type ( png_ptr, info_ptr );
            png_byte bit_depth = png_get_bit_depth ( png_ptr, info_ptr );

            if ( ( color_type == PNG_COLOR_TYPE_RGB ) || ( color_type == PNG_COLOR_TYPE_RGBA ) )
            {
                mFormat = ( color_type == PNG_COLOR_TYPE_RGB ) ? ImageFormat::RGB : ImageFormat::RGBA;
                mType   = ( bit_depth == 8 ) ? ImageType::UNSIGNED_BYTE : ImageType::UNSIGNED_SHORT;
            }
            else
            {
                throw std::runtime_error ( "PNG image color type not supported...yet" );
            }

            /*int number_of_passes =*/ png_set_interlace_handling ( png_ptr );
            png_read_update_info ( png_ptr, info_ptr );

            /* read file */
            if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
            {
                throw std::runtime_error ( "Error during read_image." );
            }
            // --------------------------------------
            // This has to be changed to create a single buffer to which all row_pointers point at.
            // See http://www.piko3d.com/tutorials/libpng-tutorial-loading-png-files-from-streams
            png_size_t rowbytes = png_get_rowbytes ( png_ptr, info_ptr );
            std::vector<uint8_t*> row_pointers ( sizeof ( png_bytep ) * mHeight );
            mData.resize ( rowbytes * mHeight );
            for ( png_uint_32 y = 0; y < mHeight; ++y )
            {
                row_pointers[y] = mData.data() + ( rowbytes * y );
            }
            // --------------------------------------
            png_read_image ( png_ptr, row_pointers.data() );
            png_destroy_read_struct ( &png_ptr, &info_ptr, ( png_infopp ) nullptr );
        }
        else
        {
            throw std::runtime_error ( "Image format not supported...yet" );
        }
    }
    PngImage::~PngImage()
        = default;
    uint32_t PngImage::Width() const
    {
        return mWidth;
    }
    uint32_t PngImage::Height() const
    {
        return mHeight;
    }
    Image::ImageFormat PngImage::Format() const
    {
        return mFormat;
    }
    Image::ImageType PngImage::Type() const
    {
        return mType;
    }
    const uint8_t* PngImage::Data() const
    {
        return mData.data();
    }
    const size_t PngImage::DataSize() const
    {
        return mData.size();
    }
}
<|endoftext|>


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

#include <precomp.h>
#include "aryattrs.hxx"

// NOT FULLY DEFINED SERVICES
#include <ary/cpp/c_class.hxx>
#include <ary/cpp/c_disply.hxx>
#include <ary/cpp/c_enum.hxx>
#include <ary/cpp/c_funct.hxx>
#include <ary/cpp/c_namesp.hxx>
#include <ary/info/codeinfo.hxx>
#include "strconst.hxx"

//********************       HtmlDisplay_Impl        *********************//

const char *
Get_ClassTypeKey( const ary::cpp::Class & i_rClass )
{
    return i_rClass.ClassKey() == ary::cpp::CK_class
                            ?   C_sHFTypeTitle_Class
                            :   i_rClass.ClassKey() == ary::cpp::CK_struct
                                    ?   C_sHFTypeTitle_Struct
                                    :   C_sHFTypeTitle_Union;

}

const char *
Get_TypeKey( const ary::CodeEntity & i_rCe )
{
    if ( i_rCe.RC() == ary::cpp::Class::RC_() )
    {
        csv_assert( dynamic_cast< const ary::cpp::Class* >(&i_rCe) != 0  );
        return Get_ClassTypeKey(
                    static_cast< const ary::cpp::Class& >(i_rCe) );
    }
    if ( i_rCe.RC() == ary::cpp::Enum::RC_() )
    {
         return "enum";
    }
    return "";
}

bool
Ce_IsInternal( const ary::CodeEntity & i_rCe )
{
    return NOT i_rCe.IsVisible();
}

const char *
Namespace_DisplayName( const ary::cpp::Namespace & i_rNsp )
{
     return i_rNsp.Depth() > 0
                ?   i_rNsp.LocalName().c_str()
                :   "GlobalNamespace of C++";
}

const char *
TypeText( ary::Tid                      i_nId,
          const ary::cpp::DisplayGate & i_rAryGate )
{
     static StreamStr sResult(2000);
    sResult.seekp(0);
    i_rAryGate.Get_TypeText(sResult, i_nId);

    return sResult.c_str();
}

const char *
SyntaxText_PreName( const ary::cpp::Function &      i_rFunction,
                    const ary::cpp::DisplayGate &   i_rAryGate )
{
    static StreamStr  sResult( 150 );
    sResult.seekp(0);

    // write pre-name:
    const ary::cpp::FunctionFlags & rFlags = i_rFunction.Flags();
    if ( rFlags.IsStaticLocal() OR rFlags.IsStaticMember() )
        sResult << "static ";
    if ( rFlags.IsExplicit() )
        sResult << "explicit ";
    if ( rFlags.IsMutable() )
        sResult << "mutable ";
    if ( i_rFunction.Virtuality() != ary::cpp::VIRTUAL_none )
        sResult << "virtual ";
    i_rAryGate.Get_TypeText( sResult, i_rFunction.ReturnType() );
    sResult << " ";

    return sResult.c_str();
}

const char *
SyntaxText_PostName( const ary::cpp::Function &     i_rFunction,
                     const ary::cpp::DisplayGate &  i_rAryGate )
{
    static StreamStr  sResult( 850 );
    sResult.seekp(0);

    // parameters and con_vol
    i_rAryGate.Get_SignatureText( sResult, i_rFunction.Signature(), &i_rFunction.ParamInfos() );

    // write Exceptions:
    const std::vector< ary::Tid > *
            pThrow = i_rFunction.Exceptions();
    if ( pThrow)
    {

        std::vector< ary::Tid >::const_iterator
                it = pThrow->begin();
        std::vector< ary::Tid >::const_iterator
                it_end = pThrow->end();

        if (it != it_end)
        {
            sResult << " throw( ";
            i_rAryGate.Get_TypeText(sResult, *it);

            for ( ++it; it != it_end; ++it )
            {
                sResult << ", ";
                i_rAryGate.Get_TypeText(sResult, *it);
            }
            sResult << " )";
        }
        else
        {
            sResult << " throw( )";
        }
    }   // endif // pThrow

    // abstractness:
    if ( i_rFunction.Virtuality() == ary::cpp::VIRTUAL_abstract )
        sResult << " = 0";

    // finish:
    sResult << ";";

    return sResult.c_str();
}

bool
Get_TypeText( const char * &                o_rPreName,
              const char * &                o_rName,
              const char * &                o_rPostName,
              ary::Tid                      i_nTypeid,
              const ary::cpp::DisplayGate & i_rAryGate )
{
    static StreamStr       sResult_PreName(250);
    static StreamStr       sResult_Name(250);
    static StreamStr       sResult_PostName(250);

    sResult_PreName.seekp(0);
    sResult_Name.seekp(0);
    sResult_PostName.seekp(0);

    bool    ret = i_rAryGate.Get_TypeText(
                                sResult_PreName,
                                sResult_Name,
                                sResult_PostName,
                                i_nTypeid );
    if ( sResult_PreName.tellp() > 0 )
    {
        char cLast = *( sResult_PreName.c_str() + (sResult_PreName.tellp() - 1) );
        if (cLast != ':' AND cLast != ' ')
            sResult_PreName << " ";
    }

    if (ret)
    {
        o_rPreName  = sResult_PreName.c_str();
        o_rName     = sResult_Name.c_str();
        o_rPostName = sResult_PostName.c_str();
    }
    else
    {
        o_rPreName  =  o_rName =  o_rPostName = "";
    }
    return ret;
}

//*********************         FunctionParam_Iterator      *****************//

FunctionParam_Iterator::FunctionParam_Iterator()
    :   // itTypes
        // itTypes_end
        // itNames_andMore
        // itNames_andMore_end
        eConVol(ary::cpp::CONVOL_none)
{
    static std::vector<ary::Tid>    aTypesNull_;
    static StringVector             aNamesNull_;

    itTypes = itTypes_end = aTypesNull_.end();
    itNames_andMore = itNames_andMore_end = aNamesNull_.end();
}

FunctionParam_Iterator::~FunctionParam_Iterator()
{
}

FunctionParam_Iterator &
FunctionParam_Iterator::operator++()
{
    if ( IsValid() )
    {
        ++itTypes;
        ++itNames_andMore;
    }
    return *this;
}

void
FunctionParam_Iterator::Assign( const ary::cpp::Function &      i_rFunction,
                                const ary::cpp::DisplayGate &   i_rAryGate )
{
    const ary::cpp::OperationSignature *
        pSigna = i_rAryGate.Find_Signature( i_rFunction.Signature() );
    if (pSigna == 0 )
        return;

    const std::vector<ary::Tid> &
        rTypes = pSigna->Parameters();
    const StringVector &
        rNames = i_rFunction.ParamInfos();

    if ( rTypes.size() != rNames.size() OR rTypes.size() == 0 )
        return;

    itTypes     = rTypes.begin();
    itTypes_end = rTypes.end();
    itNames_andMore     = rNames.begin();
    itNames_andMore_end = rNames.end();

    eConVol = pSigna->ConVol();
}

<commit_msg>INTEGRATION: CWS adc18 (1.6.2); FILE MERGED 2007/10/19 13:03:21 np 1.6.2.3: #i81775# 2007/10/19 11:50:49 np 1.6.2.2: #i81775# 2007/10/18 15:23:12 np 1.6.2.1: #i81775#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: aryattrs.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 16:23:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <precomp.h>
#include "aryattrs.hxx"

// NOT FULLY DEFINED SERVICES
#include <ary/getncast.hxx>
#include <ary/cpp/c_class.hxx>
#include <ary/cpp/c_enum.hxx>
#include <ary/cpp/c_funct.hxx>
#include <ary/cpp/c_gate.hxx>
#include <ary/cpp/c_namesp.hxx>
#include <ary/cpp/cp_ce.hxx>
#include <ary/cpp/cp_type.hxx>
#include "strconst.hxx"

//********************       HtmlDisplay_Impl        *********************//

const char *
Get_ClassTypeKey( const ary::cpp::Class & i_rClass )
{
    return i_rClass.ClassKey() == ary::cpp::CK_class
                            ?   C_sHFTypeTitle_Class
                            :   i_rClass.ClassKey() == ary::cpp::CK_struct
                                    ?   C_sHFTypeTitle_Struct
                                    :   C_sHFTypeTitle_Union;

}

const char *
Get_TypeKey( const ary::cpp::CodeEntity & i_rCe )
{
    if ( ary::is_type<ary::cpp::Class>(i_rCe) )
    {
        return Get_ClassTypeKey(
                    ary::ary_cast<ary::cpp::Class>(i_rCe) );
    }
    if ( ary::is_type<ary::cpp::Enum>(i_rCe) )
    {
         return "enum";
    }
    return "";
}

bool
Ce_IsInternal( const ary::cpp::CodeEntity & i_rCe )
{
    return NOT i_rCe.IsVisible();
}

const char *
Namespace_DisplayName( const ary::cpp::Namespace & i_rNsp )
{
     return i_rNsp.Depth() > 0
                ?   i_rNsp.LocalName().c_str()
                :   "GlobalNamespace of C++";
}

const char *
TypeText( ary::cpp::Type_id         i_nId,
          const ary::cpp::Gate &    i_rAryGate )
{
     static StreamStr sResult(2000);
    sResult.seekp(0);
    i_rAryGate.Types().Get_TypeText(sResult, i_nId);

    return sResult.c_str();
}

const char *
SyntaxText_PreName( const ary::cpp::Function &      i_rFunction,
                    const ary::cpp::Gate &   i_rAryGate )
{
    static StreamStr  sResult( 150 );
    sResult.seekp(0);

    // write pre-name:
    const ary::cpp::FunctionFlags & rFlags = i_rFunction.Flags();
    if ( rFlags.IsStaticLocal() OR rFlags.IsStaticMember() )
        sResult << "static ";
    if ( rFlags.IsExplicit() )
        sResult << "explicit ";
    if ( rFlags.IsMutable() )
        sResult << "mutable ";
    if ( i_rFunction.Virtuality() != ary::cpp::VIRTUAL_none )
        sResult << "virtual ";
    i_rAryGate.Types().Get_TypeText( sResult, i_rFunction.ReturnType() );
    sResult << " ";

    return sResult.c_str();
}

const char *
SyntaxText_PostName( const ary::cpp::Function &     i_rFunction,
                     const ary::cpp::Gate &  i_rAryGate )
{
    static StreamStr  sResult( 850 );
    sResult.seekp(0);

    // parameters and con_vol
    i_rAryGate.Ces().Get_SignatureText( sResult, i_rFunction.Signature(), &i_rFunction.ParamInfos() );

    // write Exceptions:
    const std::vector< ary::cpp::Type_id > *
            pThrow = i_rFunction.Exceptions();
    if ( pThrow)
    {

        std::vector< ary::cpp::Type_id >::const_iterator
                it = pThrow->begin();
        std::vector< ary::cpp::Type_id >::const_iterator
                it_end = pThrow->end();

        if (it != it_end)
        {
            sResult << " throw( ";
            i_rAryGate.Types().Get_TypeText(sResult, *it);

            for ( ++it; it != it_end; ++it )
            {
                sResult << ", ";
                i_rAryGate.Types().Get_TypeText(sResult, *it);
            }
            sResult << " )";
        }
        else
        {
            sResult << " throw( )";
        }
    }   // endif // pThrow

    // abstractness:
    if ( i_rFunction.Virtuality() == ary::cpp::VIRTUAL_abstract )
        sResult << " = 0";

    // finish:
    sResult << ";";

    return sResult.c_str();
}

bool
Get_TypeText( const char * &                o_rPreName,
              const char * &                o_rName,
              const char * &                o_rPostName,
              ary::cpp::Type_id             i_nTypeid,
              const ary::cpp::Gate & i_rAryGate )
{
    static StreamStr       sResult_PreName(250);
    static StreamStr       sResult_Name(250);
    static StreamStr       sResult_PostName(250);

    sResult_PreName.seekp(0);
    sResult_Name.seekp(0);
    sResult_PostName.seekp(0);

    bool    ret = i_rAryGate.Types().Get_TypeText(
                                sResult_PreName,
                                sResult_Name,
                                sResult_PostName,
                                i_nTypeid );
    if ( sResult_PreName.tellp() > 0 )
    {
        char cLast = *( sResult_PreName.c_str() + (sResult_PreName.tellp() - 1) );
        if (cLast != ':' AND cLast != ' ')
            sResult_PreName << " ";
    }

    if (ret)
    {
        o_rPreName  = sResult_PreName.c_str();
        o_rName     = sResult_Name.c_str();
        o_rPostName = sResult_PostName.c_str();
    }
    else
    {
        o_rPreName  =  o_rName =  o_rPostName = "";
    }
    return ret;
}

//*********************         FunctionParam_Iterator      *****************//

FunctionParam_Iterator::FunctionParam_Iterator()
    :   // itTypes
        // itTypes_end
        // itNames_andMore
        // itNames_andMore_end
        eConVol(ary::cpp::CONVOL_none)
{
    static std::vector<ary::cpp::Type_id>   aTypesNull_;
    static StringVector                     aNamesNull_;

    itTypes = itTypes_end = aTypesNull_.end();
    itNames_andMore = itNames_andMore_end = aNamesNull_.end();
}

FunctionParam_Iterator::~FunctionParam_Iterator()
{
}

FunctionParam_Iterator &
FunctionParam_Iterator::operator++()
{
    if ( IsValid() )
    {
        ++itTypes;
        ++itNames_andMore;
    }
    return *this;
}

void
FunctionParam_Iterator::Assign( const ary::cpp::Function &  i_rFunction )
{
    const ary::cpp::OperationSignature &
        rSigna = i_rFunction.Signature();

    const std::vector<ary::cpp::Type_id> &
        rTypes = rSigna.Parameters();
    const StringVector &
        rNames = i_rFunction.ParamInfos();

    if ( rTypes.size() != rNames.size() OR rTypes.size() == 0 )
        return;

    itTypes     = rTypes.begin();
    itTypes_end = rTypes.end();
    itNames_andMore     = rNames.begin();
    itNames_andMore_end = rNames.end();

    eConVol = rSigna.ConVol();
}
<|endoftext|>


<commit_before>#include "TestUtils.h"

namespace SupergodEngineTesting
{
	using namespace Math;

	TEST_CLASS(Vector2DTests)
	{
	private:
		TEST_METHOD(ConstructorTest)
		{
			Vector2D first(1, 1);
			Assert::AreEqual(first.x, 1.f);
			Assert::AreEqual(first.y, 1.f);

			Vector2D second(3, 876);
			Assert::AreEqual(second.x, 3.f);
			Assert::AreEqual(second.y, 876.f);

			Vector2D third(5, -2.3f);
			Assert::AreEqual(third.x, 5.f);
			Assert::AreEqual(third.y, -2.3f);
		}

		TEST_METHOD(EqualityTests)
		{
			Assert::IsTrue(Vector2D(10, 10) == Vector2D(10, 10));
			Assert::IsFalse(Vector2D(5, 10) == Vector2D(10, 10));
			Assert::IsTrue(Vector2D(10, 10).Equals(Vector2D(10, 10)));
			Assert::IsFalse(Vector2D(10, 10).Equals(Vector2D(10, 4)));

			Assert::IsFalse(Vector2D(10, 10) != Vector2D(10, 10));
			Assert::IsTrue(Vector2D(5, 10) != Vector2D(10, 10));
		}

		TEST_METHOD(BiggestSmallestComponentTest)
		{
			Vector2D vector(5, 2);
			Assert::AreEqual(Vector::SmallestComponent(vector), 2.f);
			Assert::AreNotEqual(Vector::SmallestComponent(vector), 5.f);
			Assert::AreEqual(Vector::BiggestComponent(vector), 5.f);
			Assert::AreNotEqual(Vector::BiggestComponent(vector), 2.f);

			Assert::AreEqual(vector.SmallestComponent(), 2.f);
			Assert::AreNotEqual(vector.SmallestComponent(), 5.f);
			Assert::AreEqual(vector.BiggestComponent(), 5.f);
			Assert::AreNotEqual(vector.BiggestComponent(), 2.f);

			vector.SmallestComponent() = 0;
			Assert::AreEqual(vector.y, 0.f);
			Assert::AreEqual(vector.SmallestComponent(), 0.f);

			vector.BiggestComponent() = 2;
			Assert::AreEqual(vector.x, 2.f);
			Assert::AreEqual(vector.BiggestComponent(), 2.f);
		}

		TEST_METHOD(ContainsAxisTest)
		{
			Vector2D vector(1, 2);
			Assert::IsTrue(vector.ContainsComponent([](float x) { return x == 1; }));
			Assert::IsTrue(vector.ContainsComponent([](float x) { return x == 2; }));
			Assert::IsFalse(vector.ContainsComponent([](float x) { return x == 3; }));
		}

		TEST_METHOD(CloseEnoughTest)
		{
			Vector2D left(4, 2);
			Vector2D right(2, 4);

			Assert::IsTrue(!left.CloseEnough(right));
			Assert::IsTrue(!right.CloseEnough(left));

			Assert::IsTrue(left.CloseEnough(right, 2));
			Assert::IsTrue(right.CloseEnough(left, 2));
		}

		// TODO: Maybe insert IndexerTest here later.

		TEST_METHOD(MagnitudeTest)
		{
			Vector2D vec(5, .6f);
			Assert::AreEqual(vec.Magnitude(), Vector::Magnitude(vec));
			AssertUtils::CloseEnough(vec.Magnitude(), 5.03587f);

			AssertUtils::CloseEnough(vec.SqrMagnitude(), Vector::SqrMagnitude(vec));
			AssertUtils::CloseEnough(vec.SqrMagnitude(), 25.36f);

			vec = Vector2D(-5, .2f);
			Assert::IsTrue(vec.Magnitude() == Vector::Magnitude(vec) && SMath::CloseEnough(vec.Magnitude(), 5.004f));
			Assert::IsTrue(SMath::CloseEnough(vec.SqrMagnitude(), Vector::SqrMagnitude(vec)) && SMath::CloseEnough(vec.SqrMagnitude(), 25.04f));
		}

		// TODO: Maybe insert
		//        ProjectOntoTest, ReflectionTest, AngleTest,
		//		  DistanceTests and LookPointAtTests here later.

		TEST_METHOD(ClampingTests)
		{
			Vector2D vector = Vector2D(0, 10).Clamp(Vector2D(-2, 15), Vector2D(2, 20));
			AssertUtils::AreEqual(vector, Vector2D(0, 15));

			vector = Vector2D(2, 2).ClampComponents(0, 1);
			AssertUtils::AreEqual(vector, Vector2D(1, 1));

			vector = Vector2D(2, 2).ClampComponents(3, 4);
			AssertUtils::AreEqual(vector, Vector2D(3, 3));

			Vector2D lengthVector = Vector2D(1, 1);
			Vector2D oldLengthVector = lengthVector;
			lengthVector = lengthVector.ClampMagnitude(.5f, .7f);

			Assert::AreEqual(lengthVector.Magnitude(), .7f);
			AssertUtils::AreEqual(lengthVector.Normalized(), oldLengthVector.Normalized());

			lengthVector = Vector2D(10, 10);
			oldLengthVector = lengthVector;
			lengthVector = lengthVector.ClampMagnitude(18, 20);

			Assert::AreEqual(lengthVector.Magnitude(), 18.f);
			AssertUtils::AreEqual(lengthVector.Normalized(), oldLengthVector.Normalized());

			lengthVector = Vector2D(5, 5);
			oldLengthVector = lengthVector;
			lengthVector = lengthVector.ClampMagnitude(-10, 10);
			Assert::AreEqual(lengthVector.Magnitude(), oldLengthVector.Magnitude());
			AssertUtils::AreEqual(lengthVector.Normalized(), oldLengthVector.Normalized());

			AssertUtils::AreEqual(Vector2D(-1, -2).Abs(), Vector2D(1, 2));
			AssertUtils::AreEqual(Absolutable::Abs(Vector2D(1, 2)), Vector2D(1, 2));
		}

		// TODO: Maybe insert LerpTests here later.
		TEST_METHOD(LerpTest)
		{
			Vector2D a(-10, -5);
			Vector2D b(2, .5f);
			Vector2D difference = b - a;

			Test01([&](float alpha)
			{
				Vector2D result1 = Lerper::Lerp(a, b, alpha);
				Vector2D result1NonStatic = a.Lerp(b, alpha);
				Vector2D result2 = a + alpha * difference;

				AssertUtils::CloseEnough(result1.x, result2.x);
				AssertUtils::CloseEnough(result1.y, result2.y);

				AssertUtils::CloseEnough(result1NonStatic.x, result2.x);
				AssertUtils::CloseEnough(result1NonStatic.y, result2.y);
			});
		}

		TEST_METHOD(AdditionTest)
		{
			Vector2D left(1, 1);
			Vector2D right(3, 5);
			Vector2D expectedResult(4, 6);

			Assert::IsTrue(left + right == expectedResult);
			Assert::IsTrue(left.Add(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Add(left, right) == expectedResult);

			left = Vector2D(3, 876);
			right = Vector2D(-1, -500);
			expectedResult = Vector2D(2, 376);

			Assert::IsTrue(left + right == expectedResult);
			Assert::IsTrue(left.Add(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Add(left, right) == expectedResult);

			left = Vector2D(5, -2.3f);
			right = Vector2D(5, 0.3f);
			expectedResult = Vector2D(10, -2);

			Assert::IsTrue(left + right == expectedResult);
			Assert::IsTrue(left.Add(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Add(left, right) == expectedResult);
		}

		TEST_METHOD(SubtractionTest)
		{
			Vector2D left(1, 1);
			Vector2D right(3, 5);
			Vector2D expectedResult(-2, -4);

			Assert::IsTrue(left - right == expectedResult);
			Assert::IsTrue(left.Subtract(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Subtract(left, right) == expectedResult);

			left = Vector2D(3, 876);
			right = Vector2D(-1, -500);
			expectedResult = Vector2D(4, 1376);

			Assert::IsTrue(left - right == expectedResult);
			Assert::IsTrue(left.Subtract(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Subtract(left, right) == expectedResult);

			left = Vector2D(5, -2.3f);
			right = Vector2D(5, 0.3f);
			expectedResult = Vector2D(0, -2.6f);

			Assert::IsTrue(left - right == expectedResult);
			Assert::IsTrue(left.Subtract(right) == expectedResult);
		}

		TEST_METHOD(NegatingTest)
		{
			Vector2D vector(1, 1);
			Vector2D expectedResult(-1, -1);

			Assert::IsTrue(-vector == expectedResult);
			Assert::IsTrue(vector.Negated() == expectedResult);
			Assert::IsTrue(ArithmeticOps::Negate(vector) == expectedResult);

			vector = Vector2D(2, 5);
			expectedResult = Vector2D(-2, -5);

			Assert::IsTrue(-vector == expectedResult);
			Assert::IsTrue(vector.Negated() == expectedResult);
			Assert::IsTrue(ArithmeticOps::Negate(vector) == expectedResult);

			vector = Vector2D(-2, 6.5f);
			expectedResult = Vector2D(2, -6.5f);

			Assert::IsTrue(-vector == expectedResult);
			Assert::IsTrue(vector.Negated() == expectedResult);
			Assert::IsTrue(ArithmeticOps::Negate(vector) == expectedResult);
		}

		TEST_METHOD(ScalarMultiplicationTest)
		{
			Vector2D vector(1, 1);
			float scalar = 5;
			Vector2D expectedResult(5, 5);

			Assert::IsTrue(vector * scalar == expectedResult);
			Assert::IsTrue(scalar * vector == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(vector, scalar) == expectedResult);
			Assert::IsTrue(vector.Multiply(scalar) == expectedResult);

			vector = Vector2D(3, 876);
			scalar = 2;
			expectedResult = Vector2D(6, 1752);

			Assert::IsTrue(vector * scalar == expectedResult);
			Assert::IsTrue(scalar * vector == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(vector, scalar) == expectedResult);
			Assert::IsTrue(vector.Multiply(scalar) == expectedResult);

			vector = Vector2D(5, .3f);
			scalar = -1.5f;
			expectedResult = Vector2D(-7.5f, -.45f);

			Assert::IsTrue((vector * scalar).CloseEnough(expectedResult));
			Assert::IsTrue((scalar * vector).CloseEnough(expectedResult));
			Assert::IsTrue(ArithmeticOps::Multiply(vector, scalar).CloseEnough(expectedResult));
			Assert::IsTrue(vector.Multiply(scalar).CloseEnough(expectedResult));
		}

		TEST_METHOD(DivisionTest)
		{
			Vector2D vector(5, 2);
			float scalar = 2;
			Vector2D expectedResult(2.5f, 1);

			AssertUtils::AreEqual(vector / scalar, expectedResult);
			AssertUtils::AreEqual(vector.Divide(scalar), expectedResult);
			AssertUtils::AreEqual(ArithmeticOps::Divide(vector, scalar), expectedResult);

			vector = Vector2D(.5f, -5);
			scalar = .5f;
			expectedResult = Vector2D(1, -10);

			AssertUtils::AreEqual(vector / scalar, expectedResult);
			AssertUtils::AreEqual(vector.Divide(scalar), expectedResult);
			AssertUtils::AreEqual(ArithmeticOps::Divide(vector, scalar), expectedResult);

			vector = Vector2D(5, 2);
			Vector2D vector2 = Vector2D(2, -2);
			expectedResult = Vector2D(2.5f, -1);

			AssertUtils::AreEqual(vector / vector2, expectedResult);
			AssertUtils::AreEqual(vector.Divide(vector2), expectedResult);
			AssertUtils::AreEqual(ArithmeticOps::Divide(vector, vector2), expectedResult);

			vector = Vector2D(1, -5);
			vector2 = Vector2D(5, 2);
			expectedResult = Vector2D(.2f, -2.5f);

			AssertUtils::AreEqual(vector / vector2, expectedResult);
			AssertUtils::AreEqual(vector.Divide(vector2), expectedResult);
			AssertUtils::AreEqual(ArithmeticOps::Divide(vector, vector2), expectedResult);
		}

		TEST_METHOD(MultiplicationTest)
		{
			Vector2D left = Vector2D(1, 1);
			Vector2D right = Vector2D(2, 0);
			Vector2D expectedResult = Vector2D(2, 0);

			Assert::IsTrue(left * right == expectedResult);
			Assert::IsTrue(left.Multiply(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(left, right) == expectedResult);

			left = Vector2D(3, 10);
			right = Vector2D(-1, 1.5f);
			expectedResult = Vector2D(-3, 15);

			Assert::IsTrue(left * right == expectedResult);
			Assert::IsTrue(left.Multiply(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(left, right) == expectedResult);

			left = Vector2D(3, 5);
			right = Vector2D(5, -.5f);
			expectedResult = Vector2D(15, -2.5f);

			Assert::IsTrue(left * right == expectedResult);
			Assert::IsTrue(left.Multiply(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(left, right) == expectedResult);
		}

		TEST_METHOD(DotTest)
		{
			Vector2D firstLeft(1, 5);
			Vector2D firstRight(2, .5f);
			float first = Vector::Dot(firstLeft, firstRight);
			Assert::IsTrue(first == 4.5f);

			Vector2D secondLeft = Vector2D(-2, -4);
			Vector2D secondRight = Vector2D(5, 5);
			float second = Vector::Dot(secondLeft, secondRight);
			Assert::IsTrue(second == -30);

			Vector2D thirdLeft = Vector2D(-2, -4);
			Vector2D thirdRight = Vector2D(5, 5);
			float third = thirdLeft.Dot(thirdRight);
			Assert::IsTrue(third == -30);
		}

		// TODO: MAYBE test conversions (depends on if they will even exist).
	};
}<commit_msg>Removed a comment I forgot to remove previously.<commit_after>#include "TestUtils.h"

namespace SupergodEngineTesting
{
	using namespace Math;

	TEST_CLASS(Vector2DTests)
	{
	private:
		TEST_METHOD(ConstructorTest)
		{
			Vector2D first(1, 1);
			Assert::AreEqual(first.x, 1.f);
			Assert::AreEqual(first.y, 1.f);

			Vector2D second(3, 876);
			Assert::AreEqual(second.x, 3.f);
			Assert::AreEqual(second.y, 876.f);

			Vector2D third(5, -2.3f);
			Assert::AreEqual(third.x, 5.f);
			Assert::AreEqual(third.y, -2.3f);
		}

		TEST_METHOD(EqualityTests)
		{
			Assert::IsTrue(Vector2D(10, 10) == Vector2D(10, 10));
			Assert::IsFalse(Vector2D(5, 10) == Vector2D(10, 10));
			Assert::IsTrue(Vector2D(10, 10).Equals(Vector2D(10, 10)));
			Assert::IsFalse(Vector2D(10, 10).Equals(Vector2D(10, 4)));

			Assert::IsFalse(Vector2D(10, 10) != Vector2D(10, 10));
			Assert::IsTrue(Vector2D(5, 10) != Vector2D(10, 10));
		}

		TEST_METHOD(BiggestSmallestComponentTest)
		{
			Vector2D vector(5, 2);
			Assert::AreEqual(Vector::SmallestComponent(vector), 2.f);
			Assert::AreNotEqual(Vector::SmallestComponent(vector), 5.f);
			Assert::AreEqual(Vector::BiggestComponent(vector), 5.f);
			Assert::AreNotEqual(Vector::BiggestComponent(vector), 2.f);

			Assert::AreEqual(vector.SmallestComponent(), 2.f);
			Assert::AreNotEqual(vector.SmallestComponent(), 5.f);
			Assert::AreEqual(vector.BiggestComponent(), 5.f);
			Assert::AreNotEqual(vector.BiggestComponent(), 2.f);

			vector.SmallestComponent() = 0;
			Assert::AreEqual(vector.y, 0.f);
			Assert::AreEqual(vector.SmallestComponent(), 0.f);

			vector.BiggestComponent() = 2;
			Assert::AreEqual(vector.x, 2.f);
			Assert::AreEqual(vector.BiggestComponent(), 2.f);
		}

		TEST_METHOD(ContainsAxisTest)
		{
			Vector2D vector(1, 2);
			Assert::IsTrue(vector.ContainsComponent([](float x) { return x == 1; }));
			Assert::IsTrue(vector.ContainsComponent([](float x) { return x == 2; }));
			Assert::IsFalse(vector.ContainsComponent([](float x) { return x == 3; }));
		}

		TEST_METHOD(CloseEnoughTest)
		{
			Vector2D left(4, 2);
			Vector2D right(2, 4);

			Assert::IsTrue(!left.CloseEnough(right));
			Assert::IsTrue(!right.CloseEnough(left));

			Assert::IsTrue(left.CloseEnough(right, 2));
			Assert::IsTrue(right.CloseEnough(left, 2));
		}

		// TODO: Maybe insert IndexerTest here later.

		TEST_METHOD(MagnitudeTest)
		{
			Vector2D vec(5, .6f);
			Assert::AreEqual(vec.Magnitude(), Vector::Magnitude(vec));
			AssertUtils::CloseEnough(vec.Magnitude(), 5.03587f);

			AssertUtils::CloseEnough(vec.SqrMagnitude(), Vector::SqrMagnitude(vec));
			AssertUtils::CloseEnough(vec.SqrMagnitude(), 25.36f);

			vec = Vector2D(-5, .2f);
			Assert::IsTrue(vec.Magnitude() == Vector::Magnitude(vec) && SMath::CloseEnough(vec.Magnitude(), 5.004f));
			Assert::IsTrue(SMath::CloseEnough(vec.SqrMagnitude(), Vector::SqrMagnitude(vec)) && SMath::CloseEnough(vec.SqrMagnitude(), 25.04f));
		}

		// TODO: Maybe insert
		//        ProjectOntoTest, ReflectionTest, AngleTest,
		//		  DistanceTests and LookPointAtTests here later.

		TEST_METHOD(ClampingTests)
		{
			Vector2D vector = Vector2D(0, 10).Clamp(Vector2D(-2, 15), Vector2D(2, 20));
			AssertUtils::AreEqual(vector, Vector2D(0, 15));

			vector = Vector2D(2, 2).ClampComponents(0, 1);
			AssertUtils::AreEqual(vector, Vector2D(1, 1));

			vector = Vector2D(2, 2).ClampComponents(3, 4);
			AssertUtils::AreEqual(vector, Vector2D(3, 3));

			Vector2D lengthVector = Vector2D(1, 1);
			Vector2D oldLengthVector = lengthVector;
			lengthVector = lengthVector.ClampMagnitude(.5f, .7f);

			Assert::AreEqual(lengthVector.Magnitude(), .7f);
			AssertUtils::AreEqual(lengthVector.Normalized(), oldLengthVector.Normalized());

			lengthVector = Vector2D(10, 10);
			oldLengthVector = lengthVector;
			lengthVector = lengthVector.ClampMagnitude(18, 20);

			Assert::AreEqual(lengthVector.Magnitude(), 18.f);
			AssertUtils::AreEqual(lengthVector.Normalized(), oldLengthVector.Normalized());

			lengthVector = Vector2D(5, 5);
			oldLengthVector = lengthVector;
			lengthVector = lengthVector.ClampMagnitude(-10, 10);
			Assert::AreEqual(lengthVector.Magnitude(), oldLengthVector.Magnitude());
			AssertUtils::AreEqual(lengthVector.Normalized(), oldLengthVector.Normalized());

			AssertUtils::AreEqual(Vector2D(-1, -2).Abs(), Vector2D(1, 2));
			AssertUtils::AreEqual(Absolutable::Abs(Vector2D(1, 2)), Vector2D(1, 2));
		}

		TEST_METHOD(LerpTest)
		{
			Vector2D a(-10, -5);
			Vector2D b(2, .5f);
			Vector2D difference = b - a;

			Test01([&](float alpha)
			{
				Vector2D result1 = Lerper::Lerp(a, b, alpha);
				Vector2D result1NonStatic = a.Lerp(b, alpha);
				Vector2D result2 = a + alpha * difference;

				AssertUtils::CloseEnough(result1.x, result2.x);
				AssertUtils::CloseEnough(result1.y, result2.y);

				AssertUtils::CloseEnough(result1NonStatic.x, result2.x);
				AssertUtils::CloseEnough(result1NonStatic.y, result2.y);
			});
		}

		TEST_METHOD(AdditionTest)
		{
			Vector2D left(1, 1);
			Vector2D right(3, 5);
			Vector2D expectedResult(4, 6);

			Assert::IsTrue(left + right == expectedResult);
			Assert::IsTrue(left.Add(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Add(left, right) == expectedResult);

			left = Vector2D(3, 876);
			right = Vector2D(-1, -500);
			expectedResult = Vector2D(2, 376);

			Assert::IsTrue(left + right == expectedResult);
			Assert::IsTrue(left.Add(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Add(left, right) == expectedResult);

			left = Vector2D(5, -2.3f);
			right = Vector2D(5, 0.3f);
			expectedResult = Vector2D(10, -2);

			Assert::IsTrue(left + right == expectedResult);
			Assert::IsTrue(left.Add(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Add(left, right) == expectedResult);
		}

		TEST_METHOD(SubtractionTest)
		{
			Vector2D left(1, 1);
			Vector2D right(3, 5);
			Vector2D expectedResult(-2, -4);

			Assert::IsTrue(left - right == expectedResult);
			Assert::IsTrue(left.Subtract(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Subtract(left, right) == expectedResult);

			left = Vector2D(3, 876);
			right = Vector2D(-1, -500);
			expectedResult = Vector2D(4, 1376);

			Assert::IsTrue(left - right == expectedResult);
			Assert::IsTrue(left.Subtract(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Subtract(left, right) == expectedResult);

			left = Vector2D(5, -2.3f);
			right = Vector2D(5, 0.3f);
			expectedResult = Vector2D(0, -2.6f);

			Assert::IsTrue(left - right == expectedResult);
			Assert::IsTrue(left.Subtract(right) == expectedResult);
		}

		TEST_METHOD(NegatingTest)
		{
			Vector2D vector(1, 1);
			Vector2D expectedResult(-1, -1);

			Assert::IsTrue(-vector == expectedResult);
			Assert::IsTrue(vector.Negated() == expectedResult);
			Assert::IsTrue(ArithmeticOps::Negate(vector) == expectedResult);

			vector = Vector2D(2, 5);
			expectedResult = Vector2D(-2, -5);

			Assert::IsTrue(-vector == expectedResult);
			Assert::IsTrue(vector.Negated() == expectedResult);
			Assert::IsTrue(ArithmeticOps::Negate(vector) == expectedResult);

			vector = Vector2D(-2, 6.5f);
			expectedResult = Vector2D(2, -6.5f);

			Assert::IsTrue(-vector == expectedResult);
			Assert::IsTrue(vector.Negated() == expectedResult);
			Assert::IsTrue(ArithmeticOps::Negate(vector) == expectedResult);
		}

		TEST_METHOD(ScalarMultiplicationTest)
		{
			Vector2D vector(1, 1);
			float scalar = 5;
			Vector2D expectedResult(5, 5);

			Assert::IsTrue(vector * scalar == expectedResult);
			Assert::IsTrue(scalar * vector == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(vector, scalar) == expectedResult);
			Assert::IsTrue(vector.Multiply(scalar) == expectedResult);

			vector = Vector2D(3, 876);
			scalar = 2;
			expectedResult = Vector2D(6, 1752);

			Assert::IsTrue(vector * scalar == expectedResult);
			Assert::IsTrue(scalar * vector == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(vector, scalar) == expectedResult);
			Assert::IsTrue(vector.Multiply(scalar) == expectedResult);

			vector = Vector2D(5, .3f);
			scalar = -1.5f;
			expectedResult = Vector2D(-7.5f, -.45f);

			Assert::IsTrue((vector * scalar).CloseEnough(expectedResult));
			Assert::IsTrue((scalar * vector).CloseEnough(expectedResult));
			Assert::IsTrue(ArithmeticOps::Multiply(vector, scalar).CloseEnough(expectedResult));
			Assert::IsTrue(vector.Multiply(scalar).CloseEnough(expectedResult));
		}

		TEST_METHOD(DivisionTest)
		{
			Vector2D vector(5, 2);
			float scalar = 2;
			Vector2D expectedResult(2.5f, 1);

			AssertUtils::AreEqual(vector / scalar, expectedResult);
			AssertUtils::AreEqual(vector.Divide(scalar), expectedResult);
			AssertUtils::AreEqual(ArithmeticOps::Divide(vector, scalar), expectedResult);

			vector = Vector2D(.5f, -5);
			scalar = .5f;
			expectedResult = Vector2D(1, -10);

			AssertUtils::AreEqual(vector / scalar, expectedResult);
			AssertUtils::AreEqual(vector.Divide(scalar), expectedResult);
			AssertUtils::AreEqual(ArithmeticOps::Divide(vector, scalar), expectedResult);

			vector = Vector2D(5, 2);
			Vector2D vector2 = Vector2D(2, -2);
			expectedResult = Vector2D(2.5f, -1);

			AssertUtils::AreEqual(vector / vector2, expectedResult);
			AssertUtils::AreEqual(vector.Divide(vector2), expectedResult);
			AssertUtils::AreEqual(ArithmeticOps::Divide(vector, vector2), expectedResult);

			vector = Vector2D(1, -5);
			vector2 = Vector2D(5, 2);
			expectedResult = Vector2D(.2f, -2.5f);

			AssertUtils::AreEqual(vector / vector2, expectedResult);
			AssertUtils::AreEqual(vector.Divide(vector2), expectedResult);
			AssertUtils::AreEqual(ArithmeticOps::Divide(vector, vector2), expectedResult);
		}

		TEST_METHOD(MultiplicationTest)
		{
			Vector2D left = Vector2D(1, 1);
			Vector2D right = Vector2D(2, 0);
			Vector2D expectedResult = Vector2D(2, 0);

			Assert::IsTrue(left * right == expectedResult);
			Assert::IsTrue(left.Multiply(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(left, right) == expectedResult);

			left = Vector2D(3, 10);
			right = Vector2D(-1, 1.5f);
			expectedResult = Vector2D(-3, 15);

			Assert::IsTrue(left * right == expectedResult);
			Assert::IsTrue(left.Multiply(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(left, right) == expectedResult);

			left = Vector2D(3, 5);
			right = Vector2D(5, -.5f);
			expectedResult = Vector2D(15, -2.5f);

			Assert::IsTrue(left * right == expectedResult);
			Assert::IsTrue(left.Multiply(right) == expectedResult);
			Assert::IsTrue(ArithmeticOps::Multiply(left, right) == expectedResult);
		}

		TEST_METHOD(DotTest)
		{
			Vector2D firstLeft(1, 5);
			Vector2D firstRight(2, .5f);
			float first = Vector::Dot(firstLeft, firstRight);
			Assert::IsTrue(first == 4.5f);

			Vector2D secondLeft = Vector2D(-2, -4);
			Vector2D secondRight = Vector2D(5, 5);
			float second = Vector::Dot(secondLeft, secondRight);
			Assert::IsTrue(second == -30);

			Vector2D thirdLeft = Vector2D(-2, -4);
			Vector2D thirdRight = Vector2D(5, 5);
			float third = thirdLeft.Dot(thirdRight);
			Assert::IsTrue(third == -30);
		}

		// TODO: MAYBE test conversions (depends on if they will even exist).
	};
}<|endoftext|>


<commit_before>// Copyright (C) 2015 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "CompileConfig.h"

#if defined(OUZEL_PLATFORM_OSX) || defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
#include <sys/time.h>
#endif

#if defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
#include <sys/syslog.h>
#endif

#ifdef OUZEL_PLATFORM_WINDOWS
#include <windows.h>
#include <strsafe.h>
#endif

#ifdef OUZEL_PLATFORM_ANDROID
#include <android/log.h>
#endif

#include "Utils.h"

namespace ouzel
{
    char TEMP_BUFFER[65536];

    void log(const char* format, ...)
    {
        va_list list;
        va_start(list, format);

        vsprintf(TEMP_BUFFER, format, list);

        va_end(list);

#if defined(OUZEL_PLATFORM_OSX)
        printf("%s\n", TEMP_BUFFER);
#elif defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
        syslog(LOG_WARNING, "%s", TEMP_BUFFER);
        printf("%s\n", TEMP_BUFFER);
#elif defined(OUZEL_PLATFORM_WINDOWS)
        wchar_t szBuffer[256];
        MultiByteToWideChar(CP_ACP, 0, TEMP_BUFFER, -1, szBuffer, 256);
        StringCchCat(szBuffer, sizeof(szBuffer), L"\n");
        OutputDebugString(szBuffer);
#elif defined(OUZEL_PLATFORM_ANDROID)
        __android_log_print(ANDROID_LOG_DEBUG, "Ouzel", "%s", TEMP_BUFFER);
#endif
    }

    uint64_t getCurrentMicroSeconds()
    {
#if defined(OUZEL_PLATFORM_OSX) || defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS) || defined(OUZEL_PLATFORM_ANDROID)
        struct timeval currentTime;

        gettimeofday(&currentTime, NULL);
        return currentTime.tv_sec * 1000000L + currentTime.tv_usec;
#elif defined(OUZEL_PLATFORM_WINDOWS)
        LARGE_INTEGER li;
        if (!QueryPerformanceFrequency(&li))
        {
            log("Failed to query frequency");
            return 0;
        }
        uint64_t frequency = li.QuadPart / 1000000L;

        QueryPerformanceCounter(&li);

        return li.QuadPart / frequency;
#else
        return 0;
#endif
    }
}
<commit_msg>Query timer frequency only once on Windows<commit_after>// Copyright (C) 2015 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "CompileConfig.h"

#if defined(OUZEL_PLATFORM_OSX) || defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
#include <sys/time.h>
#endif

#if defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
#include <sys/syslog.h>
#endif

#ifdef OUZEL_PLATFORM_WINDOWS
#include <windows.h>
#include <strsafe.h>
#endif

#ifdef OUZEL_PLATFORM_ANDROID
#include <android/log.h>
#endif

#include "Utils.h"

namespace ouzel
{
    char TEMP_BUFFER[65536];

    void log(const char* format, ...)
    {
        va_list list;
        va_start(list, format);

        vsprintf(TEMP_BUFFER, format, list);

        va_end(list);

#if defined(OUZEL_PLATFORM_OSX)
        printf("%s\n", TEMP_BUFFER);
#elif defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
        syslog(LOG_WARNING, "%s", TEMP_BUFFER);
        printf("%s\n", TEMP_BUFFER);
#elif defined(OUZEL_PLATFORM_WINDOWS)
        wchar_t szBuffer[256];
        MultiByteToWideChar(CP_ACP, 0, TEMP_BUFFER, -1, szBuffer, 256);
        StringCchCat(szBuffer, sizeof(szBuffer), L"\n");
        OutputDebugString(szBuffer);
#elif defined(OUZEL_PLATFORM_ANDROID)
        __android_log_print(ANDROID_LOG_DEBUG, "Ouzel", "%s", TEMP_BUFFER);
#endif
    }

    uint64_t getCurrentMicroSeconds()
    {
#if defined(OUZEL_PLATFORM_OSX) || defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS) || defined(OUZEL_PLATFORM_ANDROID)
        struct timeval currentTime;

        gettimeofday(&currentTime, NULL);
        return currentTime.tv_sec * 1000000L + currentTime.tv_usec;
#elif defined(OUZEL_PLATFORM_WINDOWS)

        static uint64_t frequency = 0;
        LARGE_INTEGER li;

        if (!frequency)
        {
            if (!QueryPerformanceFrequency(&li))
            {
                log("Failed to query frequency");
                return 0;
            }
            frequency = li.QuadPart / 1000000L;
        }

        QueryPerformanceCounter(&li);

        return li.QuadPart / frequency;
#else
        return 0;
#endif
    }
}
<|endoftext|>


<commit_before>// Example program
#include <iostream>
#include <vector>

void Merge(std::vector<int>& sub_data,unsigned int left_index, unsigned int middle_index, unsigned int right_index){
       std::cout << "l_index : " << left_index << ", Right_index : " << right_index << ",Middle_index : " << middle_index;
       const int l_size = middle_index - left_index ;
       const int r_size = right_index - middle_index;
       std::vector<int> l_data,r_data;
       std::vector<int>::iterator itr = sub_data.begin()+left_index;
       for(int x = 0; x < l_size ; ++x){
            l_data.push_back(*itr);
            ++itr;
        }
       itr = sub_data.begin()+ middle_index + 1;
       for(int x = 0; x < r_size ; ++x){
            r_data.push_back(*itr);
            ++itr;
        }

       std::cout << " Left Data : ";
       for(const auto& x : l_data)
            std::cout << x << ",";
       std::cout << " Right Data : ";
       for(const auto& x : r_data)
            std::cout << x << ",";
        std::cout << "\n";

       // Merging the data
       int i = 0, j =0 , k = left_index;
       while(i < l_size && j < r_size){
            if(l_data[i] < r_data[j]){
                sub_data[k] = l_data[i];
                i++;
            }else{
                sub_data[k] = r_data[j];
                j++;
            }
            k++;
        }
}

void MSort(std::vector<int>& sub_data,unsigned int left_index, unsigned int right_index){
    if(left_index < right_index){
        int middle_index = left_index + (right_index-left_index) /2;
        MSort(sub_data,left_index,middle_index);
        MSort(sub_data,middle_index+1,right_index);
        Merge(sub_data,left_index,middle_index + 1,right_index);
    }

};

int main()
{
    std::vector<int> data = {38,27,43,3,9,82,10};
    for(const auto& x : data)
        std::cout << x << ",";
    std::cout << "\nStarting the sort ...\n";
    MSort(data,0,data.size());
    for(const auto& x : data)
        std::cout << x << ",";
    std::cout<< "\nFinished" << std::endl;
}
<commit_msg>Update MergeSort.cc<commit_after>// Example program
#include <iostream>
#include <vector>

void Merge(std::vector<int>& sub_data,unsigned int left_index, unsigned int middle_index, unsigned int right_index){

       const int l_size = middle_index - left_index + 1;
       const int r_size = right_index - middle_index;
       std::cout << "l_index : " << left_index << ", Right_index : " << right_index << ",Middle_index : " << middle_index << ", l_size : " << l_size << ", r_size " << r_size;
       std::vector<int> l_data,r_data;
       std::vector<int>::iterator itr = sub_data.begin()+left_index;
       for(int x = 0; x < l_size ; ++x){
            l_data.push_back(*itr);
            ++itr;
        }
       itr = sub_data.begin()+ middle_index + 1;
       for(int x = 0; x < r_size ; ++x){
            r_data.push_back(*itr);
            ++itr;
        }

       std::cout << " Left Data : ";
       for(const auto& x : l_data)
            std::cout << x << ",";
       std::cout << " Right Data : ";
       for(const auto& x : r_data)
            std::cout << x << ",";
        std::cout << "\n";

       // Merging the data
       int i = 0, j =0 , k = left_index;
       while(i < l_size && j < r_size){
            sub_data[k++] = (l_data[i] < r_data[j]) ? l_data[i++] : r_data[j++];
        }
        while (i < l_size)
            sub_data[k++] = l_data[i++];
        while (j < r_size)
            sub_data[k++] = r_data[j++];
}

void MSort(std::vector<int>& sub_data,unsigned int left_index, unsigned int right_index){
    if(left_index < right_index){
        int middle_index = left_index + (right_index-left_index) /2;
        MSort(sub_data,left_index,middle_index);
        MSort(sub_data,middle_index+1,right_index);
        Merge(sub_data,left_index,middle_index,right_index);
    }

};

int main()
{
    //std::vector<int> data = {38,27,43,3,9,82,10};
    std::vector<int> data = {38,27,43};
    for(const auto& x : data)
        std::cout << x << ",";
    std::cout << "\nStarting the sort ...\n";
    MSort(data,0,data.size());
    for(const auto& x : data)
        std::cout << x << ",";
    std::cout<< "\nFinished" << std::endl;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>

#include "TTreeFormula.h"
#include "TCanvas.h"
#include "TH1F.h"
#include "TH1.h"

#include "CutflowMaker.h"

ClassImp(CutflowMaker)

//--------------------------------------------------------------------
CutflowMaker::CutflowMaker() :
{
  fCutNames.resize(0);
  fCuts.resize(0);
  fYields.resize(0);
}

//--------------------------------------------------------------------
void
CutflowMaker::GetCutflow()
{
  if (fYields.size() == 0 && fTree != NULL) {
    std::vector<TTreeFormula*> formulae;
    TTreeFormula *tempFormula;
    for (UInt_t iCut = 0; iCut != fCuts.size(); ++iCut) {
      tempFormula = new TTreeFormula(fCutNames[iCut],fCuts[iCut],fTree);
      formulae.push_back(tempFormula);
      fYields.push_back(0);
    }
    Int_t numEntries = fTree->GetEntriesFast();
    for (Int_t iEntry = 0; iEntry != numEntries; ++iEntry) {
      fTree->GetEntry(iEntry);
      for (UInt_t iCut = 0; iCut != formulae.size(); ++iCut) {
        if (formulae[iCut]->EvalInstance() == 0)
          break;

        ++fYields[iCut];
      }
    }
    for (UInt_t iFormula = 0; iFormula != formulae.size(); ++iFormula)
      delete formulae[iFormula];
  }
}

//--------------------------------------------------------------------
void
CutflowMaker::PrintCutflow(Bool_t OnlyNums)
{
  GetCutflow();
  std::cout << std::endl;
  for (UInt_t iCut = 0; iCut != fCuts.size(); ++iCut) {
    if (!OnlyNums) {
      std::cout << std::setw(20);
      std::cout << fCutNames[iCut] << ": ";
    }
    if (fTree != NULL) {
      std::cout << std::setw(15);
      std::cout << fYields[iCut];
    }
    std::cout << std::endl;
  }
  std::cout << std::endl;
}

//--------------------------------------------------------------------
void
CutflowMaker::MakePlot(TString name, PlotStyle type)
{
  if (fTree == NULL) {
    std::cout << "Tree has not been set." << std::endl;
    exit(1);
  }
  GetCutflow();
  TH1F* theHist = new TH1F("cutflow",";;Number of Events",fCuts.size(),0,fCuts.size());
  for (UInt_t iCut = 0; iCut != fCuts.size(); ++iCut) {
    theHist->GetXaxis()->SetBinLabel(iCut+1,fCutNames[iCut]);
    if (PlotStyle == kAbsolute)
      theHist->SetBinContent(iCut+1,fYields[iCut]);
    if (PlotStyle == kFractional) {
      if (iCut == 0)
        theHist->SetBinContent(iCut+1,float(fYields[iCut])/fTree->GetEntriesFast());
      else
        theHist->SetBinContent(iCut+1,float(fYields[iCut])/fYields[iCut - 1]);
    }
  }
  theHist->SetLineWidth(2);

  TCanvas* theCanvas = new TCanvas("canvas",";;Number of Events",fWidth,fHeight);
  theHist->Draw();

  theCanvas->SaveAs(name + ".pdf");
  theCanvas->SaveAs(name + ".png");
  theCanvas->SaveAs(name + ".C");
}
<commit_msg>Small bug<commit_after>#include <iostream>
#include <iomanip>

#include "TTreeFormula.h"
#include "TCanvas.h"
#include "TH1F.h"
#include "TH1.h"

#include "CutflowMaker.h"

ClassImp(CutflowMaker)

//--------------------------------------------------------------------
CutflowMaker::CutflowMaker() :
  fWidth(600),
  fHeight(600)
{
  fCutNames.resize(0);
  fCuts.resize(0);
  fYields.resize(0);
}

//--------------------------------------------------------------------
void
CutflowMaker::GetCutflow()
{
  if (fYields.size() == 0 && fTree != NULL) {
    std::vector<TTreeFormula*> formulae;
    TTreeFormula *tempFormula;
    for (UInt_t iCut = 0; iCut != fCuts.size(); ++iCut) {
      tempFormula = new TTreeFormula(fCutNames[iCut],fCuts[iCut],fTree);
      formulae.push_back(tempFormula);
      fYields.push_back(0);
    }
    Int_t numEntries = fTree->GetEntriesFast();
    for (Int_t iEntry = 0; iEntry != numEntries; ++iEntry) {
      fTree->GetEntry(iEntry);
      for (UInt_t iCut = 0; iCut != formulae.size(); ++iCut) {
        if (formulae[iCut]->EvalInstance() == 0)
          break;

        ++fYields[iCut];
      }
    }
    for (UInt_t iFormula = 0; iFormula != formulae.size(); ++iFormula)
      delete formulae[iFormula];
  }
}

//--------------------------------------------------------------------
void
CutflowMaker::PrintCutflow(Bool_t OnlyNums)
{
  GetCutflow();
  std::cout << std::endl;
  for (UInt_t iCut = 0; iCut != fCuts.size(); ++iCut) {
    if (!OnlyNums) {
      std::cout << std::setw(20);
      std::cout << fCutNames[iCut] << ": ";
    }
    if (fTree != NULL) {
      std::cout << std::setw(15);
      std::cout << fYields[iCut];
    }
    std::cout << std::endl;
  }
  std::cout << std::endl;
}

//--------------------------------------------------------------------
void
CutflowMaker::MakePlot(TString name, PlotStyle type)
{
  if (fTree == NULL) {
    std::cout << "Tree has not been set." << std::endl;
    exit(1);
  }
  GetCutflow();
  TH1F* theHist = new TH1F("cutflow",";;Number of Events",fCuts.size(),0,fCuts.size());
  for (UInt_t iCut = 0; iCut != fCuts.size(); ++iCut) {
    theHist->GetXaxis()->SetBinLabel(iCut+1,fCutNames[iCut]);
    if (PlotStyle == kAbsolute)
      theHist->SetBinContent(iCut+1,fYields[iCut]);
    if (PlotStyle == kFractional) {
      if (iCut == 0)
        theHist->SetBinContent(iCut+1,float(fYields[iCut])/fTree->GetEntriesFast());
      else
        theHist->SetBinContent(iCut+1,float(fYields[iCut])/fYields[iCut - 1]);
    }
  }
  theHist->SetLineWidth(2);

  TCanvas* theCanvas = new TCanvas("canvas",";;Number of Events",fWidth,fHeight);
  theHist->Draw();

  theCanvas->SaveAs(name + ".pdf");
  theCanvas->SaveAs(name + ".png");
  theCanvas->SaveAs(name + ".C");
}
<|endoftext|>


<commit_before>#include <ctime>
#include <iostream>
#include <cstdlib>
#include <iterator>

#include <dariadb.h>
#include <ctime>
#include <limits>
#include <cmath>
#include <chrono>
#include <thread>
#include <random>
#include <cstdlib>
#include <atomic>

class BenchCallback :public dariadb::storage::ReaderClb {
public:
	void call(const dariadb::Meas&) {
		count++;
	}
	size_t count;
};

void writer_1(dariadb::storage::BaseStorage_ptr ms)
{
	auto m = dariadb::Meas::empty();
	dariadb::Time t = 0;
	for (dariadb::Id i = 0; i < 32768; i += 1) {
		m.id = i;
		m.flag = dariadb::Flag(0);
		m.time = t;
		m.value = dariadb::Value(i);
		ms->append(m);
		t++;
	}
}

std::atomic_long writen{ 0 };

void writer_2(dariadb::Id id_from, size_t id_per_thread, dariadb::storage::BaseStorage_ptr ms)
{
	auto m = dariadb::Meas::empty();
	std::random_device r;
	std::default_random_engine e1(r());
	std::uniform_int_distribution<int> uniform_dist(10, 64);

    size_t max_id=(id_from + id_per_thread);

    for (dariadb::Id i = id_from; i < max_id; i += 1) {
		dariadb::Value v = 1.0;
        auto max_rnd = uniform_dist(e1);
		dariadb::Time t = dariadb::timeutil::current_time();
		for (dariadb::Time p = 0; p < dariadb::Time(max_rnd); p++) {
			m.id = i;
			m.flag = dariadb::Flag(0);
			m.time = t++;
			m.value = v;
			ms->append(m);
			writen++;
			auto rnd = rand() / float(RAND_MAX);

			v += rnd;
		}

	}
}

int main(int argc, char *argv[]) {
	(void)argc;
	(void)argv;
	srand(static_cast<unsigned int>(time(NULL)));
	//{// 1.
 //       dariadb::storage::BaseStorage_ptr ms{ new dariadb::storage::MemoryStorage{ 512 } };
	//	auto start = clock();

	//	writer_1(ms);

	//	auto elapsed = ((float)clock() - start) / CLOCKS_PER_SEC;
	//	std::cout << "1. insert : " << elapsed << std::endl;
	//}
	//
    dariadb::storage::BaseStorage_ptr ms{ new dariadb::storage::MemoryStorage{ 512 } };

	{// 2.
		const size_t threads_count = 16;
		const size_t id_per_thread = size_t(32768 / threads_count);

		auto start = clock();
		std::vector<std::thread> writers(threads_count);
		size_t pos = 0;
		for (size_t i = 0; i < threads_count; i++) {
			std::thread t{ writer_2, id_per_thread*i+1, id_per_thread, ms };
			writers[pos++] = std::move(t);
		}

		pos = 0;
		for (size_t i = 0; i < threads_count; i++) {
			std::thread t = std::move(writers[pos++]);
			t.join();
		}

		auto elapsed = ((float)clock() - start) / CLOCKS_PER_SEC;
		std::cout << "2. insert : " << elapsed << std::endl;
	}
	//{//3
	//	std::random_device r;
	//	std::default_random_engine e1(r());
	//	std::uniform_int_distribution<dariadb::Id> uniform_dist(0, 32768);
	//	std::uniform_int_distribution<dariadb::Time> uniform_dist_t(0, 32768);
	//	dariadb::IdArray ids;
	//	ids.resize(1);

 //       const size_t queries_count = 32768;

 //       dariadb::IdArray rnd_ids(queries_count);
 //       std::vector<dariadb::Time> rnd_time(queries_count);
 //       for (size_t i = 0; i < queries_count; i++){
 //           rnd_ids[i]=uniform_dist(e1);
 //           rnd_time[i]=uniform_dist_t(e1);
 //       }
	//	dariadb::storage::ReaderClb_ptr clbk{ new BenchCallback() };

	//	auto start = clock();
	//
	//	for (size_t i = 0; i < queries_count; i++) {
 //           ids[0]= rnd_ids[i];
 //           auto t = rnd_time[i];
	//		auto rdr=ms->readInTimePoint(ids,0,t);
	//		rdr->readAll(clbk.get());
	//	}

	//	auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC)/ queries_count;
	//	std::cout << "3. time point: " << elapsed << std::endl;
	//}

	//{//4
	//	std::random_device r;
	//	std::default_random_engine e1(r());
	//	std::uniform_int_distribution<dariadb::Id> uniform_dist(0, 32768);

 //       const size_t queries_count = 32;

	//	dariadb::IdArray ids;
 //       std::vector<dariadb::Time> rnd_time(queries_count);
 //       for (size_t i = 0; i < queries_count; i++){
 //           rnd_time[i]=uniform_dist(e1);
 //       }

	//	dariadb::storage::ReaderClb_ptr clbk{ new BenchCallback() };

	//	auto start = clock();

	//	for (size_t i = 0; i < queries_count; i++) {
 //           auto t = rnd_time[i];
	//		auto rdr=ms->readInTimePoint(ids, 0,t);
	//		rdr->readAll(clbk.get());
	//	}

	//	auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC) / queries_count;
	//	std::cout << "4. time point: " << elapsed << std::endl;
	//}

	//{//5
	//	std::random_device r;
	//	std::default_random_engine e1(r());
	//	std::uniform_int_distribution<dariadb::Time> uniform_dist(0, 32768/2);

	//	dariadb::storage::ReaderClb_ptr clbk{ new BenchCallback() };
	//	const size_t queries_count = 32;

 //       std::vector<dariadb::Time> rnd_time_from(queries_count),rnd_time_to(queries_count);
 //       for (size_t i = 0; i < queries_count; i++){
 //           rnd_time_from[i]=uniform_dist(e1);
 //           rnd_time_to[i]=uniform_dist(e1);
 //       }

	//	auto start = clock();

	//	for (size_t i = 0; i < queries_count; i++) {
 //           auto f = rnd_time_from[i];
 //           auto t = rnd_time_to[i];
	//		auto rdr = ms->readInterval(f, t+f);
	//		rdr->readAll(clbk.get());
	//	}

	//	auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC) / queries_count;
	//	std::cout << "5. interval: " << elapsed << std::endl;
	//}

	//{//6
	//	std::random_device r;
	//	std::default_random_engine e1(r());
	//	std::uniform_int_distribution<dariadb::Time> uniform_dist(0, 32768/2);
	//	std::uniform_int_distribution<dariadb::Id> uniform_dist_id(0, 32768);

	//	const size_t ids_count = size_t(32768 * 0.1);
	//	dariadb::IdArray ids;
	//	ids.resize(ids_count);

	//	dariadb::storage::ReaderClb_ptr clbk{ new BenchCallback() };
	//	const size_t queries_count = 32;

 //       std::vector<dariadb::Time> rnd_time_from(queries_count),rnd_time_to(queries_count);
 //       for (size_t i = 0; i < queries_count; i++){
 //           rnd_time_from[i]=uniform_dist(e1);
 //           rnd_time_to[i]=uniform_dist(e1);
 //       }

	//	auto start = clock();

	//	for (size_t i = 0; i < queries_count; i++) {
	//		for (size_t j = 0; j < ids_count; j++) {
	//			ids[j] = uniform_dist_id(e1);
	//		}
 //           auto f = rnd_time_from[i];
 //           auto t = rnd_time_to[i];
	//		auto rdr = ms->readInterval(ids,0, f, t + f);
	//		rdr->readAll(clbk.get());
	//	}

	//	auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC) / queries_count;
	//	std::cout << "6. interval: " << elapsed << std::endl;
	//}
}
<commit_msg>uncomment.<commit_after>#include <ctime>
#include <iostream>
#include <cstdlib>
#include <iterator>

#include <dariadb.h>
#include <ctime>
#include <limits>
#include <cmath>
#include <chrono>
#include <thread>
#include <random>
#include <cstdlib>
#include <atomic>

class BenchCallback :public dariadb::storage::ReaderClb {
public:
	void call(const dariadb::Meas&) {
		count++;
	}
	size_t count;
};

void writer_1(dariadb::storage::BaseStorage_ptr ms)
{
	auto m = dariadb::Meas::empty();
	dariadb::Time t = 0;
	for (dariadb::Id i = 0; i < 32768; i += 1) {
		m.id = i;
		m.flag = dariadb::Flag(0);
		m.time = t;
		m.value = dariadb::Value(i);
		ms->append(m);
		t++;
	}
}

std::atomic_long writen{ 0 };

void writer_2(dariadb::Id id_from, size_t id_per_thread, dariadb::storage::BaseStorage_ptr ms)
{
	auto m = dariadb::Meas::empty();
	std::random_device r;
	std::default_random_engine e1(r());
	std::uniform_int_distribution<int> uniform_dist(10, 64);

    size_t max_id=(id_from + id_per_thread);

    for (dariadb::Id i = id_from; i < max_id; i += 1) {
		dariadb::Value v = 1.0;
        auto max_rnd = uniform_dist(e1);
		dariadb::Time t = dariadb::timeutil::current_time();
		for (dariadb::Time p = 0; p < dariadb::Time(max_rnd); p++) {
			m.id = i;
			m.flag = dariadb::Flag(0);
			m.time = t++;
			m.value = v;
			ms->append(m);
			writen++;
			auto rnd = rand() / float(RAND_MAX);

			v += rnd;
		}

	}
}

int main(int argc, char *argv[]) {
	(void)argc;
	(void)argv;
	srand(static_cast<unsigned int>(time(NULL)));
	{// 1.
        dariadb::storage::BaseStorage_ptr ms{ new dariadb::storage::MemoryStorage{ 512 } };
		auto start = clock();

		writer_1(ms);

		auto elapsed = ((float)clock() - start) / CLOCKS_PER_SEC;
		std::cout << "1. insert : " << elapsed << std::endl;
	}

    dariadb::storage::BaseStorage_ptr ms{ new dariadb::storage::MemoryStorage{ 512 } };

	{// 2.
		const size_t threads_count = 16;
		const size_t id_per_thread = size_t(32768 / threads_count);

		auto start = clock();
		std::vector<std::thread> writers(threads_count);
		size_t pos = 0;
		for (size_t i = 0; i < threads_count; i++) {
			std::thread t{ writer_2, id_per_thread*i+1, id_per_thread, ms };
			writers[pos++] = std::move(t);
		}

		pos = 0;
		for (size_t i = 0; i < threads_count; i++) {
			std::thread t = std::move(writers[pos++]);
			t.join();
		}

		auto elapsed = ((float)clock() - start) / CLOCKS_PER_SEC;
		std::cout << "2. insert : " << elapsed << std::endl;
	}
	{//3
		std::random_device r;
		std::default_random_engine e1(r());
		std::uniform_int_distribution<dariadb::Id> uniform_dist(0, 32768);
		std::uniform_int_distribution<dariadb::Time> uniform_dist_t(0, 32768);
		dariadb::IdArray ids;
		ids.resize(1);

        const size_t queries_count = 32768;

        dariadb::IdArray rnd_ids(queries_count);
        std::vector<dariadb::Time> rnd_time(queries_count);
        for (size_t i = 0; i < queries_count; i++){
            rnd_ids[i]=uniform_dist(e1);
            rnd_time[i]=uniform_dist_t(e1);
        }
		dariadb::storage::ReaderClb_ptr clbk{ new BenchCallback() };

		auto start = clock();

		for (size_t i = 0; i < queries_count; i++) {
            ids[0]= rnd_ids[i];
            auto t = rnd_time[i];
			auto rdr=ms->readInTimePoint(ids,0,t);
			rdr->readAll(clbk.get());
		}

		auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC)/ queries_count;
		std::cout << "3. time point: " << elapsed << std::endl;
	}

	{//4
		std::random_device r;
		std::default_random_engine e1(r());
		std::uniform_int_distribution<dariadb::Id> uniform_dist(0, 32768);

        const size_t queries_count = 32;

		dariadb::IdArray ids;
        std::vector<dariadb::Time> rnd_time(queries_count);
        for (size_t i = 0; i < queries_count; i++){
            rnd_time[i]=uniform_dist(e1);
        }

		dariadb::storage::ReaderClb_ptr clbk{ new BenchCallback() };

		auto start = clock();

		for (size_t i = 0; i < queries_count; i++) {
            auto t = rnd_time[i];
			auto rdr=ms->readInTimePoint(ids, 0,t);
			rdr->readAll(clbk.get());
		}

		auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC) / queries_count;
		std::cout << "4. time point: " << elapsed << std::endl;
	}

	{//5
		std::random_device r;
		std::default_random_engine e1(r());
		std::uniform_int_distribution<dariadb::Time> uniform_dist(0, 32768/2);

		dariadb::storage::ReaderClb_ptr clbk{ new BenchCallback() };
		const size_t queries_count = 32;

        std::vector<dariadb::Time> rnd_time_from(queries_count),rnd_time_to(queries_count);
        for (size_t i = 0; i < queries_count; i++){
            rnd_time_from[i]=uniform_dist(e1);
            rnd_time_to[i]=uniform_dist(e1);
        }

		auto start = clock();

		for (size_t i = 0; i < queries_count; i++) {
            auto f = rnd_time_from[i];
            auto t = rnd_time_to[i];
			auto rdr = ms->readInterval(f, t+f);
			rdr->readAll(clbk.get());
		}

		auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC) / queries_count;
		std::cout << "5. interval: " << elapsed << std::endl;
	}

	{//6
		std::random_device r;
		std::default_random_engine e1(r());
		std::uniform_int_distribution<dariadb::Time> uniform_dist(0, 32768/2);
		std::uniform_int_distribution<dariadb::Id> uniform_dist_id(0, 32768);

		const size_t ids_count = size_t(32768 * 0.1);
		dariadb::IdArray ids;
		ids.resize(ids_count);

		dariadb::storage::ReaderClb_ptr clbk{ new BenchCallback() };
		const size_t queries_count = 32;

        std::vector<dariadb::Time> rnd_time_from(queries_count),rnd_time_to(queries_count);
        for (size_t i = 0; i < queries_count; i++){
            rnd_time_from[i]=uniform_dist(e1);
            rnd_time_to[i]=uniform_dist(e1);
        }

		auto start = clock();

		for (size_t i = 0; i < queries_count; i++) {
			for (size_t j = 0; j < ids_count; j++) {
				ids[j] = uniform_dist_id(e1);
			}
            auto f = rnd_time_from[i];
            auto t = rnd_time_to[i];
			auto rdr = ms->readInterval(ids,0, f, t + f);
			rdr->readAll(clbk.get());
		}

		auto elapsed = (((float)clock() - start) / CLOCKS_PER_SEC) / queries_count;
		std::cout << "6. interval: " << elapsed << std::endl;
	}
}
<|endoftext|>


<commit_before><commit_msg>PWGPP-485- bug fix in make histograms (#995)<commit_after><|endoftext|>