<commit_before>/*

Copyright (c) 2009-2013, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/allocator.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"

#if defined TORRENT_BEOS
#include <kernel/OS.h>
#include <stdlib.h> // malloc/free
#elif !defined TORRENT_WINDOWS
#include <stdlib.h> // valloc/free
#include <unistd.h> // _SC_PAGESIZE
#endif

#if TORRENT_USE_MEMALIGN || TORRENT_USE_POSIX_MEMALIGN || defined TORRENT_WINDOWS
#include <malloc.h> // memalign and _aligned_malloc
#include <stdlib.h> // _aligned_malloc on mingw
#endif

#ifdef TORRENT_WINDOWS
// windows.h must be included after stdlib.h under mingw
#include <windows.h>
#endif

#ifdef TORRENT_MINGW
#define _aligned_malloc __mingw_aligned_malloc
#define _aligned_free __mingw_aligned_free
#endif

#ifdef TORRENT_DEBUG_BUFFERS
#ifndef TORRENT_WINDOWS
#include <sys/mman.h>
#endif
#include "libtorrent/size_type.hpp"

struct alloc_header
{
	libtorrent::size_type size;
	int magic;
	char stack[3072];
};

#endif

namespace libtorrent
{

	int page_size()
	{
		static int s = 0;
		if (s != 0) return s;

#ifdef TORRENT_WINDOWS
		SYSTEM_INFO si;
		GetSystemInfo(&si);
		s = si.dwPageSize;
#elif defined TORRENT_BEOS
		s = B_PAGE_SIZE;
#else
		s = sysconf(_SC_PAGESIZE);
#endif
		// assume the page size is 4 kiB if we
		// fail to query it
		if (s <= 0) s = 4096;
		return s;
	}

	char* page_aligned_allocator::malloc(size_type bytes)
	{
		TORRENT_ASSERT(bytes >= page_size());
#ifdef TORRENT_DEBUG_BUFFERS
		int page = page_size();
		int num_pages = (bytes + (page-1)) / page + 2;
		char* ret = (char*)valloc(num_pages * page);
		// make the two surrounding pages non-readable and -writable
		alloc_header* h = (alloc_header*)ret;
		h->size = bytes;
		h->magic = 0x1337;
#if defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
		print_backtrace(h->stack, sizeof(h->stack));
#endif

#ifdef TORRENT_WINDOWS
#define mprotect(buf, size, prot) VirtualProtect(buf, size, prot, NULK)
#define PROT_READ PAGE_READONLY
#endif
		mprotect(ret, page, PROT_READ);
		mprotect(ret + (num_pages-1) * page, page, PROT_READ);

#ifdef TORRENT_WINDOWS
#undef mprotect
#undef PROT_READ
#endif
//		fprintf(stderr, "malloc: %p head: %p tail: %p size: %d\n", ret + page, ret, ret + page + bytes, int(bytes));

		return ret + page;
#endif

#if TORRENT_USE_POSIX_MEMALIGN
		void* ret;
		if (posix_memalign(&ret, page_size(), bytes) != 0) ret = 0;
		return (char*)ret;
#elif TORRENT_USE_MEMALIGN
		return (char*)memalign(page_size(), bytes);
#elif defined TORRENT_WINDOWS
		return (char*)_aligned_malloc(bytes, page_size());
#elif defined TORRENT_BEOS
		void* ret = 0;
		area_id id = create_area("", &ret, B_ANY_ADDRESS
			, (bytes + page_size() - 1) & (page_size()-1), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
		if (id < B_OK) return 0;
		return (char*)ret;
#else
		return (char*)valloc(bytes);
#endif
	}

	void page_aligned_allocator::free(char* const block)
	{

#ifdef TORRENT_DEBUG_BUFFERS

#ifdef TORRENT_WINDOWS
#define mprotect(buf, size, prot) VirtualProtect(buf, size, prot, NULK)
#define PROT_READ PAGE_READONLY
#define PROT_WRITE PAGE_READWRITE
#endif
		int page = page_size();
		// make the two surrounding pages non-readable and -writable
		mprotect(block - page, page, PROT_READ | PROT_WRITE);
		alloc_header* h = (alloc_header*)(block - page);
		int num_pages = (h->size + (page-1)) / page + 2;
		TORRENT_ASSERT(h->magic == 0x1337);
		mprotect(block + (num_pages-2) * page, page, PROT_READ | PROT_WRITE);
//		fprintf(stderr, "free: %p head: %p tail: %p size: %d\n", block, block - page, block + h->size, int(h->size));
		h->magic = 0;

#ifdef TORRENT_WINDOWS
#undef mprotect
#undef PROT_READ
#undef PROT_WRITE
#endif

#if defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
		print_backtrace(h->stack, sizeof(h->stack));
#endif
		::free(block - page);
		return;
#endif // TORRENT_DEBUG_BUFFERS

#ifdef TORRENT_WINDOWS
		_aligned_free(block);
#elif defined TORRENT_BEOS
		area_id id = area_for(block);
		if (id < B_OK) return;
		delete_area(id);
#else
		::free(block);
#endif // TORRENT_WINDOWS
	}

}

<commit_msg>fix build with allocator debugging<commit_after>/*

Copyright (c) 2009-2013, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/allocator.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"

#if defined TORRENT_BEOS
#include <kernel/OS.h>
#include <stdlib.h> // malloc/free
#elif !defined TORRENT_WINDOWS
#include <stdlib.h> // valloc/free
#include <unistd.h> // _SC_PAGESIZE
#endif

#if TORRENT_USE_MEMALIGN || TORRENT_USE_POSIX_MEMALIGN || defined TORRENT_WINDOWS
#include <malloc.h> // memalign and _aligned_malloc
#include <stdlib.h> // _aligned_malloc on mingw
#endif

#ifdef TORRENT_WINDOWS
// windows.h must be included after stdlib.h under mingw
#include <windows.h>
#endif

#ifdef TORRENT_MINGW
#define _aligned_malloc __mingw_aligned_malloc
#define _aligned_free __mingw_aligned_free
#endif

#ifdef TORRENT_DEBUG_BUFFERS
#ifndef TORRENT_WINDOWS
#include <sys/mman.h>
#endif
#include "libtorrent/size_type.hpp"

struct alloc_header
{
	libtorrent::size_type size;
	int magic;
	char stack[3072];
};

#endif

namespace libtorrent
{

	int page_size()
	{
		static int s = 0;
		if (s != 0) return s;

#ifdef TORRENT_WINDOWS
		SYSTEM_INFO si;
		GetSystemInfo(&si);
		s = si.dwPageSize;
#elif defined TORRENT_BEOS
		s = B_PAGE_SIZE;
#else
		s = sysconf(_SC_PAGESIZE);
#endif
		// assume the page size is 4 kiB if we
		// fail to query it
		if (s <= 0) s = 4096;
		return s;
	}

	char* page_aligned_allocator::malloc(size_type bytes)
	{
		TORRENT_ASSERT(bytes >= page_size());
#ifdef TORRENT_DEBUG_BUFFERS
		int page = page_size();
		int num_pages = (bytes + (page-1)) / page + 2;
		char* ret = (char*)valloc(num_pages * page);
		// make the two surrounding pages non-readable and -writable
		alloc_header* h = (alloc_header*)ret;
		h->size = bytes;
		h->magic = 0x1337;
#if defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
		print_backtrace(h->stack, sizeof(h->stack));
#endif

#ifdef TORRENT_WINDOWS
#define mprotect(buf, size, prot) VirtualProtect(buf, size, prot, NULK)
#define PROT_READ PAGE_READONLY
#endif
		mprotect(ret, page, PROT_READ);
		mprotect(ret + (num_pages-1) * page, page, PROT_READ);

#ifdef TORRENT_WINDOWS
#undef mprotect
#undef PROT_READ
#endif
//		fprintf(stderr, "malloc: %p head: %p tail: %p size: %d\n", ret + page, ret, ret + page + bytes, int(bytes));

		return ret + page;
#else

#if TORRENT_USE_POSIX_MEMALIGN
		void* ret;
		if (posix_memalign(&ret, page_size(), bytes) != 0) ret = 0;
		return (char*)ret;
#elif TORRENT_USE_MEMALIGN
		return (char*)memalign(page_size(), bytes);
#elif defined TORRENT_WINDOWS
		return (char*)_aligned_malloc(bytes, page_size());
#elif defined TORRENT_BEOS
		void* ret = 0;
		area_id id = create_area("", &ret, B_ANY_ADDRESS
			, (bytes + page_size() - 1) & (page_size()-1), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
		if (id < B_OK) return 0;
		return (char*)ret;
#else
		return (char*)valloc(bytes);
#endif
#endif // TORRENT_DEBUG_BUFFERS
	}

	void page_aligned_allocator::free(char* const block)
	{

#ifdef TORRENT_DEBUG_BUFFERS

#ifdef TORRENT_WINDOWS
#define mprotect(buf, size, prot) VirtualProtect(buf, size, prot, NULK)
#define PROT_READ PAGE_READONLY
#define PROT_WRITE PAGE_READWRITE
#endif
		int page = page_size();
		// make the two surrounding pages non-readable and -writable
		mprotect(block - page, page, PROT_READ | PROT_WRITE);
		alloc_header* h = (alloc_header*)(block - page);
		int num_pages = (h->size + (page-1)) / page + 2;
		TORRENT_ASSERT(h->magic == 0x1337);
		mprotect(block + (num_pages-2) * page, page, PROT_READ | PROT_WRITE);
//		fprintf(stderr, "free: %p head: %p tail: %p size: %d\n", block, block - page, block + h->size, int(h->size));
		h->magic = 0;

#ifdef TORRENT_WINDOWS
#undef mprotect
#undef PROT_READ
#undef PROT_WRITE
#endif

#if defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
		print_backtrace(h->stack, sizeof(h->stack));
#endif
		::free(block - page);
		return;
#endif // TORRENT_DEBUG_BUFFERS

#ifdef TORRENT_WINDOWS
		_aligned_free(block);
#elif defined TORRENT_BEOS
		area_id id = area_for(block);
		if (id < B_OK) return;
		delete_area(id);
#else
		::free(block);
#endif // TORRENT_WINDOWS
	}

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2016-2017 Rhys Ulerich
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef DESCENDU_TILE_HPP
#define DESCENDU_TILE_HPP

#include "consumable.hpp"
#include "optional.hpp"

namespace descendu {

struct tile
{
    std::experimental::optional<int> owner;
    consumable<int,99> height;
    consumable<int,16> walkers;
    consumable<int, 1> barracks;
    consumable<int, 1> cannon;
    consumable<int,99> ammo;
    consumable<int, 1> harvester;
};

template<class OutputStream>
OutputStream& operator<<(OutputStream& os, const tile& t)
{
    os << "(tile (owner";
    if (t.owner) {
        os << ' ' << t.owner.value();
    }
    os << ") (height "    << t.height
       << ") (walkers "   << t.walkers
       << ") (barracks "  << t.barracks
       << ") (cannon "    << t.cannon
       << ") (ammo "      << t.ammo
       << ") (harvester " << t.harvester
       << "))";
    return os;
}

} // namespace

#endif
<commit_msg>Add tile::operator ==<commit_after>/*
 * Copyright (C) 2016-2017 Rhys Ulerich
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef DESCENDU_TILE_HPP
#define DESCENDU_TILE_HPP

#include "consumable.hpp"
#include "optional.hpp"

namespace descendu {

struct tile
{
    std::experimental::optional<int> owner;
    consumable<int,99> height;
    consumable<int,16> walkers;
    consumable<int, 1> barracks;
    consumable<int, 1> cannon;
    consumable<int,99> ammo;
    consumable<int, 1> harvester;

    bool operator==(const tile& o) const {
        return owner     == o.owner
            && height    == o.height
            && walkers   == o.walkers
            && barracks  == o.barracks
            && cannon    == o.cannon
            && ammo      == o.ammo
            && harvester == o.harvester;
    }

    bool operator!=(const tile& o) const { return !(*this == o); }
};

template<class OutputStream>
OutputStream& operator<<(OutputStream& os, const tile& t)
{
    os << "(tile (owner";
    if (t.owner) {
        os << ' ' << t.owner.value();
    }
    os << ") (height "    << t.height
       << ") (walkers "   << t.walkers
       << ") (barracks "  << t.barracks
       << ") (cannon "    << t.cannon
       << ") (ammo "      << t.ammo
       << ") (harvester " << t.harvester
       << "))";
    return os;
}

} // namespace

#endif
<|endoftext|>


<commit_before>// $Id$
//
// Test Suite for geos::noding::SegmentPointComparator class.

#include <tut.hpp>
// geos
#include <geos/noding/SegmentNode.h>
#include <geos/noding/SegmentString.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/CoordinateSequence.h>
#include <geos/geom/CoordinateArraySequenceFactory.h>
// std
#include <memory>

namespace tut
{
    //
    // Test Group
    //

    // Common data used by tests
    struct test_segmentpointcomparator_data
    {

    	typedef std::auto_ptr<geos::geom::CoordinateSequence>
            CoordinateSequenceAutoPtr;

    	typedef std::auto_ptr<geos::noding::SegmentString>
            SegmentStringAutoPtr;

        const geos::geom::CoordinateSequenceFactory* csFactory;

        test_segmentpointcomparator_data()
            : csFactory(geos::geom::CoordinateArraySequenceFactory::instance())
	    {}
    };

    typedef test_group<test_segmentpointcomparator_data> group;
    typedef group::object object;

    group test_segmentpointcomparator_group("geos::noding::SegmentPointComparator");

    //
    // Test Cases
    //

    // TODO
    template<>
    template<>
    void object::test<1>()
    {

        // TODO - mloskot add test cases

    }

} // namespace tut
<commit_msg>Port JTS unit tests for SegmentPointComparator<commit_after>// $Id$
//
// Test Suite for geos::noding::SegmentPointComparator class.
//
// Ports tests found in jts/junit/noding/SegmentPointComparatorTest.java
// and jts/junit/noding/SegmentPointComparatorFullTest.java

#include <tut.hpp>
// geos
#include <geos/noding/SegmentNode.h>
#include <geos/noding/SegmentPointComparator.h>
#include <geos/noding/SegmentString.h>
#include <geos/noding/Octant.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/LineSegment.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/CoordinateSequence.h>
#include <geos/geom/CoordinateArraySequenceFactory.h>
// std
#include <memory>

namespace tut
{
    //
    // Test Group
    //

    // Common data used by tests
    struct test_segmentpointcomparator_data
    {

        typedef std::auto_ptr<geos::geom::CoordinateSequence>
            CoordinateSequenceAutoPtr;

        typedef std::auto_ptr<geos::noding::SegmentString>
            SegmentStringAutoPtr;

        typedef geos::geom::Coordinate Coordinate;
        typedef geos::geom::LineSegment LineSegment;
        typedef geos::geom::PrecisionModel PrecisionModel;

        PrecisionModel pm;

        test_segmentpointcomparator_data()
            : pm(1.0)
        {}

        void checkNodePosition(int octant, double x0, double y0,
                               double x1, double y1, int
                               expectedPositionValue)
        {
            using geos::noding::SegmentPointComparator;

            int posValue = SegmentPointComparator::compare(octant,
                Coordinate(x0, y0),
                Coordinate(x1, y1)
              );
            ensure( posValue == expectedPositionValue );
        }

        void checkNodePosition(const LineSegment& seg, const Coordinate& p0,
                               const Coordinate& p1, int expectedPositionValue)
        {
            using geos::noding::Octant;
            using geos::noding::SegmentPointComparator;

            int octant = Octant::octant(seg.p0, seg.p1);
            int posValue = SegmentPointComparator::compare(octant, p0, p1);

            ensure( posValue == expectedPositionValue );
        }

        Coordinate computePoint(const LineSegment& seg, double dist)
        {
          double dx = seg.p1.x - seg.p0.x;
          double dy = seg.p1.y - seg.p0.y;
          double len = seg.getLength();
          Coordinate pt(dist * dx / len, dist * dy / len);
          pm.makePrecise(pt);
          return pt;
        }

        void checkPointsAtDistance(const LineSegment& seg,
                                   double dist0, double dist1)
        {
          using geos::geom::Coordinate;
          Coordinate p0 = computePoint(seg, dist0);
          Coordinate p1 = computePoint(seg, dist1);
          if (p0.equals(p1)) {
            checkNodePosition(seg, p0, p1, 0);
          }
          else {
            checkNodePosition(seg, p0, p1, -1);
            checkNodePosition(seg, p1, p0, 1);
          }
        }

        void checkSegment(double x, double y)
        {
          Coordinate seg0(0, 0);
          Coordinate seg1(x, y);
          LineSegment seg(seg0, seg1);

          for (int i = 0; i < 4; i++) {
            double dist = i;

            double gridSize = 1 / pm.getScale();

            checkPointsAtDistance(seg, dist, dist + 1.0 * gridSize);
            checkPointsAtDistance(seg, dist, dist + 2.0 * gridSize);
            checkPointsAtDistance(seg, dist, dist + 3.0 * gridSize);
            checkPointsAtDistance(seg, dist, dist + 4.0 * gridSize);
          }
        }

    };

    typedef test_group<test_segmentpointcomparator_data> group;
    typedef group::object object;

    group test_segmentpointcomparator_group("geos::noding::SegmentPointComparator");

    //
    // Test Cases
    //

    // testOctant0 (from simple unit test)
    template<>
    template<>
    void object::test<1>()
    {
        checkNodePosition(0, 1, 1, 2, 2, -1);
        checkNodePosition(0, 1, 0, 1, 1, -1);
    }

    // testQuadrant0
    template<>
    template<>
    void object::test<2>()
    {
        checkSegment(100, 0);
        checkSegment(100, 50);
        checkSegment(100, 100);
        checkSegment(100, 150);
        checkSegment(0, 100);
    }

    // testQuadrant4
    template<>
    template<>
    void object::test<3>()
    {
      checkSegment(100, -50);
      checkSegment(100, -100);
      checkSegment(100, -150);
      checkSegment(0, -100);
    }

    // testQuadrant1
    template<>
    template<>
    void object::test<4>()
    {
      checkSegment(-100, 0);
      checkSegment(-100, 50);
      checkSegment(-100, 100);
      checkSegment(-100, 150);
    }

    // testQuadrant2
    template<>
    template<>
    void object::test<5>()
    {
      checkSegment(-100, 0);
      checkSegment(-100, -50);
      checkSegment(-100, -100);
      checkSegment(-100, -150);
    }

} // namespace tut
<|endoftext|>


<commit_before>#include <cstdio>

#include "blifparse.hpp"

#include "blif_common.hpp"
#include "blif_lexer.hpp"
#include "blif_error.hpp"

namespace blifparse {

//.conn [Extended BLIF]
void Callback::conn(std::string src, std::string /*dst*/) {
    parse_error(-1, src, "Unsupported BLIF extension '.conn'");
}

//.cname [Extended BLIF]
void Callback::cname(std::string cell_name) {
    parse_error(-1, cell_name, "Unsupported BLIF extension '.cname'");
}

//.attr [Extended BLIF]
void Callback::attr(std::string name, std::string /*value*/) {
    parse_error(-1, name, "Unsupported BLIF extension '.attr'");
}

//.param [Extended BLIF]
void Callback::param(std::string name, std::string /*value*/) {
    parse_error(-1, name, "Unsupported BLIF extension '.param'");
}

/*
 * Given a filename parses the file as an BLIF file
 * and returns a pointer to a struct containing all
 * the blif commands.  See blif.h for data structure
 * detials.
 */
void blif_parse_filename(std::string filename, Callback& callback) {
    blif_parse_filename(filename.c_str(), callback);
}

void blif_parse_filename(const char* filename, Callback& callback) {
    FILE* infile = std::fopen(filename, "r");
    if(infile != NULL) {
        //Parse the file
        blif_parse_file(infile, callback, filename);

        std::fclose(infile);
    } else {
        blif_error_wrap(callback, 0, "", "Could not open file '%s'.\n", filename);
    }
}

void blif_parse_file(FILE* blif_file, Callback& callback, const char* filename) {

    //Initialize the lexer
    Lexer lexer(blif_file, callback);

    //Setup the parser + lexer
    Parser parser(lexer, callback);

    //Just before parsing starts
    callback.start_parse();

    //Tell the caller the file name
    callback.filename(filename);

    //Do the actual parse
    int error = parser.parse();
    if(error) {
        blif_error_wrap(callback, 0, "", "File failed to parse.\n");
    }

    //Finished parsing
    callback.finish_parse();
}

}
<commit_msg>Improve default error message for blif extensions<commit_after>#include <cstdio>

#include "blifparse.hpp"

#include "blif_common.hpp"
#include "blif_lexer.hpp"
#include "blif_error.hpp"

namespace blifparse {

//.conn [Extended BLIF]
void Callback::conn(std::string /*src*/, std::string /*dst*/) {
    parse_error(-1, ".conn", "Unsupported BLIF extension");
}

//.cname [Extended BLIF]
void Callback::cname(std::string /*cell_name*/) {
    parse_error(-1, ".cname", "Unsupported BLIF extension");
}

//.attr [Extended BLIF]
void Callback::attr(std::string /*name*/, std::string /*value*/) {
    parse_error(-1, ".attr", "Unsupported BLIF extension");
}

//.param [Extended BLIF]
void Callback::param(std::string /*name*/, std::string /*value*/) {
    parse_error(-1, ".param", "Unsupported BLIF extension");
}

/*
 * Given a filename parses the file as an BLIF file
 * and returns a pointer to a struct containing all
 * the blif commands.  See blif.h for data structure
 * detials.
 */
void blif_parse_filename(std::string filename, Callback& callback) {
    blif_parse_filename(filename.c_str(), callback);
}

void blif_parse_filename(const char* filename, Callback& callback) {
    FILE* infile = std::fopen(filename, "r");
    if(infile != NULL) {
        //Parse the file
        blif_parse_file(infile, callback, filename);

        std::fclose(infile);
    } else {
        blif_error_wrap(callback, 0, "", "Could not open file '%s'.\n", filename);
    }
}

void blif_parse_file(FILE* blif_file, Callback& callback, const char* filename) {

    //Initialize the lexer
    Lexer lexer(blif_file, callback);

    //Setup the parser + lexer
    Parser parser(lexer, callback);

    //Just before parsing starts
    callback.start_parse();

    //Tell the caller the file name
    callback.filename(filename);

    //Do the actual parse
    int error = parser.parse();
    if(error) {
        blif_error_wrap(callback, 0, "", "File failed to parse.\n");
    }

    //Finished parsing
    callback.finish_parse();
}

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <ctime>
#include <cmath>
#include <string>
using std::string;

#ifndef TIMER_HPP
#define TIMER_HPP

namespace isa {
namespace utils {

class Timer {
public:
		Timer(string name);

	void start();
	void stop();
	void reset();

	inline double getTotalTime() const;
	inline double getLastRunTime() const;
	inline double getAverageTime() const;
	inline double getStdDev() const;

private:
	string name;
	struct timespec starting;
	struct timespec resolution;
	unsigned int nrRuns;
	double totalTime;
	double time;
	double average;
	double variance;
};

// Implementation

Timer::Timer(string name) : name(name), nrRuns(0), totalTime(0.0), time(0.0), average(0.0), variance(0.0) {
	clock_gettime(CLOCK_MONOTONIC, &starting);
	clock_getres(CLOCK_MONOTONIC, &resolution);
}

void Timer::start() {
	clock_gettime(CLOCK_MONOTONIC, &starting);
}

void Timer::stop() {
	struct timespec ending;

	clock_gettime(CLOCK_MONOTONIC, &ending);
	time = static_cast< double >(ending.tv_nsec - starting.tv_nsec) / resolution.tv_nsec;
	totalTime += time;
	nrRuns++;

	if ( nrRuns == 1 ) {
		average = time;
		variance = 0.0;
	} else {
		double oldAverage = average;

		average = oldAverage + ((time - oldAverage) / nrRuns);
		variance += ((time - oldAverage) * (time - average));
	}
}

void Timer::reset() {
	clock_gettime(CLOCK_MONOTONIC, &starting);
	nrRuns = 0;
	totalTime = 0.0;
	time = 0.0;
	average = 0.0;
	variance = 0.0;
}

inline double Timer::getTotalTime() const {
	return totalTime;
}

inline double Timer::getLastRunTime() const {
	return time;
}

inline double Timer::getAverageTime() const {
	return average;
}

inline double Timer::getStdDev() const {
	return sqrt(variance / nrRuns);
}

} // utils
} // isa

#endif // TIMER_HPP

<commit_msg>Revert "Fixing the errors for my first attempt at using C++11."<commit_after>/*
 * Copyright (C) 2013
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <ctime>
#include <cmath>
#include <string>
#include <chrono>
using std::string;
using std::chrono::duration_cast;
using std::chrono::duration;
using std::chrono::high_resolution_clock::time_point;
using std::chrono::high_resolution_time::now;

#ifndef TIMER_HPP
#define TIMER_HPP

namespace isa {
namespace utils {

class Timer {
public:
	Timer(string name);

	void start();
	void stop();
	void reset();

	inline double getTotalTime() const;
	inline double getLastRunTime() const;
	inline double getAverageTime() const;
	inline double getStdDev() const;

private:
	string name;
	time_point starting;
	unsigned int nrRuns;
	double totalTime;
	double time;
	double average;
	double variance;
};

// Implementation

Timer::Timer(string name) : name(name), starting(time_point()), nrRuns(0), totalTime(0.0), time(0.0), average(0.0), variance(0.0) {}

void Timer::start() {
	starting = now();
}

void Timer::stop() {
	time = (duration_cast< duration< double > >(now() - starting)).count();
	totalTime += time;
	nrRuns++;
	starting = 0;

	if ( nrRuns == 1 ) {
		average = time;
		variance = 0.0;
	} else {
		double oldAverage = average;

		average = oldAverage + ((time - oldAverage) / nrRuns);
		variance += ((time - oldAverage) * (time - average));
	}
}

void Timer::reset() {
	starting = 0;
	nrRuns = 0;
	totalTime = 0.0;
	time = 0.0;
	average = 0.0;
	variance = 0.0;
}

inline double Timer::getTotalTime() const {
	return totalTime;
}

inline double Timer::getLastRunTime() const {
	return time;
}

inline double Timer::getAverageTime() const {
	return average;
}

inline double Timer::getStdDev() const {
	return sqrt(variance / nrRuns);
}

} // utils
} // isa

#endif // TIMER_HPP

<|endoftext|>


<commit_before>#pragma once
#include "common.hpp"
#include <Prelude/FastList.hpp>
#include <Prelude/LinkedList.hpp>
#include <Prelude/Allocator.hpp>
#include "value.hpp"
#include "value-map.hpp"
#include "char-array.hpp"
#include "classes/object.hpp"
#include "allocator.hpp"

namespace Mirb
{
	class FreeBlock:
		public Value::Header
	{
		public:
			void *next;

			template<typename F> void mark(F) {}
	};

	class Collector
	{
		private:
			prelude_align(struct, Region, mirb_object_align)
			{
				ListEntry<Region> entry;
				char_t *pos;
				char_t *end;

				value_t data()
				{
					return (value_t)((size_t)this + sizeof(Region));
				}

				bool area_contains(value_t obj)
				{
					return ((size_t)obj >= (size_t)data()) && ((size_t)obj <= (size_t)end);
				}

				bool contains(value_t obj)
				{
					return ((size_t)obj >= (size_t)data()) && ((size_t)obj <= (size_t)pos);
				}
			};

			static bool pending;

			static void sweep();
			static void compact();
			static void mark();
			static void naive_mark();

			static void update_forward();
			static void update_backward();

			friend struct MarkRootFunc;
			friend struct ThreadFunc;

			static List<Region> regions;
			static const size_t page_size = 0x1000;

			friend struct RegionWalker;
			template<bool backward> friend struct RegionAllocator;

			template<typename F> friend void each_root(F mark);

			static Region *current;
			static size_t pages;

			#ifdef VALGRIND
				static LinkedList<Value::Header> heap_list;
			#else
				static LinkedList<PinnedHeader, PinnedHeader, &PinnedHeader::entry> heap_list;
			#endif

			void test_sizes();

			static Region *allocate_region(size_t bytes);
			static void free_region(Region *region);
			static void *get_region(size_t bytes);

			template<class T> static void *allocate_object()
			{
				return allocate_simple(sizeof(T));
			}

			template<class T> static T *setup_object(T *object)
			{
				static_assert(std::is_base_of<Value::Header, T>::value, "T must be a Value::Header");

				#ifdef DEBUG
					object->size = sizeof(T);
				#endif

				return object;
			}

			friend class Class;
			friend class Value::Header;

			template<class T> static void *allocate_pinned_object()
			{
				return std::malloc(sizeof(T));
			}

			template<class T> static T *setup_pinned_object(T *object)
			{
				static_assert(std::is_base_of<PinnedHeader, T>::value, "T must be a PinnedHeader");

				#ifdef DEBUG
					object->size = sizeof(T);
				#endif

				heap_list.append(object);

				return object;
			}
		public:
			static size_t collections;
			static size_t region_count;
			static size_t region_free_count;
			static unsigned long long memory;
			static bool enable_interrupts;

			/*
				signal is callable from other threads
			*/
			static void signal();

			static bool collect();
			static void initialize();
			static void free();

			static bool check()
			{
				mirb_debug(collect());

				if(prelude_unlikely(pending))
				{
					pending = false;
					return collect();
				}
				else
					return false;
			}

			static void *allocate_simple(size_t bytes)
			{
				mirb_debug_assert((bytes & object_ref_mask) == 0);

				memory += bytes;

				char_t *result;

				#ifdef VALGRIND
					result = (char_t *)std::malloc(bytes);

					mirb_runtime_assert(result != 0);
				#else
					result = current->pos;

					char_t *next = result + bytes;

					mirb_debug_assert(((size_t)next & object_ref_mask) == 0);

					if(prelude_unlikely(next > current->end))
						return get_region(bytes);

					current->pos = next;
				#endif

				mirb_debug_assert(((size_t)result & object_ref_mask) == 0);

				return (void *)result;
			}

			static void *allocate(size_t bytes);
			static void *reallocate(void *memory, size_t old_size, size_t bytes);

			template<class T> static Tuple<T> &allocate_tuple(size_t entries)
			{
				size_t size = sizeof(Tuple<T>) + entries * sizeof(T *);

				auto tuple = new (allocate_simple(size)) Tuple<T>(entries);

				#ifdef DEBUG
					tuple->size = size;
				#endif

				#ifdef VALGRIND
					heap_list.append(tuple);
				#endif

				return *tuple;
			}

			template<class T> static T *allocate_pinned()
			{
				return setup_pinned_object<T>(new (allocate_pinned_object<T>()) T());
			}

			template<class T, typename Arg1> static T *allocate_pinned(Arg1&& arg1)
			{
				return setup_pinned_object<T>(new (allocate_pinned_object<T>()) T(std::forward<Arg1>(arg1)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> static T *allocate_pinned(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4)
			{
				return setup_pinned_object<T>(new (allocate_pinned_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4)));
			}

			template<class T> static T *allocate()
			{
				return setup_object<T>(new (allocate_object<T>()) T());
			}

			template<class T, typename Arg1> static T *allocate(Arg1&& arg1)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1)));
			}

			template<class T, typename Arg1, typename Arg2> static T *allocate(Arg1&& arg1, Arg2&& arg2)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2)));
			}

			template<class T,  typename Arg1, typename Arg2, typename Arg3> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5, Arg6&& arg6)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5), std::forward<Arg6>(arg6)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5, Arg6&& arg6, Arg7&& arg7)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), std::forward<Arg7>(arg7)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7, typename Arg8> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5, Arg6&& arg6, Arg7&& arg7, Arg8&& arg8)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), std::forward<Arg7>(arg7), std::forward<Arg8>(arg8)));
			}
	};
};
<commit_msg>Don't run the GC every Ruby call.<commit_after>#pragma once
#include "common.hpp"
#include <Prelude/FastList.hpp>
#include <Prelude/LinkedList.hpp>
#include <Prelude/Allocator.hpp>
#include "value.hpp"
#include "value-map.hpp"
#include "char-array.hpp"
#include "classes/object.hpp"
#include "allocator.hpp"

namespace Mirb
{
	class FreeBlock:
		public Value::Header
	{
		public:
			void *next;

			template<typename F> void mark(F) {}
	};

	class Collector
	{
		private:
			prelude_align(struct, Region, mirb_object_align)
			{
				ListEntry<Region> entry;
				char_t *pos;
				char_t *end;

				value_t data()
				{
					return (value_t)((size_t)this + sizeof(Region));
				}

				bool area_contains(value_t obj)
				{
					return ((size_t)obj >= (size_t)data()) && ((size_t)obj <= (size_t)end);
				}

				bool contains(value_t obj)
				{
					return ((size_t)obj >= (size_t)data()) && ((size_t)obj <= (size_t)pos);
				}
			};

			static bool pending;

			static void sweep();
			static void compact();
			static void mark();
			static void naive_mark();

			static void update_forward();
			static void update_backward();

			friend struct MarkRootFunc;
			friend struct ThreadFunc;

			static List<Region> regions;
			static const size_t page_size = 0x1000;

			friend struct RegionWalker;
			template<bool backward> friend struct RegionAllocator;

			template<typename F> friend void each_root(F mark);

			static Region *current;
			static size_t pages;

			#ifdef VALGRIND
				static LinkedList<Value::Header> heap_list;
			#else
				static LinkedList<PinnedHeader, PinnedHeader, &PinnedHeader::entry> heap_list;
			#endif

			void test_sizes();

			static Region *allocate_region(size_t bytes);
			static void free_region(Region *region);
			static void *get_region(size_t bytes);

			template<class T> static void *allocate_object()
			{
				return allocate_simple(sizeof(T));
			}

			template<class T> static T *setup_object(T *object)
			{
				static_assert(std::is_base_of<Value::Header, T>::value, "T must be a Value::Header");

				#ifdef DEBUG
					object->size = sizeof(T);
				#endif

				return object;
			}

			friend class Class;
			friend class Value::Header;

			template<class T> static void *allocate_pinned_object()
			{
				return std::malloc(sizeof(T));
			}

			template<class T> static T *setup_pinned_object(T *object)
			{
				static_assert(std::is_base_of<PinnedHeader, T>::value, "T must be a PinnedHeader");

				#ifdef DEBUG
					object->size = sizeof(T);
				#endif

				heap_list.append(object);

				return object;
			}
		public:
			static size_t collections;
			static size_t region_count;
			static size_t region_free_count;
			static unsigned long long memory;
			static bool enable_interrupts;

			/*
				signal is callable from other threads
			*/
			static void signal();

			static bool collect();
			static void initialize();
			static void free();

			static bool check()
			{
#ifdef DEBUG_MEMORY
				collect();
#endif

				if(prelude_unlikely(pending))
				{
					pending = false;
					return collect();
				}
				else
					return false;
			}

			static void *allocate_simple(size_t bytes)
			{
				mirb_debug_assert((bytes & object_ref_mask) == 0);

				memory += bytes;

				char_t *result;

				#ifdef VALGRIND
					result = (char_t *)std::malloc(bytes);

					mirb_runtime_assert(result != 0);
				#else
					result = current->pos;

					char_t *next = result + bytes;

					mirb_debug_assert(((size_t)next & object_ref_mask) == 0);

					if(prelude_unlikely(next > current->end))
						return get_region(bytes);

					current->pos = next;
				#endif

				mirb_debug_assert(((size_t)result & object_ref_mask) == 0);

				return (void *)result;
			}

			static void *allocate(size_t bytes);
			static void *reallocate(void *memory, size_t old_size, size_t bytes);

			template<class T> static Tuple<T> &allocate_tuple(size_t entries)
			{
				size_t size = sizeof(Tuple<T>) + entries * sizeof(T *);

				auto tuple = new (allocate_simple(size)) Tuple<T>(entries);

				#ifdef DEBUG
					tuple->size = size;
				#endif

				#ifdef VALGRIND
					heap_list.append(tuple);
				#endif

				return *tuple;
			}

			template<class T> static T *allocate_pinned()
			{
				return setup_pinned_object<T>(new (allocate_pinned_object<T>()) T());
			}

			template<class T, typename Arg1> static T *allocate_pinned(Arg1&& arg1)
			{
				return setup_pinned_object<T>(new (allocate_pinned_object<T>()) T(std::forward<Arg1>(arg1)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> static T *allocate_pinned(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4)
			{
				return setup_pinned_object<T>(new (allocate_pinned_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4)));
			}

			template<class T> static T *allocate()
			{
				return setup_object<T>(new (allocate_object<T>()) T());
			}

			template<class T, typename Arg1> static T *allocate(Arg1&& arg1)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1)));
			}

			template<class T, typename Arg1, typename Arg2> static T *allocate(Arg1&& arg1, Arg2&& arg2)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2)));
			}

			template<class T,  typename Arg1, typename Arg2, typename Arg3> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5, Arg6&& arg6)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5), std::forward<Arg6>(arg6)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5, Arg6&& arg6, Arg7&& arg7)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), std::forward<Arg7>(arg7)));
			}

			template<class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7, typename Arg8> static T *allocate(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5, Arg6&& arg6, Arg7&& arg7, Arg8&& arg8)
			{
				return setup_object<T>(new (allocate_object<T>()) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), std::forward<Arg7>(arg7), std::forward<Arg8>(arg8)));
			}
	};
};
<|endoftext|>


<commit_before>///
/// @file  pmath.hpp
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PMATH_HPP
#define PMATH_HPP

#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <vector>

namespace primecount {

inline int64_t isquare(int32_t x)
{
  return x * (int64_t) x;
}

template <typename T>
inline T max3(T a, T b, T c)
{
  return std::max(std::max(a, b), c);
}

/// Convenience min function for different types.
template <typename A, typename B>
inline B min(A a, B b)
{
  return (a < b) ? (B) a : b;
}

template <typename A, typename B>
inline A ceil_div(A a, B b)
{
  assert(b > 0);
  return (A) ((a + b - 1) / b);
}

template <typename T>
inline T number_of_bits(T)
{
  return (T) (sizeof(T) * 8);
}

/// @brief  Check if an integer is a power of 2.
/// @see    Book "Hacker's Delight".
///
template <typename T>
inline bool is_power_of_2(T x)
{
  return (x != 0 && (x & (x - 1)) == 0);
}

/// @brief  Round up to the next power of 2.
/// @see    Book "Hacker's Delight".
///
template <typename T>
inline T next_power_of_2(T x)
{
  if (x == 0)
    return 1;

  x--;
  for (T i = 1; i < number_of_bits(x); i += i)
    x |= (x >> i);

  return ++x;
}

template <typename T>
inline int ilog(T x)
{
  return (int) std::log((double) x);
}

/// Raise to power
template <typename T>
inline T ipow(T x, int n)
{
  T r = 1;
  for (int i = 0; i < n; i++)
    r *= x;

  return r;
}

/// Integer suare root
template <typename T>
inline T isqrt(T x)
{
  T r = (T) std::sqrt((double) x);
  while (r * r > x)
    r--;
  while (x - r * r > r * 2)
    r++;
  return r;
}

/// Check if ipow(x, n) <= limit
template <typename T>
inline bool ipow_less_equal(T x, int n, T limit)
{
  if (limit <= 0)
    return false;

  for (T r = 1; n > 0; n--, r *= x)
    if (r > limit / x)
      return false;

  return true;
}

/// Integer nth root
template <int N, typename T>
inline T iroot(T x)
{
  T r = (T) std::pow((double) x, 1.0 / N);
  while (ipow(r, N) > x)
    r--;
  while (ipow_less_equal(r + 1, N, x))
    r++;
  return r;
}

/// Calculate the number of primes below x using binary search.
/// @pre primes[1] = 2, primes[3] = 3, ...
/// @pre x <= primes.back()
///
template <typename T1, typename T2>
inline T2 pi_bsearch(const std::vector<T1>& primes, T2 x)
{
  // primecount uses 1-indexing
  assert(primes[0] == 0);
  return (T2) (std::upper_bound(primes.begin() + 1, primes.end(), x)
      - (primes.begin() + 1));
}

/// Calculate the number of primes below x using binary search.
/// @pre primes[1] = 2, primes[3] = 3, ...
/// @pre x <= primes.back()
///
template <typename T1, typename T2, typename T3>
inline T3 pi_bsearch(const std::vector<T1>& primes, T2 len, T3 x)
{
  // primecount uses 1-indexing
  assert(primes[0] == 0);
  return (T3) (std::upper_bound(primes.begin() + 1, primes.begin() + len + 1, x)
      - (primes.begin() + 1));
}

template <typename T1, typename T2, typename T3>
inline T2 in_between(T1 min, T2 x, T3 max)
{
  if (x < min)
    return (T2) min;
  if (x > max)
    return (T2) max;

  return x;
}

} // namespace

#endif
<commit_msg>Fix overflow bug in isqrt(x)<commit_after>///
/// @file  pmath.hpp
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PMATH_HPP
#define PMATH_HPP

#include <stdint.h>
#include <algorithm>
#include <limits>
#include <cassert>
#include <cmath>
#include <vector>

namespace primecount {

inline int64_t isquare(int32_t x)
{
  return x * (int64_t) x;
}

template <typename T>
inline T max3(T a, T b, T c)
{
  return std::max(std::max(a, b), c);
}

/// Convenience min function for different types.
template <typename A, typename B>
inline B min(A a, B b)
{
  return (a < b) ? (B) a : b;
}

template <typename A, typename B>
inline A ceil_div(A a, B b)
{
  assert(b > 0);
  return (A) ((a + b - 1) / b);
}

template <typename T>
inline T number_of_bits(T)
{
  return (T) (sizeof(T) * 8);
}

/// @brief  Check if an integer is a power of 2.
/// @see    Book "Hacker's Delight".
///
template <typename T>
inline bool is_power_of_2(T x)
{
  return (x != 0 && (x & (x - 1)) == 0);
}

/// @brief  Round up to the next power of 2.
/// @see    Book "Hacker's Delight".
///
template <typename T>
inline T next_power_of_2(T x)
{
  if (x == 0)
    return 1;

  x--;
  for (T i = 1; i < number_of_bits(x); i += i)
    x |= (x >> i);

  return ++x;
}

template <typename T>
inline int ilog(T x)
{
  return (int) std::log((double) x);
}

/// Raise to power
template <typename T>
inline T ipow(T x, int n)
{
  T r = 1;
  for (int i = 0; i < n; i++)
    r *= x;

  return r;
}

/// Integer suare root
template <typename T>
inline T isqrt(T x)
{
  T r = (T) std::sqrt((double) x);
  T max_r = std::numeric_limits<T>::max() >> (sizeof(T) / 2);
  r = std::min(r, max_r);
  while (r * r > x)
    r--;
  while (x - r * r > r * 2)
    r++;
  return r;
}

/// Check if ipow(x, n) <= limit
template <typename T>
inline bool ipow_less_equal(T x, int n, T limit)
{
  if (limit <= 0)
    return false;

  for (T r = 1; n > 0; n--, r *= x)
    if (r > limit / x)
      return false;

  return true;
}

/// Integer nth root
template <int N, typename T>
inline T iroot(T x)
{
  T r = (T) std::pow((double) x, 1.0 / N);
  while (ipow(r, N) > x)
    r--;
  while (ipow_less_equal(r + 1, N, x))
    r++;
  return r;
}

/// Calculate the number of primes below x using binary search.
/// @pre primes[1] = 2, primes[3] = 3, ...
/// @pre x <= primes.back()
///
template <typename T1, typename T2>
inline T2 pi_bsearch(const std::vector<T1>& primes, T2 x)
{
  // primecount uses 1-indexing
  assert(primes[0] == 0);
  return (T2) (std::upper_bound(primes.begin() + 1, primes.end(), x)
      - (primes.begin() + 1));
}

/// Calculate the number of primes below x using binary search.
/// @pre primes[1] = 2, primes[3] = 3, ...
/// @pre x <= primes.back()
///
template <typename T1, typename T2, typename T3>
inline T3 pi_bsearch(const std::vector<T1>& primes, T2 len, T3 x)
{
  // primecount uses 1-indexing
  assert(primes[0] == 0);
  return (T3) (std::upper_bound(primes.begin() + 1, primes.begin() + len + 1, x)
      - (primes.begin() + 1));
}

template <typename T1, typename T2, typename T3>
inline T2 in_between(T1 min, T2 x, T3 max)
{
  if (x < min)
    return (T2) min;
  if (x > max)
    return (T2) max;

  return x;
}

} // namespace

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <new>
#include <stdexcept>
#include <vector>
#include <memory>
#include <mutex>
#include <thread>

class bitset
{
public:
explicit
bitset( size_t size ) /*strong*/;

bitset( bitset const & other ) = delete;
auto operator =( bitset const & other ) -> bitset & = delete;

bitset( bitset && other ) = delete;
auto operator =( bitset && other ) -> bitset & = delete;

auto set( size_t index ) /*strong*/ -> void;
auto reset( size_t index ) throw(std::out_of_range)/*strong*/ -> void;
auto test( size_t index ) const throw(std::out_of_range)/*strong*/ -> bool;

auto size() const /*noexcept*/ -> size_t;
auto counter() const /*noexcept*/ -> size_t;

private:
std::unique_ptr<bool[]> ptr_;
size_t size_;
size_t counter_;
};
bitset::bitset(size_t size) : ptr_(std::make_unique<bool[]>(size)),size_(size),counter_(0)
{}

auto bitset::set(size_t index)->void //инициализация всех битов единицами или изменение значения отдельного бита
{
	if (index >= 0 && index < size_)
	{
		ptr_[index] = true; ++counter_;
	}
	else throw("problem with index");
}

auto bitset::reset(size_t index) throw(std::out_of_range) -> void //обнуление указанных битов
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	ptr_[index] = false;
	--counter_;
}

auto bitset::test(size_t index) const throw(std::out_of_range) -> bool //возвращает значение указанного бита
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	return ptr_[index];
}

auto bitset::size() const -> size_t
{
	return size_;
}
auto bitset::counter() const -> size_t
{
	return counter_;
}

template <typename T>
class allocator
{
public:
explicit
allocator( std::size_t size = 0 ) /*strong*/;
allocator( allocator const & other ) /*strong*/;
auto operator =( allocator const & other ) -> allocator & = delete;
~allocator();

auto resize() /*strong*/ -> void;

auto construct(T * ptr, T const & value ) /*strong*/ -> void;
auto destroy( T * ptr ) /*noexcept*/ -> void;

auto get() /*noexcept*/ -> T *;
auto get() const /*noexcept*/ -> T const *;

auto count() const /*noexcept*/ -> size_t;
auto full() const /*noexcept*/ -> bool;
auto empty() const /*noexcept*/ -> bool;
private:
auto destroy( T * first, T * last ) /*noexcept*/ -> void;
auto swap( allocator & other ) /*noexcept*/ -> void;

private:
size_t count_;
T * ptr_;
size_t size_;
std::unique_ptr<bitset> map_;
};
template<typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)operator new(size*sizeof(T))), size_(size), map_(std::make_unique<bitset>(size))//конструктор с параметром
{}

template<typename T>
allocator<T>::allocator(allocator const& other) : allocator<T>(other.size_) //конструктор копирования
{
	for (size_t i=0; i < size_; i++)
	{
		if (map_->test(i))
		{
			destroy(ptr_, ptr_ +i);
		}
	construct(ptr_ + i, other.ptr_[i]);
}}

template<typename T>
allocator<T>::~allocator()
{
	if (this->count() > 0)
	{
		destroy(ptr_, ptr_ + size_);
	}
	operator delete(ptr_);
}

template<typename T> //увеличение памяти
auto allocator<T>::resize()->void
{
	allocator<T> alloc(size_ * 2 + (size_ == 0));
	for (size_t i = 0; i < size_; ++i) if(map_->test(i)) alloc.construct(alloc.get() + i, ptr_[i]);
	this->swap(alloc);
}

template<typename T>
auto allocator<T>::construct(T * ptr, T const & value)->void
{
	if (ptr >= ptr_&&ptr < ptr_ + size_)
	{
		new(ptr)T(value);
		map_->set(ptr - ptr_);
	}
	else { throw("error"); }
}
template <typename T>
auto allocator<T>::destroy(T * ptr)->void
{
if (ptr < ptr_ || ptr >= ptr_ + size_ || map_->test(ptr-ptr_) == false)
{
		throw std::out_of_range("Error");
}
	ptr->~T();
	map_->reset(ptr - ptr_);

}

template<typename T> //получаем ptr_
auto allocator<T>::get()-> T* { return ptr_; }

template<typename T>
auto allocator<T>::get() const -> T const * { return ptr_; }

template<typename T>
auto allocator<T>::count() const -> size_t{ return map_->counter(); }

template<typename T> //заполненность
auto allocator<T>::full() const -> bool { return (map_->counter() == size_); }

template<typename T>
auto allocator<T>::empty() const -> bool { return (map_->counter() == 0); }

template<typename T>
auto allocator<T>::destroy(T * first, T * last)->void
{
	if(first>=ptr_&&last<=ptr_+this->count())
		for (; first != last; ++first)
		{
			destroy(&*first);
		}
}

template<typename T>
auto allocator<T>::swap(allocator & other)->void{
	std::swap(ptr_, other.ptr_);
	std::swap(size_, other.size_);
	std::swap(map_, other.map_);
	std::swap(count_, other.count_);
}

template <typename T>
class stack
{
public:
explicit
stack( size_t size = 0 );
stack (stack const & other);
auto operator =( stack const & other ) /*strong*/ -> stack &;

auto empty() const /*noexcept*/ -> bool;
auto count() const /*noexcept*/ -> size_t;

auto push( T const & value ) /*strong*/ -> void;
auto pop() /*strong*/ -> std::shared_ptr<T>;

private:
allocator<T> allocator_;
mutable std::mutex mutex_;

auto throw_is_empty() const -> void;
};

template<typename T>
stack<T>::stack(size_t size) : allocator_(size),mutex_() {};

template <typename T>
 stack<T>::stack(stack const & other) : allocator_(0), mutex_()
 {
 	std::lock_guard<std::mutex> lock(other.mutex_);
 	allocator<T>(other.allocator_).swap(allocator_);
}

template <typename T>
auto stack<T>::operator=(const stack &other)->stack&
{
	if (this != &other)
	{
		std::lock(mutex_, other.mutex_);
 		std::lock_guard<std::mutex> lock_a(mutex_, std::adopt_lock);
 		std::lock_guard<std::mutex> lock_b(other.mutex_, std::adopt_lock);
		stack(other).allocator_.swap(allocator_);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const->bool
{
	std::lock_guard<std::mutex> lock(mutex_);
	return (allocator_.count() == 0);
}

template<typename T>
auto stack<T>::count()const->size_t
{
return allocator_.count();
}

template<typename T>
auto stack<T>::push(T const & value)->void
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (allocator_.full()) allocator_.resize();
	allocator_.construct(allocator_.get() + this->count(), value);
}

template <typename T>
auto stack<T>::pop()->std::shared_ptr<T>
{
	std::lock_guard<std::mutex> lock(mutex_);
			if(allocator_.empty()) throw std::logic_error("Empty!");
				std::shared_ptr<T> const result(std::make_shared<T>(std::move(allocator_.get()[allocator_.count()-1])));
			allocator_.destroy(allocator_.get() + allocator_.count() - 1);
			return result;
}

<commit_msg>Update stack.hpp<commit_after>#include <iostream>
#include <new>
#include <stdexcept>
#include <vector>
#include <memory>
#include <mutex>
#include <thread>

class bitset
{
public:
explicit
bitset( size_t size ) /*strong*/;

bitset( bitset const & other ) = delete;
auto operator =( bitset const & other ) -> bitset & = delete;

bitset( bitset && other ) = delete;
auto operator =( bitset && other ) -> bitset & = delete;

auto set( size_t index ) /*strong*/ -> void;
auto reset( size_t index ) throw(std::out_of_range)/*strong*/ -> void;
auto test( size_t index ) const throw(std::out_of_range)/*strong*/ -> bool;

auto size() const /*noexcept*/ -> size_t;
auto counter() const /*noexcept*/ -> size_t;

private:
std::unique_ptr<bool[]> ptr_;
size_t size_;
size_t counter_;
};
bitset::bitset(size_t size) : ptr_(std::make_unique<bool[]>(size)),size_(size),counter_(0)
{}

auto bitset::set(size_t index)->void //инициализация всех битов единицами или изменение значения отдельного бита
{
	if (index >= 0 && index < size_)
	{
		ptr_[index] = true; ++counter_;
	}
	else throw("problem with index");
}

auto bitset::reset(size_t index) throw(std::out_of_range) -> void //обнуление указанных битов
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	ptr_[index] = false;
	--counter_;
}

auto bitset::test(size_t index) const throw(std::out_of_range) -> bool //возвращает значение указанного бита
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	return ptr_[index];
}

auto bitset::size() const -> size_t
{
	return size_;
}
auto bitset::counter() const -> size_t
{
	return counter_;
}

template <typename T>
class allocator
{
public:
explicit
allocator( std::size_t size = 0 ) /*strong*/;
allocator( allocator const & other ) /*strong*/;
auto operator =( allocator const & other ) -> allocator & = delete;
~allocator();

auto resize() /*strong*/ -> void;

auto construct(T * ptr, T const & value ) /*strong*/ -> void;
auto destroy( T * ptr ) /*noexcept*/ -> void;

auto get() /*noexcept*/ -> T *;
auto get() const /*noexcept*/ -> T const *;

auto count() const /*noexcept*/ -> size_t;
auto full() const /*noexcept*/ -> bool;
auto empty() const /*noexcept*/ -> bool;
private:
auto destroy( T * first, T * last ) /*noexcept*/ -> void;
auto swap( allocator & other ) /*noexcept*/ -> void;

private:
size_t count_;
T * ptr_;
size_t size_;
std::unique_ptr<bitset> map_;
};
template<typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)operator new(size*sizeof(T))), size_(size), map_(std::make_unique<bitset>(size))//конструктор с параметром
{}

template<typename T>
allocator<T>::allocator(allocator const& other) : allocator<T>(other.size_) //конструктор копирования
{
	for (size_t i=0; i < size_; i++)
	{
		if (map_->test(i))
		{
			destroy(ptr_, ptr_ +i);
		}
	construct(ptr_ + i, other.ptr_[i]);
}}

template<typename T>
allocator<T>::~allocator()
{
	if (this->count() > 0)
	{
		destroy(ptr_, ptr_ + size_);
	}
	operator delete(ptr_);
}

template<typename T> //увеличение памяти
auto allocator<T>::resize()->void
{
	allocator<T> alloc(size_ * 2 + (size_ == 0));
	for (size_t i = 0; i < size_; ++i) if(map_->test(i)) alloc.construct(alloc.get() + i, ptr_[i]);
	this->swap(alloc);
}

template<typename T>
auto allocator<T>::construct(T * ptr, T const & value)->void
{
	if (ptr >= ptr_&&ptr < ptr_ + size_)
	{
		new(ptr)T(value);
		map_->set(ptr - ptr_);
	}
	else { throw("error"); }
}
template <typename T>
auto allocator<T>::destroy(T * ptr)->void
{
if (ptr < ptr_ || ptr >= ptr_ + size_ || map_->test(ptr-ptr_) == false)
{
		throw std::out_of_range("Error");
}
	ptr->~T();
	map_->reset(ptr - ptr_);

}

template<typename T> //получаем ptr_
auto allocator<T>::get()-> T* { return ptr_; }

template<typename T>
auto allocator<T>::get() const -> T const * { return ptr_; }

template<typename T>
auto allocator<T>::count() const -> size_t{ return map_->counter(); }

template<typename T> //заполненность
auto allocator<T>::full() const -> bool { return (map_->counter() == size_); }

template<typename T>
auto allocator<T>::empty() const -> bool { return (map_->counter() == 0); }

template<typename T>
auto allocator<T>::destroy(T * first, T * last)->void
{
	if(first>=ptr_&&last<=ptr_+this->count())
		for (; first != last; ++first)
		{
			destroy(&*first);
		}
}

template<typename T>
auto allocator<T>::swap(allocator & other)->void{
	std::swap(ptr_, other.ptr_);
	std::swap(size_, other.size_);
	std::swap(map_, other.map_);
	std::swap(count_, other.count_);
}

template <typename T>
class stack
{
public:
explicit
stack( size_t size = 0 );
stack (stack const & other);
auto operator =( stack const & other ) /*strong*/ -> stack &;

auto empty() const /*noexcept*/ -> bool;
auto count() const /*noexcept*/ -> size_t;

auto push( T const & value ) /*strong*/ -> void;
auto pop() /*strong*/ -> std::shared_ptr<T>;

private:
allocator<T> allocator_;
mutable std::mutex mutex_;

auto throw_is_empty() const -> void;
};

template<typename T>
stack<T>::stack(size_t size) : allocator_(size),mutex_() {};

template <typename T>
 stack<T>::stack(stack const & other) : allocator_(0), mutex_()
 {
 	std::lock_guard<std::mutex> lock(other.mutex_);
 	allocator_.swap(allocator<T>(other.allocator_));
}

template <typename T>
auto stack<T>::operator=(const stack &other)->stack&
{
	if (this != &other)
	{
		std::lock(mutex_, other.mutex_);
 		std::lock_guard<std::mutex> lock_1(mutex_, std::adopt_lock);
 		std::lock_guard<std::mutex> lock_2(other.mutex_, std::adopt_lock);
		(allocator<T>(other.allocator_)).swap(allocator_);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const->bool
{
	std::lock_guard<std::mutex> lock(mutex_);
	return (allocator_.count() == 0);
}

template<typename T>
auto stack<T>::count()const->size_t
{
return allocator_.count();
}

template<typename T>
auto stack<T>::push(T const & value)->void
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (allocator_.full()) allocator_.resize();
	allocator_.construct(allocator_.get() + this->count(), value);
}

template <typename T>
auto stack<T>::pop()->std::shared_ptr<T>
{
	std::lock_guard<std::mutex> lock(mutex_);
			if(allocator_.empty()) throw std::logic_error("Empty!");
				std::shared_ptr<T> const result(std::make_shared<T>(std::move(allocator_.get()[allocator_.count()-1])));
			allocator_.destroy(allocator_.get() + allocator_.count() - 1);
			return result;
}

<|endoftext|>


<commit_before>/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */
/*
 * Copyright 2014 Teclo Networks AG
 */

#include "connection.h"

#include <functional>
#include <google/protobuf/text_format.h>

#include "io-backend.h"
#include "log.h"
#include "sequtil.h"
#include "strutil.h"

TcpFlow::TcpFlow(State* state, Profile* profile,
                 IoInterface* iface, const std::string& id)
    : state_(state),
      iface_(iface),
      dumper_(iface->name() + "-" + id + ".cap"),
      transmit_timer_(state, [this] (Timer* t) { transmit_timeout(); }),
      delay_s_(0),
      received_rst_(false),
      received_fin_(false),
      throttler_(state) {
    if (profile->profile_config().dump_pcap()) {
        if (!dumper_.open()) {
            fail("Failed to open trace file.");
        }
    }
}

TcpFlow::~TcpFlow() {
    for (auto packet : packets_) {
        delete packet.second;
    }
}

void TcpFlow::record_packet_rx(Packet* p) {
    if (p->tcp().fin()) {
        received_fin_ = true;
    }
    if (p->tcp().rst()) {
        received_rst_ = true;
    }

    if (p->tcp().syn()) {
        other_->snd_una_ = p->tcp().seq();
        snd_nxt_ = p->tcp().seq();
    }

    if (p->tcp().ack()) {
        snd_una_ = seq_max(snd_una_, p->tcp().ack_seq());
    }
    if (p->tcp().has_end_seq()) {
        snd_nxt_ = seq_max(snd_nxt_, p->tcp().end_seq());
    }

    dumper_.dump_packet(p);
}

void TcpFlow::queue_packet_tx(Packet* p) {
    auto callback = [&] (Packet copy) {
        packets_.push_back(std::make_pair(ev_now(state_->loop) + delay_s_,
                                          new Packet(copy)));
        transmit();
    };

    throttler_.insert(p->length_, std::bind(callback, *p));
}

void TcpFlow::reschedule_transmit_timer() {
    transmit_timer_.stop();

    if (!packets_.empty()) {
        ev_tstamp delay = packets_.front().first - ev_now(state_->loop);
        transmit_timer_.reschedule(delay);
    }
}

void TcpFlow::transmit() {
    while (!packets_.empty()) {
        ev_tstamp target = packets_.front().first;
        if (target > ev_now(state_->loop)) {
            break;
        }

        Packet* p = packets_.front().second;

        iface_->io()->inject(p);
        dumper_.dump_packet(p);

        packets_.pop_front();
        delete p;
    }

    reschedule_transmit_timer();
}

void TcpFlow::transmit_timeout() {
    transmit();
}

bool TcpFlow::is_valid_synack(Packet* p) {
    // FIXME: Stub
    if (p->tcp().syn() && p->tcp().ack()) {
        return true;
    }

    return false;
}

bool TcpFlow::is_valid_3whs_ack(Packet* p) {
    // FIXME: Stub
    if (!p->tcp().syn() && p->tcp().ack()) {
        return true;
    }

    return false;
}

bool TcpFlow::is_identical_syn(Packet* p) {
    // FIXME: Stub
    if (p->tcp().syn() && !p->tcp().ack()) {
        return true;
    }

    return false;
}

bool TcpFlow::is_identical_synack(Packet* p) {
    // FIXME: Stub
    if (p->tcp().syn() && p->tcp().ack()) {
        return true;
    }

    return false;
}

bool TcpFlow::should_close() {
    if (received_rst_ ||
        (received_fin_ && other_->received_fin_)) {
        return true;
    }

    return false;
}

bool TcpFlow::can_close() {
    if (received_rst_ || packets_.empty()) {
        return true;
    }

    return false;
}

Connection::Connection(Profile* profile, Packet* p, State* state)
    : state_(state),
      profile_(profile),
      first_syn_timestamp_(ev_now(state_->loop)),
      connection_state_(STATE_SYN),
      id_(stringprintf("%.9lf", ev_time())),
      client_(state, profile, p->from_iface_, id_),
      server_(state, profile, p->from_iface_->other(), id_),
      idle_timer_(state, ([this] (Timer* t) { close(); })) {
    info("New connection %p using profile %s\n", this,
         profile->profile_config().id().c_str());

    client_.set_other(&server_);
    server_.set_other(&client_);

    if (profile->profile_config().has_downlink()) {
        client_.throttler()->enable(profile->profile_config().downlink());
    }

    if (profile->profile_config().has_uplink()) {
        server_.throttler()->enable(profile->profile_config().uplink());
    }

    client_.record_packet_rx(p);
    server_.queue_packet_tx(p);

    idle_timer_.reschedule(120);

    for (auto event : profile->profile_config().timed_event()) {
        auto apply = [this, event] (Timer* t) {
            apply_timed_effect(t, event);
        };
        auto revert = [this, event] (Timer* t) {
            revert_timed_effect(t, event);
        };

        event_timers_.push_back(new Timer(state, apply));
        event_timers_.back()->reschedule(event.trigger_time());

        if (event.has_duration()) {
            event_timers_.push_back(new Timer(state, revert));
            event_timers_.back()->reschedule(event.trigger_time() +
                                             event.duration());
        }
    }
}

Connection::~Connection() {
    for (auto event_timer : event_timers_) {
        delete event_timer;
    }
}

void Connection::apply_timed_effect(Timer* timer, const TimedEvent& event) {
    if (event.has_extra_rtt()) {
        info("Applying extra delay of %lf", event.extra_rtt());
        client_.set_delay(client_.delay() + event.extra_rtt());
    }

    client_.throttler()->apply(event.downlink());
    server_.throttler()->apply(event.uplink());

    if (event.has_repeat_interval()) {
        timer->reschedule(event.repeat_interval());
    }
}

void Connection::revert_timed_effect(Timer* timer, const TimedEvent& event) {
    if (event.has_extra_rtt()) {
        info("Reverting extra delay of %lf", event.extra_rtt());
        client_.set_delay(client_.delay() - event.extra_rtt());
    }

    client_.throttler()->revert(event.downlink());
    server_.throttler()->revert(event.uplink());

    if (event.has_repeat_interval()) {
        timer->reschedule(event.repeat_interval());
    }
}

void Connection::receive(Packet* p) {
    TcpFlow* source_flow = packet_source_flow(p);
    TcpFlow* target_flow = source_flow->other();

    bool from_client = source_flow == &client_;

    // {
    //     std::string text;
    //     google::protobuf::TextFormat::PrintToString(*p, &text);
    //     info("rx: %s\n", text.c_str());
    // }

    source_flow->record_packet_rx(p);

    if (source_flow->should_close()) {
        connection_state_ = STATE_CLOSING;
    }

    switch (connection_state_) {
    case STATE_SYN:
        if (!from_client && client_.is_valid_synack(p)) {
            connection_state_ = STATE_SYN_ACK;
            double server_side_rtt = ev_now(state_->loop) - first_syn_timestamp_;
            double target_rtt = profile_->profile_config().target_rtt();
            if (target_rtt && target_rtt > server_side_rtt) {
                double delay_s = target_rtt - server_side_rtt;
                client_.set_delay(delay_s);
            }
        } else if (from_client && source_flow->is_identical_syn(p)) {
            // Retransmit. Do nothing.
        } else {
            // Getting packets that don't make sense for this handshake.
            // Give up on the connection.
            warn("Handshake confusion, expected SYN-ACK from server. "
                 "Bailing out.\n");
            std::string text;
            google::protobuf::TextFormat::PrintToString(*p, &text);
            warn("packet: %s\n", text.c_str());
            goto fail;
        }
        // Note: we don't support SYN-SYN connection opening.

        break;

    case STATE_SYN_ACK:
        if ((!from_client && source_flow->is_identical_synack(p)) ||
            (from_client && source_flow->is_identical_syn(p))) {
            // Retransmit. Do nothing.
        } else if (from_client && source_flow->is_valid_3whs_ack(p)) {
            connection_state_ = STATE_ESTABLISHED;
        } else {
            // Getting packets that don't make sense for this handshake.
            // Give up on the connection.
            warn("Handshake confusion, expected ACK from client. "
                 "Bailing out.\n");
            goto fail;
        }

        break;

    case STATE_ESTABLISHED:
        break;

    case STATE_CLOSING:
        if (source_flow->can_close() &&
            source_flow->can_close()) {
            close();
            return;
        }
        break;
    }

    target_flow->queue_packet_tx(p);
    idle_timer_.reschedule(120);

    return;

fail:
    close();
    return;
}

void Connection::close() {
    info("Closing connection %p\n", this);
    state_->connections->remove(this);
    delete this;
}

TcpFlow* Connection::packet_source_flow(Packet* p) {
    if (p->from_iface_ == client_.iface()) {
        return &client_;
    } else {
        return &server_;
    }
}

class ConnectionIpv4 : public Connection {
public:
    ConnectionIpv4(Profile* profile, Packet* p, State* state)
        : Connection(profile, p, state) {
    }

    virtual int addr_bytes() const { return 4; }
};

class ConnectionIpv6 : public Connection {
public:
    ConnectionIpv6(Profile* profile, Packet* p, State* state)
        : Connection(profile, p, state) {
    }

    virtual int addr_bytes() const { return 16; }
};

Connection* Connection::make(Profile* profile, Packet* p, State* state) {
    Connection* connection;
    if (p->has_ipv4()) {
        connection = new ConnectionIpv4(profile, p, state);
    } else if (p->has_ipv6()) {
        connection = new ConnectionIpv6(profile, p, state);
    } else {
        fail("TCP without IPv4 or IPv6?");
    }

    state->connections->add_connection_for_packet(connection, p);

    return connection;
}
<commit_msg>Add profile name to dump file<commit_after>/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */
/*
 * Copyright 2014 Teclo Networks AG
 */

#include "connection.h"

#include <functional>
#include <google/protobuf/text_format.h>

#include "io-backend.h"
#include "log.h"
#include "sequtil.h"
#include "strutil.h"

TcpFlow::TcpFlow(State* state, Profile* profile,
                 IoInterface* iface, const std::string& id)
    : state_(state),
      iface_(iface),
      dumper_(stringprintf("%s-%s-%s.cap",
                           iface->name().c_str(),
                           profile->profile_config().id().c_str(),
                           id.c_str())),
      transmit_timer_(state, [this] (Timer* t) { transmit_timeout(); }),
      delay_s_(0),
      received_rst_(false),
      received_fin_(false),
      throttler_(state) {
    if (profile->profile_config().dump_pcap()) {
        if (!dumper_.open()) {
            fail("Failed to open trace file.");
        }
    }
}

TcpFlow::~TcpFlow() {
    for (auto packet : packets_) {
        delete packet.second;
    }
}

void TcpFlow::record_packet_rx(Packet* p) {
    if (p->tcp().fin()) {
        received_fin_ = true;
    }
    if (p->tcp().rst()) {
        received_rst_ = true;
    }

    if (p->tcp().syn()) {
        other_->snd_una_ = p->tcp().seq();
        snd_nxt_ = p->tcp().seq();
    }

    if (p->tcp().ack()) {
        snd_una_ = seq_max(snd_una_, p->tcp().ack_seq());
    }
    if (p->tcp().has_end_seq()) {
        snd_nxt_ = seq_max(snd_nxt_, p->tcp().end_seq());
    }

    dumper_.dump_packet(p);
}

void TcpFlow::queue_packet_tx(Packet* p) {
    auto callback = [&] (Packet copy) {
        packets_.push_back(std::make_pair(ev_now(state_->loop) + delay_s_,
                                          new Packet(copy)));
        transmit();
    };

    throttler_.insert(p->length_, std::bind(callback, *p));
}

void TcpFlow::reschedule_transmit_timer() {
    transmit_timer_.stop();

    if (!packets_.empty()) {
        ev_tstamp delay = packets_.front().first - ev_now(state_->loop);
        transmit_timer_.reschedule(delay);
    }
}

void TcpFlow::transmit() {
    while (!packets_.empty()) {
        ev_tstamp target = packets_.front().first;
        if (target > ev_now(state_->loop)) {
            break;
        }

        Packet* p = packets_.front().second;

        iface_->io()->inject(p);
        dumper_.dump_packet(p);

        packets_.pop_front();
        delete p;
    }

    reschedule_transmit_timer();
}

void TcpFlow::transmit_timeout() {
    transmit();
}

bool TcpFlow::is_valid_synack(Packet* p) {
    // FIXME: Stub
    if (p->tcp().syn() && p->tcp().ack()) {
        return true;
    }

    return false;
}

bool TcpFlow::is_valid_3whs_ack(Packet* p) {
    // FIXME: Stub
    if (!p->tcp().syn() && p->tcp().ack()) {
        return true;
    }

    return false;
}

bool TcpFlow::is_identical_syn(Packet* p) {
    // FIXME: Stub
    if (p->tcp().syn() && !p->tcp().ack()) {
        return true;
    }

    return false;
}

bool TcpFlow::is_identical_synack(Packet* p) {
    // FIXME: Stub
    if (p->tcp().syn() && p->tcp().ack()) {
        return true;
    }

    return false;
}

bool TcpFlow::should_close() {
    if (received_rst_ ||
        (received_fin_ && other_->received_fin_)) {
        return true;
    }

    return false;
}

bool TcpFlow::can_close() {
    if (received_rst_ || packets_.empty()) {
        return true;
    }

    return false;
}

Connection::Connection(Profile* profile, Packet* p, State* state)
    : state_(state),
      profile_(profile),
      first_syn_timestamp_(ev_now(state_->loop)),
      connection_state_(STATE_SYN),
      id_(stringprintf("%.9lf", ev_time())),
      client_(state, profile, p->from_iface_, id_),
      server_(state, profile, p->from_iface_->other(), id_),
      idle_timer_(state, ([this] (Timer* t) { close(); })) {
    info("New connection %p using profile %s\n", this,
         profile->profile_config().id().c_str());

    client_.set_other(&server_);
    server_.set_other(&client_);

    if (profile->profile_config().has_downlink()) {
        client_.throttler()->enable(profile->profile_config().downlink());
    }

    if (profile->profile_config().has_uplink()) {
        server_.throttler()->enable(profile->profile_config().uplink());
    }

    client_.record_packet_rx(p);
    server_.queue_packet_tx(p);

    idle_timer_.reschedule(120);

    for (auto event : profile->profile_config().timed_event()) {
        auto apply = [this, event] (Timer* t) {
            apply_timed_effect(t, event);
        };
        auto revert = [this, event] (Timer* t) {
            revert_timed_effect(t, event);
        };

        event_timers_.push_back(new Timer(state, apply));
        event_timers_.back()->reschedule(event.trigger_time());

        if (event.has_duration()) {
            event_timers_.push_back(new Timer(state, revert));
            event_timers_.back()->reschedule(event.trigger_time() +
                                             event.duration());
        }
    }
}

Connection::~Connection() {
    for (auto event_timer : event_timers_) {
        delete event_timer;
    }
}

void Connection::apply_timed_effect(Timer* timer, const TimedEvent& event) {
    if (event.has_extra_rtt()) {
        info("Applying extra delay of %lf", event.extra_rtt());
        client_.set_delay(client_.delay() + event.extra_rtt());
    }

    client_.throttler()->apply(event.downlink());
    server_.throttler()->apply(event.uplink());

    if (event.has_repeat_interval()) {
        timer->reschedule(event.repeat_interval());
    }
}

void Connection::revert_timed_effect(Timer* timer, const TimedEvent& event) {
    if (event.has_extra_rtt()) {
        info("Reverting extra delay of %lf", event.extra_rtt());
        client_.set_delay(client_.delay() - event.extra_rtt());
    }

    client_.throttler()->revert(event.downlink());
    server_.throttler()->revert(event.uplink());

    if (event.has_repeat_interval()) {
        timer->reschedule(event.repeat_interval());
    }
}

void Connection::receive(Packet* p) {
    TcpFlow* source_flow = packet_source_flow(p);
    TcpFlow* target_flow = source_flow->other();

    bool from_client = source_flow == &client_;

    // {
    //     std::string text;
    //     google::protobuf::TextFormat::PrintToString(*p, &text);
    //     info("rx: %s\n", text.c_str());
    // }

    source_flow->record_packet_rx(p);

    if (source_flow->should_close()) {
        connection_state_ = STATE_CLOSING;
    }

    switch (connection_state_) {
    case STATE_SYN:
        if (!from_client && client_.is_valid_synack(p)) {
            connection_state_ = STATE_SYN_ACK;
            double server_side_rtt = ev_now(state_->loop) - first_syn_timestamp_;
            double target_rtt = profile_->profile_config().target_rtt();
            if (target_rtt && target_rtt > server_side_rtt) {
                double delay_s = target_rtt - server_side_rtt;
                client_.set_delay(delay_s);
            }
        } else if (from_client && source_flow->is_identical_syn(p)) {
            // Retransmit. Do nothing.
        } else {
            // Getting packets that don't make sense for this handshake.
            // Give up on the connection.
            warn("Handshake confusion, expected SYN-ACK from server. "
                 "Bailing out.\n");
            std::string text;
            google::protobuf::TextFormat::PrintToString(*p, &text);
            warn("packet: %s\n", text.c_str());
            goto fail;
        }
        // Note: we don't support SYN-SYN connection opening.

        break;

    case STATE_SYN_ACK:
        if ((!from_client && source_flow->is_identical_synack(p)) ||
            (from_client && source_flow->is_identical_syn(p))) {
            // Retransmit. Do nothing.
        } else if (from_client && source_flow->is_valid_3whs_ack(p)) {
            connection_state_ = STATE_ESTABLISHED;
        } else {
            // Getting packets that don't make sense for this handshake.
            // Give up on the connection.
            warn("Handshake confusion, expected ACK from client. "
                 "Bailing out.\n");
            goto fail;
        }

        break;

    case STATE_ESTABLISHED:
        break;

    case STATE_CLOSING:
        if (source_flow->can_close() &&
            source_flow->can_close()) {
            close();
            return;
        }
        break;
    }

    target_flow->queue_packet_tx(p);
    idle_timer_.reschedule(120);

    return;

fail:
    close();
    return;
}

void Connection::close() {
    info("Closing connection %p\n", this);
    state_->connections->remove(this);
    delete this;
}

TcpFlow* Connection::packet_source_flow(Packet* p) {
    if (p->from_iface_ == client_.iface()) {
        return &client_;
    } else {
        return &server_;
    }
}

class ConnectionIpv4 : public Connection {
public:
    ConnectionIpv4(Profile* profile, Packet* p, State* state)
        : Connection(profile, p, state) {
    }

    virtual int addr_bytes() const { return 4; }
};

class ConnectionIpv6 : public Connection {
public:
    ConnectionIpv6(Profile* profile, Packet* p, State* state)
        : Connection(profile, p, state) {
    }

    virtual int addr_bytes() const { return 16; }
};

Connection* Connection::make(Profile* profile, Packet* p, State* state) {
    Connection* connection;
    if (p->has_ipv4()) {
        connection = new ConnectionIpv4(profile, p, state);
    } else if (p->has_ipv6()) {
        connection = new ConnectionIpv6(profile, p, state);
    } else {
        fail("TCP without IPv4 or IPv6?");
    }

    state->connections->add_connection_for_packet(connection, p);

    return connection;
}
<|endoftext|>


<commit_before>#pragma once
#include <opencv2/core/core.hpp>
#include <ctype.h>
#include <cmath>

namespace sift {
    const auto IMAGE_DATA_TYPE = CV_8U;
    typedef uint8_t image_t;

    const auto GAUSSIAN_PYR_KERNEL_SIZE = 3;
    // sigma of the gaussian blur kernel
    const auto GAUSSIAN_PYR_SIGMA0      = std::sqrt(2);

    // size of each octave is s+3
    const auto GAUSSIAN_PYR_S           = 2;
    // factor between sigma of each blurred image
    const auto GAUSSIAN_PYR_K           = std::pow(2.0, 1.0/GAUSSIAN_PYR_S);

    // size of each octave (number of blurred images)
    const auto GAUSSIAN_PYR_OCTAVE_SIZE = GAUSSIAN_PYR_S + 3;
}
<commit_msg>Use double precision floating points as our native datatype<commit_after>#pragma once
#include <opencv2/core/core.hpp>
#include <ctype.h>
#include <cmath>

namespace sift {
    const auto IMAGE_DATA_TYPE = CV_64F;
    typedef double image_t;

    const auto GAUSSIAN_PYR_KERNEL_SIZE = 3;
    // sigma of the gaussian blur kernel
    const auto GAUSSIAN_PYR_SIGMA0      = std::sqrt(2);

    // size of each octave is s+3
    const auto GAUSSIAN_PYR_S           = 2;
    // factor between sigma of each blurred image
    const auto GAUSSIAN_PYR_K           = std::pow(2.0, 1.0/GAUSSIAN_PYR_S);

    // size of each octave (number of blurred images)
    const auto GAUSSIAN_PYR_OCTAVE_SIZE = GAUSSIAN_PYR_S + 3;
}
<|endoftext|>