<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2005 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/io.h>

namespace geos {

string WKBReader::BAD_GEOM_TYPE_MSG = "bad geometry type encountered in ";

ostream &
WKBReader::printHEX(istream &is, ostream &os)
{
	ios_base::fmtflags fl = os.flags(); // take note of output stream flags

	// Set hex,uppercase,fill and width output stream flags
	os.setf(ios::uppercase);
	os.setf(ios::hex, ios::basefield);
	os.setf(ios::hex, ios::basefield);
	os.fill('0');

	long pos = is.tellg(); // take note of input stream get pointer
	is.seekg(0, ios::beg); // rewind

	byte each=0;
	while(is.read(reinterpret_cast<char *>(&each), 1))
		os<<setw(2)<<(int)each;

	is.clear(); // clear input stream eof flag
	is.seekg(pos); // reset input stream position
	os.setf(fl);  // reset output stream status
	return os;
}

Geometry *
WKBReader::read(istream &is)
{
	dis.setInStream(&is); // will default to machine endian
	inputDimension = 2; // handle 2d only for now

	// only allocate ordValues buffer if necessary
	if ( ordValues.size() < inputDimension )
		ordValues.resize(inputDimension);

	return readGeometry();
}

Geometry *
WKBReader::readGeometry()
{
	// determine byte order
	byte byteOrder = dis.readByte();

#if DEBUG_WKB_READER
	cout<<"WKB byteOrder: "<<(int)byteOrder<<endl;
#endif

	// default is machine endian
	if (byteOrder == WKBConstants::wkbNDR)
		dis.setOrder(ByteOrderValues::ENDIAN_LITTLE);

	int typeInt = dis.readInt();
#if DEBUG_WKB_READER
	cout<<"WKB type: "<<typeInt<<endl;
#endif

	int geometryType = typeInt & 0xff;
	bool hasZ = ((typeInt & 0x80000000) != 0);
	if (hasZ) inputDimension = 3;

#if DEBUG_WKB_READER
	cout<<"WKB dimensions: "<<inputDimension<<endl;
#endif

	switch (geometryType) {
		case WKBConstants::wkbPoint :
			return readPoint();
		case WKBConstants::wkbLineString :
			return readLineString();
		case WKBConstants::wkbPolygon :
			return readPolygon();
		case WKBConstants::wkbMultiPoint :
			return readMultiPoint();
		case WKBConstants::wkbMultiLineString :
			return readMultiLineString();
		case WKBConstants::wkbMultiPolygon :
			return readMultiPolygon();
		case WKBConstants::wkbGeometryCollection :
			return readGeometryCollection();
	}
	throw new ParseException("Unknown WKB type " + geometryType);
}

Point *
WKBReader::readPoint()
{
	readCoordinate();
#if DEBUG_WKB_READER
	cout<<"Coordinates: "<<ordValues[0]<<","<<ordValues[1]<<endl;
#endif
	return factory.createPoint(Coordinate(ordValues[0], ordValues[1]));
}

LineString *
WKBReader::readLineString()
{
	int size = dis.readInt();
	CoordinateSequence *pts = readCoordinateSequence(size);
	return factory.createLineString(pts);
}

LinearRing *
WKBReader::readLinearRing()
{
	int size = dis.readInt();
	CoordinateSequence *pts = readCoordinateSequence(size);
	return factory.createLinearRing(pts);
}

Polygon *
WKBReader::readPolygon()
{
	int numRings = dis.readInt();
	LinearRing *shell = readLinearRing();

	vector<Geometry *>*holes=NULL;
	if ( numRings > 1 )
	{
		try {
			holes = new vector<Geometry *>(numRings-1);
			for (int i=0; i<numRings-1; i++)
				(*holes)[i] = (Geometry *)readLinearRing();
		} catch (...) {
			for (unsigned int i=0; i<holes->size(); i++)
				delete (*holes)[i];
			delete holes;
			delete shell;
			throw;
		}
	}
	return factory.createPolygon(shell, holes);
}

MultiPoint *
WKBReader::readMultiPoint()
{
	int numGeoms = dis.readInt();
	vector<Geometry *> *geoms = new vector<Geometry *>(numGeoms);

	try {
		for (int i=0; i<numGeoms; i++)
		{
			Geometry *g = readGeometry();
			if (!dynamic_cast<Point *>(g))
				throw new ParseException(BAD_GEOM_TYPE_MSG+
					" MultiPoint");
			(*geoms)[i] = g;
		}
	} catch (...) {
		for (unsigned int i=0; i<geoms->size(); i++)
			delete (*geoms)[i];
		delete geoms;
		throw;
	}
	return factory.createMultiPoint(geoms);
}

MultiLineString *
WKBReader::readMultiLineString()
{
	int numGeoms = dis.readInt();
	vector<Geometry *> *geoms = new vector<Geometry *>(numGeoms);

	try {
		for (int i=0; i<numGeoms; i++)
		{
			Geometry *g = readGeometry();
			if (!dynamic_cast<LineString *>(g))
				throw new ParseException(BAD_GEOM_TYPE_MSG+
					" LineString");
			(*geoms)[i] = g;
		}
	} catch (...) {
		for (unsigned int i=0; i<geoms->size(); i++)
			delete (*geoms)[i];
		delete geoms;
		throw;
	}
	return factory.createMultiLineString(geoms);
}

MultiPolygon *
WKBReader::readMultiPolygon()
{
	int numGeoms = dis.readInt();
	vector<Geometry *> *geoms = new vector<Geometry *>(numGeoms);

	try {
		for (int i=0; i<numGeoms; i++)
		{
			Geometry *g = readGeometry();
			if (!dynamic_cast<Polygon *>(g))
				throw new ParseException(BAD_GEOM_TYPE_MSG+
					" Polygon");
			(*geoms)[i] = g;
		}
	} catch (...) {
		for (unsigned int i=0; i<geoms->size(); i++)
			delete (*geoms)[i];
		delete geoms;
		throw;
	}
	return factory.createMultiPolygon(geoms);
}

GeometryCollection *
WKBReader::readGeometryCollection()
{
	int numGeoms = dis.readInt();
	vector<Geometry *> *geoms = new vector<Geometry *>(numGeoms);

	try {
		for (int i=0; i<numGeoms; i++)
			(*geoms)[i] = (readGeometry());
	} catch (...) {
		for (unsigned int i=0; i<geoms->size(); i++)
			delete (*geoms)[i];
		delete geoms;
		throw;
	}
	return factory.createGeometryCollection(geoms);
}

CoordinateSequence *
WKBReader::readCoordinateSequence(int size)
{
	CoordinateSequence *seq = factory.getCoordinateSequenceFactory()->create(size, inputDimension);
	unsigned int targetDim = seq->getDimension();
	if ( targetDim > inputDimension )
		targetDim = inputDimension;
	for (int i=0; i<size; i++) {
		readCoordinate();
		for (unsigned int j=0; j<targetDim; j++) {
			seq->setOrdinate(i, j, ordValues[j]);
		}
	}
	return seq;
}

void
WKBReader::readCoordinate()
{
	for (unsigned int i=0; i<inputDimension; ++i)
	{
		ordValues[i] = dis.readDouble();
	}
}

} // namespace geos
<commit_msg>Fixed handling of higher dimensional WKB streams<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2005 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/io.h>

//#define DEBUG_WKB_READER 1

namespace geos {

string WKBReader::BAD_GEOM_TYPE_MSG = "bad geometry type encountered in ";

ostream &
WKBReader::printHEX(istream &is, ostream &os)
{
	ios_base::fmtflags fl = os.flags(); // take note of output stream flags

	// Set hex,uppercase,fill and width output stream flags
	os.setf(ios::uppercase);
	os.setf(ios::hex, ios::basefield);
	os.setf(ios::hex, ios::basefield);
	os.fill('0');

	long pos = is.tellg(); // take note of input stream get pointer
	is.seekg(0, ios::beg); // rewind

	byte each=0;
	while(is.read(reinterpret_cast<char *>(&each), 1))
		os<<setw(2)<<(int)each;

	is.clear(); // clear input stream eof flag
	is.seekg(pos); // reset input stream position
	os.setf(fl);  // reset output stream status
	return os;
}

Geometry *
WKBReader::read(istream &is)
{
	dis.setInStream(&is); // will default to machine endian
	return readGeometry();
}

Geometry *
WKBReader::readGeometry()
{
	// determine byte order
	byte byteOrder = dis.readByte();

#if DEBUG_WKB_READER
	cout<<"WKB byteOrder: "<<(int)byteOrder<<endl;
#endif

	// default is machine endian
	if (byteOrder == WKBConstants::wkbNDR)
		dis.setOrder(ByteOrderValues::ENDIAN_LITTLE);

	int typeInt = dis.readInt();
	int geometryType = typeInt & 0xff;

#if DEBUG_WKB_READER
	cout<<"WKB geometryType: "<<geometryType<<endl;
#endif

	bool hasZ = ((typeInt & 0x80000000) != 0);
	if (hasZ) inputDimension = 3;
	else inputDimension = 2; // doesn't handle M currently

#if DEBUG_WKB_READER
	cout<<"WKB hasZ: "<<hasZ<<endl;
#endif

#if DEBUG_WKB_READER
	cout<<"WKB dimensions: "<<inputDimension<<endl;
#endif

	// allocate space for ordValues
	if ( ordValues.size() < inputDimension )
		ordValues.resize(inputDimension);

	switch (geometryType) {
		case WKBConstants::wkbPoint :
			return readPoint();
		case WKBConstants::wkbLineString :
			return readLineString();
		case WKBConstants::wkbPolygon :
			return readPolygon();
		case WKBConstants::wkbMultiPoint :
			return readMultiPoint();
		case WKBConstants::wkbMultiLineString :
			return readMultiLineString();
		case WKBConstants::wkbMultiPolygon :
			return readMultiPolygon();
		case WKBConstants::wkbGeometryCollection :
			return readGeometryCollection();
	}
	throw new ParseException("Unknown WKB type " + geometryType);
}

Point *
WKBReader::readPoint()
{
	readCoordinate();
#if DEBUG_WKB_READER
	cout<<"Coordinates: "<<ordValues[0]<<","<<ordValues[1]<<endl;
#endif
	return factory.createPoint(Coordinate(ordValues[0], ordValues[1]));
}

LineString *
WKBReader::readLineString()
{
	int size = dis.readInt();
	CoordinateSequence *pts = readCoordinateSequence(size);
	return factory.createLineString(pts);
}

LinearRing *
WKBReader::readLinearRing()
{
	int size = dis.readInt();
	CoordinateSequence *pts = readCoordinateSequence(size);
	return factory.createLinearRing(pts);
}

Polygon *
WKBReader::readPolygon()
{
	int numRings = dis.readInt();
	LinearRing *shell = readLinearRing();

	vector<Geometry *>*holes=NULL;
	if ( numRings > 1 )
	{
		try {
			holes = new vector<Geometry *>(numRings-1);
			for (int i=0; i<numRings-1; i++)
				(*holes)[i] = (Geometry *)readLinearRing();
		} catch (...) {
			for (unsigned int i=0; i<holes->size(); i++)
				delete (*holes)[i];
			delete holes;
			delete shell;
			throw;
		}
	}
	return factory.createPolygon(shell, holes);
}

MultiPoint *
WKBReader::readMultiPoint()
{
	int numGeoms = dis.readInt();
	vector<Geometry *> *geoms = new vector<Geometry *>(numGeoms);

	try {
		for (int i=0; i<numGeoms; i++)
		{
			Geometry *g = readGeometry();
			if (!dynamic_cast<Point *>(g))
				throw new ParseException(BAD_GEOM_TYPE_MSG+
					" MultiPoint");
			(*geoms)[i] = g;
		}
	} catch (...) {
		for (unsigned int i=0; i<geoms->size(); i++)
			delete (*geoms)[i];
		delete geoms;
		throw;
	}
	return factory.createMultiPoint(geoms);
}

MultiLineString *
WKBReader::readMultiLineString()
{
	int numGeoms = dis.readInt();
	vector<Geometry *> *geoms = new vector<Geometry *>(numGeoms);

	try {
		for (int i=0; i<numGeoms; i++)
		{
			Geometry *g = readGeometry();
			if (!dynamic_cast<LineString *>(g))
				throw new ParseException(BAD_GEOM_TYPE_MSG+
					" LineString");
			(*geoms)[i] = g;
		}
	} catch (...) {
		for (unsigned int i=0; i<geoms->size(); i++)
			delete (*geoms)[i];
		delete geoms;
		throw;
	}
	return factory.createMultiLineString(geoms);
}

MultiPolygon *
WKBReader::readMultiPolygon()
{
	int numGeoms = dis.readInt();
	vector<Geometry *> *geoms = new vector<Geometry *>(numGeoms);

	try {
		for (int i=0; i<numGeoms; i++)
		{
			Geometry *g = readGeometry();
			if (!dynamic_cast<Polygon *>(g))
				throw new ParseException(BAD_GEOM_TYPE_MSG+
					" Polygon");
			(*geoms)[i] = g;
		}
	} catch (...) {
		for (unsigned int i=0; i<geoms->size(); i++)
			delete (*geoms)[i];
		delete geoms;
		throw;
	}
	return factory.createMultiPolygon(geoms);
}

GeometryCollection *
WKBReader::readGeometryCollection()
{
	int numGeoms = dis.readInt();
	vector<Geometry *> *geoms = new vector<Geometry *>(numGeoms);

	try {
		for (int i=0; i<numGeoms; i++)
			(*geoms)[i] = (readGeometry());
	} catch (...) {
		for (unsigned int i=0; i<geoms->size(); i++)
			delete (*geoms)[i];
		delete geoms;
		throw;
	}
	return factory.createGeometryCollection(geoms);
}

CoordinateSequence *
WKBReader::readCoordinateSequence(int size)
{
	cerr<<"WKBReader::readCoordinateSequence("<<size<<") called"<<endl;
	CoordinateSequence *seq = factory.getCoordinateSequenceFactory()->create(size, inputDimension);
	unsigned int targetDim = seq->getDimension();
	if ( targetDim > inputDimension )
		targetDim = inputDimension;
	for (int i=0; i<size; i++) {
		readCoordinate();
		for (unsigned int j=0; j<targetDim; j++) {
			seq->setOrdinate(i, j, ordValues[j]);
		}
	}
	return seq;
}

void
WKBReader::readCoordinate()
{
	for (unsigned int i=0; i<inputDimension; ++i)
	{
		ordValues[i] = dis.readDouble();
	}
}

} // namespace geos
<|endoftext|>


<commit_before>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <stdexcept>
#include "VorbisClip.hpp"
#include "Audio.hpp"
#include "mixer/Stream.hpp"
#include "mixer/Source.hpp"
#include "utils/Utils.hpp"

#include "stb_vorbis.c"

namespace ouzel
{
    namespace audio
    {
        class VorbisData;

        class VorbisSource final: public mixer::Stream
        {
        public:
            VorbisSource(VorbisData& vorbisData);

            ~VorbisSource()
            {
                if (vorbisStream)
                    stb_vorbis_close(vorbisStream);
            }

            void reset() override
            {
                stb_vorbis_seek_start(vorbisStream);
            }

            void getData(uint32_t frames, std::vector<float>& samples) override;

        private:
            stb_vorbis* vorbisStream = nullptr;
            std::vector<float> data;
        };

        class VorbisData final: public mixer::Source
        {
        public:
            VorbisData(const std::vector<uint8_t>& initData):
                data(initData)
            {
                stb_vorbis* vorbisStream = stb_vorbis_open_memory(data.data(), static_cast<int>(data.size()), nullptr, nullptr);

                if (!vorbisStream)
                    throw std::runtime_error("Failed to load Vorbis stream");

                stb_vorbis_info info = stb_vorbis_get_info(vorbisStream);

                channels = static_cast<uint16_t>(info.channels);
                sampleRate = info.sample_rate;

                stb_vorbis_close(vorbisStream);
            }

            const std::vector<uint8_t>& getData() const { return data; }

            std::unique_ptr<mixer::Stream> createStream() override
            {
                return std::unique_ptr<mixer::Stream>(new VorbisSource(*this));
            }

        private:
            std::vector<uint8_t> data;
        };

        VorbisSource::VorbisSource(VorbisData& vorbisData):
            Stream(vorbisData)
        {
            const std::vector<uint8_t>& data = vorbisData.getData();
            vorbisStream = stb_vorbis_open_memory(data.data(), static_cast<int>(data.size()), nullptr, nullptr);
        }

        void VorbisSource::getData(uint32_t frames, std::vector<float>& samples)
        {
            uint32_t neededSize = frames * source.getChannels();
            samples.resize(neededSize);

            uint32_t copyFrames = 0;

            if (neededSize > 0)
            {
                if (vorbisStream->eof)
                    reset();

                data.resize(neededSize);

                int resultFrames = stb_vorbis_get_samples_float_interleaved(vorbisStream, source.getChannels(),
                                                                            data.data(), static_cast<int>(data.size()));
                copyFrames = static_cast<uint32_t>(resultFrames);

                switch (source.getChannels())
                {
                    case 1:
                        samples = data;
                        break;
                    case 2:
                        for (uint32_t frame = 0; frame < frames; ++frame)
                        {
                            samples[0 * frames + frame] = data[frame * 2 + 0];
                            samples[1 * frames + frame] = data[frame * 2 + 1];
                        }
                        break;
                    case 4:
                        for (uint32_t frame = 0; frame < frames; ++frame)
                        {
                            samples[0 * frames + frame] = data[frame * 4 + 0];
                            samples[1 * frames + frame] = data[frame * 4 + 1];
                            samples[2 * frames + frame] = data[frame * 4 + 2];
                            samples[3 * frames + frame] = data[frame * 4 + 3];
                        }
                        break;
                    case 6:
                        for (uint32_t frame = 0; frame < frames; ++frame)
                        {
                            samples[0 * frames + frame] = data[frame * 4 + 0];
                            samples[1 * frames + frame] = data[frame * 4 + 2];
                            samples[2 * frames + frame] = data[frame * 4 + 1];
                            samples[3 * frames + frame] = data[frame * 4 + 5];
                            samples[4 * frames + frame] = data[frame * 4 + 3];
                            samples[5 * frames + frame] = data[frame * 4 + 4];
                        }
                        break;
                    default:
                        throw std::runtime_error("Unsupported channel count");
                }
            }

            if (vorbisStream->eof)
            {
                playing = false; // TODO: fire event
                reset();
            }

            for (uint32_t channel = 0; channel < source.getChannels(); ++channel)
                for (uint32_t frame = copyFrames; frame < frames; ++frame)
                    samples[channel * frames + frame] = 0.0F;
        }

        VorbisClip::VorbisClip(Audio& initAudio, const std::vector<uint8_t>& initData):
            Sound(initAudio, initAudio.initSource([initData](){
                return std::unique_ptr<mixer::Source>(new VorbisData(initData));
            }))
        {
        }
    } // namespace audio
} // namespace ouzel
<commit_msg>Silence the shadowing error in VorbisClip<commit_after>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <stdexcept>
#include "VorbisClip.hpp"
#include "Audio.hpp"
#include "mixer/Stream.hpp"
#include "mixer/Source.hpp"
#include "utils/Utils.hpp"

#include "stb_vorbis.c"

namespace ouzel
{
    namespace audio
    {
        class VorbisData;

        class VorbisSource final: public mixer::Stream
        {
        public:
            VorbisSource(VorbisData& vorbisData);

            ~VorbisSource()
            {
                if (vorbisStream)
                    stb_vorbis_close(vorbisStream);
            }

            void reset() override
            {
                stb_vorbis_seek_start(vorbisStream);
            }

            void getData(uint32_t frames, std::vector<float>& samples) override;

        private:
            stb_vorbis* vorbisStream = nullptr;
            std::vector<float> data;
        };

        class VorbisData final: public mixer::Source
        {
        public:
            VorbisData(const std::vector<uint8_t>& initData):
                data(initData)
            {
                stb_vorbis* vorbisStream = stb_vorbis_open_memory(data.data(), static_cast<int>(data.size()), nullptr, nullptr);

                if (!vorbisStream)
                    throw std::runtime_error("Failed to load Vorbis stream");

                stb_vorbis_info info = stb_vorbis_get_info(vorbisStream);

                channels = static_cast<uint16_t>(info.channels);
                sampleRate = info.sample_rate;

                stb_vorbis_close(vorbisStream);
            }

            const std::vector<uint8_t>& getData() const { return data; }

            std::unique_ptr<mixer::Stream> createStream() override
            {
                return std::unique_ptr<mixer::Stream>(new VorbisSource(*this));
            }

        private:
            std::vector<uint8_t> data;
        };

        VorbisSource::VorbisSource(VorbisData& vorbisData):
            Stream(vorbisData)
        {
            vorbisStream = stb_vorbis_open_memory(vorbisData.getData().data(),
                                                  static_cast<int>(vorbisData.getData().size()),
                                                  nullptr, nullptr);
        }

        void VorbisSource::getData(uint32_t frames, std::vector<float>& samples)
        {
            uint32_t neededSize = frames * source.getChannels();
            samples.resize(neededSize);

            uint32_t copyFrames = 0;

            if (neededSize > 0)
            {
                if (vorbisStream->eof)
                    reset();

                data.resize(neededSize);

                int resultFrames = stb_vorbis_get_samples_float_interleaved(vorbisStream, source.getChannels(),
                                                                            data.data(), static_cast<int>(data.size()));
                copyFrames = static_cast<uint32_t>(resultFrames);

                switch (source.getChannels())
                {
                    case 1:
                        samples = data;
                        break;
                    case 2:
                        for (uint32_t frame = 0; frame < frames; ++frame)
                        {
                            samples[0 * frames + frame] = data[frame * 2 + 0];
                            samples[1 * frames + frame] = data[frame * 2 + 1];
                        }
                        break;
                    case 4:
                        for (uint32_t frame = 0; frame < frames; ++frame)
                        {
                            samples[0 * frames + frame] = data[frame * 4 + 0];
                            samples[1 * frames + frame] = data[frame * 4 + 1];
                            samples[2 * frames + frame] = data[frame * 4 + 2];
                            samples[3 * frames + frame] = data[frame * 4 + 3];
                        }
                        break;
                    case 6:
                        for (uint32_t frame = 0; frame < frames; ++frame)
                        {
                            samples[0 * frames + frame] = data[frame * 4 + 0];
                            samples[1 * frames + frame] = data[frame * 4 + 2];
                            samples[2 * frames + frame] = data[frame * 4 + 1];
                            samples[3 * frames + frame] = data[frame * 4 + 5];
                            samples[4 * frames + frame] = data[frame * 4 + 3];
                            samples[5 * frames + frame] = data[frame * 4 + 4];
                        }
                        break;
                    default:
                        throw std::runtime_error("Unsupported channel count");
                }
            }

            if (vorbisStream->eof)
            {
                playing = false; // TODO: fire event
                reset();
            }

            for (uint32_t channel = 0; channel < source.getChannels(); ++channel)
                for (uint32_t frame = copyFrames; frame < frames; ++frame)
                    samples[channel * frames + frame] = 0.0F;
        }

        VorbisClip::VorbisClip(Audio& initAudio, const std::vector<uint8_t>& initData):
            Sound(initAudio, initAudio.initSource([initData](){
                return std::unique_ptr<mixer::Source>(new VorbisData(initData));
            }))
        {
        }
    } // namespace audio
} // namespace ouzel
<|endoftext|>


<commit_before>// Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#include <pegtl.hh>

namespace modulus
{
   template< unsigned M, unsigned R = 0 >
   struct my_rule
   {
      static_assert( M > 1, "Modulus must be greater than 1" );
      static_assert( R < M, "Remainder must be less than modulus" );

      static bool match( pegtl::input & in )
      {
         if ( in.size() ) {
            if ( ( ( * in.begin() ) % M ) == R ) {
               in.bump( 1 );
               return true;
            }
         }
         return false;
      }
   };

   struct grammar
         : pegtl::until< pegtl::eolf, my_rule< 3 > > {};
}

int main( int argc, char * argv[] )
{
   if ( argc > 1 ) {
      pegtl::parse< modulus::grammar >( 1, argv );
   }
   return 0;
}
<commit_msg>Work-around for Clang<commit_after>// Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#include <pegtl.hh>

namespace modulus
{
   template< unsigned M, unsigned R = 0 >
   struct my_rule
   {
      static_assert( M > 1, "Modulus must be greater than 1" );
      static_assert( R < M, "Remainder must be less than modulus" );

      template< typename Input >
      static bool match( Input & in )
      {
         if ( in.size() ) {
            if ( ( ( * in.begin() ) % M ) == R ) {
               in.bump( 1 );
               return true;
            }
         }
         return false;
      }
   };

   struct grammar
         : pegtl::until< pegtl::eolf, my_rule< 3 > > {};
}

int main( int argc, char * argv[] )
{
   if ( argc > 1 ) {
      pegtl::parse< modulus::grammar >( 1, argv );
   }
   return 0;
}
<|endoftext|>


<commit_before>#include "includes.h"

#ifndef _WIN32
#include <sys/types.h>
#include <dirent.h>
#endif

void prepare_logdir()
{
    spdlog::drop_all();
#ifdef _WIN32
    system("if not exist logs mkdir logs");
    system("del /F /Q logs\\*");
#else
    auto rv = system("mkdir -p logs");
    if (rv != 0)
    {
        throw std::runtime_error("Failed to mkdir -p logs");
    }
    rv = system("rm -f logs/*");
    if (rv != 0)
    {
        throw std::runtime_error("Failed to rm -f logs/*");
    }
#endif
}

std::string file_contents(const std::string &filename)
{
    std::ifstream ifs(filename);
    if (!ifs)
    {
        throw std::runtime_error("Failed open file ");
    }
    return std::string((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
}

std::size_t count_lines(const std::string &filename)
{
    std::ifstream ifs(filename);
    if (!ifs)
    {
        throw std::runtime_error("Failed open file ");
    }

    std::string line;
    size_t counter = 0;
    while (std::getline(ifs, line))
        counter++;
    return counter;
}

std::size_t get_filesize(const std::string &filename)
{
    std::ifstream ifs(filename, std::ifstream::ate | std::ifstream::binary);
    if (!ifs)
    {
        throw std::runtime_error("Failed open file ");
    }

    return static_cast<std::size_t>(ifs.tellg());
}

// source: https://stackoverflow.com/a/2072890/192001
bool ends_with(std::string const &value, std::string const &ending)
{
    if (ending.size() > value.size())
    {
        return false;
    }
    return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}

#ifdef _WIN32
// Based on: https://stackoverflow.com/a/37416569/192001
std::size_t count_files(const std::string &folder)
{
    size_t counter = 0;
    WIN32_FIND_DATA ffd;
    HANDLE hFind = INVALID_HANDLE_VALUE;

    // Start iterating over the files in the path directory.
    hFind = ::FindFirstFileA((folder + "\\*").c_str(), &ffd);
    if (hFind != INVALID_HANDLE_VALUE)
    {
        do // Managed to locate and create an handle to that folder.
        {
             if (ffd.cFileName[0] != '.')
                counter++;
        } while (::FindNextFile(hFind, &ffd) == TRUE);
        ::FindClose(hFind);
    }
    else
    {
        throw std::runtime_error("Failed open folder " + folder);
    }

    return counter;
}
#else
// Based on: https://stackoverflow.com/a/2802255/192001
std::size_t count_files(const std::string &folder)
{
    size_t counter = 0;
    DIR *dp = opendir(folder.c_str());
    if (dp == nullptr)
    {
        throw std::runtime_error("Failed open folder " + folder);
    }

    struct dirent *ep;
    while (ep = readdir(dp))
    {
        if (ep->d_name[0] != '.')
            counter++;
    }
    (void)closedir(dp);
    return counter;
}
#endif
<commit_msg>Update tests utils<commit_after>#include "includes.h"

#ifndef _WIN32
#include <sys/types.h>
#include <dirent.h>
#endif

void prepare_logdir()
{
    spdlog::drop_all();
#ifdef _WIN32
    system("if not exist logs mkdir logs");
    system("del /F /Q logs\\*");
#else
    auto rv = system("mkdir -p logs");
    if (rv != 0)
    {
        throw std::runtime_error("Failed to mkdir -p logs");
    }
    rv = system("rm -f logs/*");
    if (rv != 0)
    {
        throw std::runtime_error("Failed to rm -f logs/*");
    }
#endif
}

std::string file_contents(const std::string &filename)
{
    std::ifstream ifs(filename);
    if (!ifs)
    {
        throw std::runtime_error("Failed open file ");
    }
    return std::string((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
}

std::size_t count_lines(const std::string &filename)
{
    std::ifstream ifs(filename);
    if (!ifs)
    {
        throw std::runtime_error("Failed open file ");
    }

    std::string line;
    size_t counter = 0;
    while (std::getline(ifs, line))
        counter++;
    return counter;
}

std::size_t get_filesize(const std::string &filename)
{
    std::ifstream ifs(filename, std::ifstream::ate | std::ifstream::binary);
    if (!ifs)
    {
        throw std::runtime_error("Failed open file ");
    }

    return static_cast<std::size_t>(ifs.tellg());
}

// source: https://stackoverflow.com/a/2072890/192001
bool ends_with(std::string const &value, std::string const &ending)
{
    if (ending.size() > value.size())
    {
        return false;
    }
    return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}

#ifdef _WIN32
// Based on: https://stackoverflow.com/a/37416569/192001
std::size_t count_files(const std::string &folder)
{
    size_t counter = 0;
    WIN32_FIND_DATA ffd;
    HANDLE hFind = INVALID_HANDLE_VALUE;

    // Start iterating over the files in the path directory.
    hFind = ::FindFirstFileA((folder + "\\*").c_str(), &ffd);
    if (hFind != INVALID_HANDLE_VALUE)
    {
        do // Managed to locate and create an handle to that folder.
        {
             if (ffd.cFileName[0] != '.')
                counter++;
        } while (::FindNextFile(hFind, &ffd) != 0);
        ::FindClose(hFind);
    }
    else
    {
        throw std::runtime_error("Failed open folder " + folder);
    }

    return counter;
}
#else
// Based on: https://stackoverflow.com/a/2802255/192001
std::size_t count_files(const std::string &folder)
{
    size_t counter = 0;
    DIR *dp = opendir(folder.c_str());
    if (dp == nullptr)
    {
        throw std::runtime_error("Failed open folder " + folder);
    }

    struct dirent *ep;
    while (ep = readdir(dp))
    {
        if (ep->d_name[0] != '.')
            counter++;
    }
    (void)closedir(dp);
    return counter;
}
#endif
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <iostream>
#include <sstream>

#include <osquery/core.h>

#include "osquery/devtools/devtools.h"

namespace osquery {

std::string generateToken(const std::map<std::string, size_t>& lengths,
                          const std::vector<std::string>& columns) {
  std::string output = "+";
  for (const auto& col : columns) {
    if (lengths.count(col) > 0) {
      output += std::string(lengths.at(col) + 2, '-');
    }
    output += "+";
  }

  output += "\n";
  return output;
}

std::string generateHeader(const std::map<std::string, size_t>& lengths,
                           const std::vector<std::string>& columns) {
  std::string output = "|";
  for (const auto& col : columns) {
    output += " " + col;
    if (lengths.count(col) > 0) {
      int buffer_size = lengths.at(col) - utf8StringSize(col) + 1;
      if (buffer_size > 0) {
        output += std::string(buffer_size, ' ');
      } else {
        output += ' ';
      }
    }
    output += "|";
  }
  output += "\n";
  return output;
}

std::string generateRow(const Row& r,
                        const std::map<std::string, size_t>& lengths,
                        const std::vector<std::string>& order) {
  std::string output;
  for (const auto& column : order) {
    if (r.count(column) == 0 || lengths.count(column) == 0) {
      continue;
    }
    // Print a terminator for the previous value or lhs, followed by spaces.

    int buffer_size = lengths.at(column) - utf8StringSize(r.at(column)) + 1;
    if (buffer_size > 0) {
      output += "| " + r.at(column) + std::string(buffer_size, ' ');
    }
  }

  if (output.size() > 0) {
    // Only append if a row was added.
    output += "|\n";
  }

  return output;
}

void prettyPrint(const QueryData& results,
                 const std::vector<std::string>& columns,
                 std::map<std::string, size_t>& lengths) {
  if (results.size() == 0) {
    return;
  }

  // Call a final compute using the column names as minimum lengths.
  computeRowLengths(results.front(), lengths, true);

  // Output a nice header wrapping the column names.
  auto separator = generateToken(lengths, columns);
  auto header = separator + generateHeader(lengths, columns) + separator;
  printf("%s", header.c_str());

  // Iterate each row and pretty print.
  for (const auto& row : results) {
    printf("%s", generateRow(row, lengths, columns).c_str());
  }
  printf("%s", separator.c_str());
}

void jsonPrint(const QueryData& q) {
  printf("[\n");
  for (int i = 0; i < q.size(); ++i) {
    std::string row_string;
    if (serializeRowJSON(q[i], row_string).ok()) {
      row_string.pop_back();
      printf("  %s", row_string.c_str());
      if (i < q.size() - 1) {
        printf(",\n");
      }
    }
  }
  printf("\n]\n");
}

void computeRowLengths(const Row& r,
                       std::map<std::string, size_t>& lengths,
                       bool use_columns) {
  for (const auto& col : r) {
    size_t current = (lengths.count(col.first) > 0) ? lengths.at(col.first) : 0;
    size_t size =
        (use_columns) ? utf8StringSize(col.first) : utf8StringSize(col.second);
    lengths[col.first] = (size > current) ? size : current;
  }
}
}
<commit_msg>Fix small issue with printing<commit_after>/*
 *  Copyright (c) 2014, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <iostream>
#include <sstream>

#include <osquery/core.h>

#include "osquery/devtools/devtools.h"

namespace osquery {

static std::vector<size_t> kOffset = {0, 0};
static std::string kToken = "|";

std::string generateToken(const std::map<std::string, size_t>& lengths,
                          const std::vector<std::string>& columns) {
  std::string out = "+";
  for (const auto& col : columns) {
    if (lengths.count(col) > 0) {
      if (getenv("ENHANCE") != nullptr) {
        std::string e = "\xF0\x9F\x90\x8C";
        e[2] += kOffset[1];
        e[3] += kOffset[0];
        for (int i = 0; i < lengths.at(col) + 2; i++) {
          e[3] = '\x8c' + kOffset[0]++;
          if (e[3] == '\xbf') {
            e[3] = '\x80';
            kOffset[1] = (kOffset[1] > 3 && kOffset[1] < 8) ? 9 : kOffset[1];
            e[2] = '\x90' + ++kOffset[1];
            kOffset[0] = 0;
          }
          if (kOffset[1] == ('\x97' - '\x8d')) {
            kOffset = {0, 0};
          }
          out += e.c_str();
        }
      } else {
        out += std::string(lengths.at(col) + 2, '-');
      }
    }
    out += "+";
  }

  out += "\n";
  return out;
}

std::string generateHeader(const std::map<std::string, size_t>& lengths,
                           const std::vector<std::string>& columns) {
  if (getenv("ENHANCE") != nullptr) {
    kToken = "\xF0\x9F\x91\x8D";
  }
  std::string out = kToken;
  for (const auto& col : columns) {
    out += " " + col;
    if (lengths.count(col) > 0) {
      int buffer_size = lengths.at(col) - utf8StringSize(col) + 1;
      if (buffer_size > 0) {
        out += std::string(buffer_size, ' ');
      } else {
        out += ' ';
      }
    }
    out += kToken;
  }
  out += "\n";
  return out;
}

std::string generateRow(const Row& r,
                        const std::map<std::string, size_t>& lengths,
                        const std::vector<std::string>& order) {
  std::string out;
  for (const auto& column : order) {
    if (r.count(column) == 0 || lengths.count(column) == 0) {
      continue;
    }
    // Print a terminator for the previous value or lhs, followed by spaces.

    int buffer_size = lengths.at(column) - utf8StringSize(r.at(column)) + 1;
    if (buffer_size > 0) {
      out += kToken + " " + r.at(column) + std::string(buffer_size, ' ');
    }
  }

  if (out.size() > 0) {
    // Only append if a row was added.
    out += kToken + "\n";
  }

  return out;
}

void prettyPrint(const QueryData& results,
                 const std::vector<std::string>& columns,
                 std::map<std::string, size_t>& lengths) {
  if (results.size() == 0) {
    return;
  }

  // Call a final compute using the column names as minimum lengths.
  computeRowLengths(results.front(), lengths, true);

  // Output a nice header wrapping the column names.
  auto separator = generateToken(lengths, columns);
  auto header = separator + generateHeader(lengths, columns) + separator;
  printf("%s", header.c_str());

  // Iterate each row and pretty print.
  for (const auto& row : results) {
    printf("%s", generateRow(row, lengths, columns).c_str());
  }
  printf("%s", separator.c_str());
}

void jsonPrint(const QueryData& q) {
  printf("[\n");
  for (int i = 0; i < q.size(); ++i) {
    std::string row_string;
    if (serializeRowJSON(q[i], row_string).ok()) {
      row_string.pop_back();
      printf("  %s", row_string.c_str());
      if (i < q.size() - 1) {
        printf(",\n");
      }
    }
  }
  printf("\n]\n");
}

void computeRowLengths(const Row& r,
                       std::map<std::string, size_t>& lengths,
                       bool use_columns) {
  for (const auto& col : r) {
    size_t current = (lengths.count(col.first) > 0) ? lengths.at(col.first) : 0;
    size_t size =
        (use_columns) ? utf8StringSize(col.first) : utf8StringSize(col.second);
    lengths[col.first] = (size > current) ? size : current;
  }
}
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2016                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/actor_system.hpp"

#include <unordered_set>

#include "caf/send.hpp"
#include "caf/to_string.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/actor_system_config.hpp"

#include "caf/policy/work_sharing.hpp"
#include "caf/policy/work_stealing.hpp"

#include "caf/scheduler/coordinator.hpp"
#include "caf/scheduler/abstract_coordinator.hpp"
#include "caf/scheduler/profiled_coordinator.hpp"

namespace caf {

namespace {

struct kvstate {
  using key_type = std::string;
  using mapped_type = message;
  using subscriber_set = std::unordered_set<strong_actor_ptr>;
  using topic_set = std::unordered_set<std::string>;
  std::unordered_map<key_type, std::pair<mapped_type, subscriber_set>> data;
  std::unordered_map<strong_actor_ptr, topic_set> subscribers;
  static const char* name;
  template <class Processor>
  friend void serialize(Processor& proc, kvstate& x, const unsigned int) {
    proc & x.data;
    proc & x.subscribers;
  }
};

const char* kvstate::name = "caf.config_server";

behavior config_serv_impl(stateful_actor<kvstate>* self) {
  CAF_LOG_TRACE("");
  std::string wildcard = "*";
  auto unsubscribe_all = [=](actor subscriber) {
    auto& subscribers = self->state.subscribers;
    auto ptr = actor_cast<strong_actor_ptr>(subscriber);
    auto i = subscribers.find(ptr);
    if (i == subscribers.end())
      return;
    for (auto& key : i->second)
      self->state.data[key].second.erase(ptr);
    subscribers.erase(i);
  };
  self->set_down_handler([=](down_msg& dm) {
    CAF_LOG_TRACE(CAF_ARG(dm));
    auto ptr = actor_cast<strong_actor_ptr>(dm.source);
    if (ptr)
      unsubscribe_all(actor_cast<actor>(std::move(ptr)));
  });
  return {
    // set a key/value pair
    [=](put_atom, const std::string& key, message& msg) {
      CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(msg));
      if (key == "*")
        return;
      auto& vp = self->state.data[key];
      vp.first = std::move(msg);
      for (auto& subscriber_ptr : vp.second) {
        // we never put a nullptr in our map
        auto subscriber = actor_cast<actor>(subscriber_ptr);
        if (subscriber != self->current_sender())
          self->send(subscriber, update_atom::value, key, vp.second);
      }
      // also iterate all subscribers for '*'
      for (auto& subscriber : self->state.data[wildcard].second)
        if (subscriber != self->current_sender())
          self->send(actor_cast<actor>(subscriber), update_atom::value,
                     key, vp.second);
    },
    // get a key/value pair
    [=](get_atom, std::string& key) -> message {
      CAF_LOG_TRACE(CAF_ARG(key));
      if (key == wildcard) {
        std::vector<std::pair<std::string, message>> msgs;
        for (auto& kvp : self->state.data)
          if (kvp.first != "*")
            msgs.emplace_back(kvp.first, kvp.second.first);
        return make_message(std::move(msgs));
      }
      auto i = self->state.data.find(key);
      return make_message(std::move(key),
                          i != self->state.data.end() ? i->second.first
                                                      : make_message());
    },
    // subscribe to a key
    [=](subscribe_atom, const std::string& key) {
      auto subscriber = actor_cast<strong_actor_ptr>(self->current_sender());
      CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(subscriber));
      if (!subscriber)
        return;
      self->state.data[key].second.insert(subscriber);
      auto& subscribers = self->state.subscribers;
      auto i = subscribers.find(subscriber);
      if (i != subscribers.end()) {
        i->second.insert(key);
      } else {
        self->monitor(subscriber);
        subscribers.emplace(subscriber, kvstate::topic_set{key});
      }
    },
    // unsubscribe from a key
    [=](unsubscribe_atom, const std::string& key) {
      auto subscriber = actor_cast<strong_actor_ptr>(self->current_sender());
      if (!subscriber)
        return;
      CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(subscriber));
      if (key == wildcard) {
        unsubscribe_all(actor_cast<actor>(std::move(subscriber)));
        return;
      }
      self->state.subscribers[subscriber].erase(key);
      self->state.data[key].second.erase(subscriber);
    },
    // get a 'named' actor from local registry
    [=](get_atom, atom_value name) {
      return self->home_system().registry().get(name);
    }
  };
}

behavior spawn_serv_impl(event_based_actor* self) {
  CAF_LOG_TRACE("");
  return {
    [=](spawn_atom, const std::string& name,
        message& args, actor_system::mpi& xs)
    -> expected<strong_actor_ptr> {
      CAF_LOG_TRACE(CAF_ARG(name) << CAF_ARG(args));
      return self->system().spawn<strong_actor_ptr>(name, std::move(args),
                                                    self->context(), true, &xs);
    }
  };
}

class dropping_execution_unit : public execution_unit {
public:
  dropping_execution_unit(actor_system* sys) : execution_unit(sys) {
    // nop
  }

  void exec_later(resumable*) override {
    // should not happen in the first place
    CAF_LOG_ERROR("actor registry actor called exec_later during shutdown");
  }
};

} // namespace <anonymous>

actor_system::module::~module() {
  // nop
}

actor_system::actor_system(actor_system_config& cfg)
    : ids_(0),
      types_(*this),
      logger_(*this),
      registry_(*this),
      groups_(*this),
      middleman_(nullptr),
      dummy_execution_unit_(this),
      await_actors_before_shutdown_(true),
      detached(0),
      cfg_(cfg) {
  CAF_SET_LOGGER_SYS(this);
  for (auto& f : cfg.module_factories) {
    auto mod_ptr = f(*this);
    modules_[mod_ptr->id()].reset(mod_ptr);
  }
  auto& mmptr = modules_[module::middleman];
  if (mmptr)
    middleman_ = reinterpret_cast<io::middleman*>(mmptr->subtype_ptr());
  auto& clptr = modules_[module::opencl_manager];
  if (clptr)
    opencl_manager_ = reinterpret_cast<opencl::manager*>(clptr->subtype_ptr());
  auto& sched = modules_[module::scheduler];
  using share = scheduler::coordinator<policy::work_sharing>;
  using steal = scheduler::coordinator<policy::work_stealing>;
  using profiled_share = scheduler::profiled_coordinator<policy::work_sharing>;
  using profiled_steal = scheduler::profiled_coordinator<policy::work_stealing>;
  // set scheduler only if not explicitly loaded by user
  if (!sched) {
    enum sched_conf {
      stealing          = 0x0001,
      sharing           = 0x0002,
      profiled          = 0x0100,
      profiled_stealing = 0x0101,
      profiled_sharing  = 0x0102
    };
    sched_conf sc = stealing;
    if (cfg.scheduler_policy == atom("sharing"))
      sc = sharing;
    else if (cfg.scheduler_policy != atom("stealing"))
      std::cerr << "[WARNING] " << deep_to_string(cfg.scheduler_policy)
                << " is an unrecognized scheduler pollicy, "
                   "falling back to 'stealing' (i.e. work-stealing)"
                << std::endl;
    if (cfg.scheduler_enable_profiling)
      sc = static_cast<sched_conf>(sc | profiled);
    switch (sc) {
      default: // any invalid configuration falls back to work stealing
        sched.reset(new steal(*this));
        break;
      case sharing:
        sched.reset(new share(*this));
        break;
      case profiled_stealing:
        sched.reset(new profiled_steal(*this));
        break;
      case profiled_sharing:
        sched.reset(new profiled_share(*this));
        break;
    }
  }
  // initialize state for each module and give each module the opportunity
  // to influence the system configuration, e.g., by adding more types
  for (auto& mod : modules_)
    if (mod)
      mod->init(cfg);
  groups_.init(cfg);
  // spawn config and spawn servers (lazily to not access the scheduler yet)
  static constexpr auto Flags = hidden + lazy_init;
  spawn_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(spawn_serv_impl));
  config_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(config_serv_impl));
  // fire up remaining modules
  logger_.start();
  registry_.start();
  registry_.put(atom("SpawnServ"), spawn_serv_);
  registry_.put(atom("ConfigServ"), config_serv_);
  for (auto& mod : modules_)
    if (mod)
      mod->start();
  groups_.start();
}

actor_system::~actor_system() {
  if (await_actors_before_shutdown_)
    await_all_actors_done();
  // shutdown system-level servers
  anon_send_exit(spawn_serv_, exit_reason::user_shutdown);
  anon_send_exit(config_serv_, exit_reason::user_shutdown);
  // release memory as soon as possible
  spawn_serv_ = nullptr;
  config_serv_ = nullptr;
  registry_.erase(atom("SpawnServ"));
  registry_.erase(atom("ConfigServ"));
  // group module is the first one, relies on MM
  groups_.stop();
  // stop modules in reverse order
  for (auto i = modules_.rbegin(); i != modules_.rend(); ++i)
    if (*i)
      (*i)->stop();
  await_detached_threads();
  registry_.stop();
  logger_.stop();
  CAF_SET_LOGGER_SYS(nullptr);
}

/// Returns the host-local identifier for this system.
const node_id& actor_system::node() const {
  return node_;
}

/// Returns the scheduler instance.
scheduler::abstract_coordinator& actor_system::scheduler() {
  using ptr = scheduler::abstract_coordinator*;
  return *static_cast<ptr>(modules_[module::scheduler].get());
}

caf::logger& actor_system::logger() {
  return logger_;
}

actor_registry& actor_system::registry() {
  return registry_;
}

const uniform_type_info_map& actor_system::types() const {
  return types_;
}

std::string actor_system::render(const error& x) const {
  if (!x)
    return to_string(x);
  auto& xs = config().error_renderers;
  auto i = xs.find(x.category());
  if (i != xs.end())
    return i->second(x.code(), x.category(), x.context());
  return to_string(x);
}

group_manager& actor_system::groups() {
  return groups_;
}

bool actor_system::has_middleman() const {
  return middleman_ != nullptr;
}

io::middleman& actor_system::middleman() {
  if (!middleman_)
    CAF_RAISE_ERROR("cannot access middleman: module not loaded");
  return *middleman_;
}

bool actor_system::has_opencl_manager() const {
  return opencl_manager_ != nullptr;
}

opencl::manager& actor_system::opencl_manager() const {
  if (!opencl_manager_)
    CAF_RAISE_ERROR("cannot access opencl manager: module not loaded");
  return *opencl_manager_;
}

scoped_execution_unit* actor_system::dummy_execution_unit() {
  return &dummy_execution_unit_;
}

actor_id actor_system::next_actor_id() {
  return ++ids_;
}

actor_id actor_system::latest_actor_id() const {
  return ids_.load();
}

void actor_system::await_all_actors_done() const {
  registry_.await_running_count_equal(0);
}

void actor_system::inc_detached_threads() {
  ++detached;
}

void actor_system::dec_detached_threads() {
  if (--detached == 0) {
    std::unique_lock<std::mutex> guard{detached_mtx};
    detached_cv.notify_all();
  }
}

void actor_system::await_detached_threads() {
  std::unique_lock<std::mutex> guard{detached_mtx};
  while (detached != 0)
    detached_cv.wait(guard);
}

expected<strong_actor_ptr>
actor_system::dyn_spawn_impl(const std::string& name, message& args,
                             execution_unit* ctx, bool check_interface,
                             optional<const mpi&> expected_ifs) {
  CAF_LOG_TRACE(CAF_ARG(name) << CAF_ARG(args) << CAF_ARG(check_interface)
                << CAF_ARG(expected_ifs));
  if (name.empty())
    return sec::invalid_argument;
  auto& fs = cfg_.actor_factories;
  auto i = fs.find(name);
  if (i == fs.end())
    return sec::unknown_type;
  actor_config cfg{ctx ? ctx : &dummy_execution_unit_};
  auto res = i->second(cfg, args);
  if (!res.first)
    return sec::cannot_spawn_actor_from_arguments;
  if (check_interface && !assignable(res.second, *expected_ifs))
    return sec::unexpected_actor_messaging_interface;
  return std::move(res.first);
}

} // namespace caf
<commit_msg>Fix potential segfault in dec_detached_threads<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2016                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/actor_system.hpp"

#include <unordered_set>

#include "caf/send.hpp"
#include "caf/to_string.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/actor_system_config.hpp"

#include "caf/policy/work_sharing.hpp"
#include "caf/policy/work_stealing.hpp"

#include "caf/scheduler/coordinator.hpp"
#include "caf/scheduler/abstract_coordinator.hpp"
#include "caf/scheduler/profiled_coordinator.hpp"

namespace caf {

namespace {

struct kvstate {
  using key_type = std::string;
  using mapped_type = message;
  using subscriber_set = std::unordered_set<strong_actor_ptr>;
  using topic_set = std::unordered_set<std::string>;
  std::unordered_map<key_type, std::pair<mapped_type, subscriber_set>> data;
  std::unordered_map<strong_actor_ptr, topic_set> subscribers;
  static const char* name;
  template <class Processor>
  friend void serialize(Processor& proc, kvstate& x, const unsigned int) {
    proc & x.data;
    proc & x.subscribers;
  }
};

const char* kvstate::name = "caf.config_server";

behavior config_serv_impl(stateful_actor<kvstate>* self) {
  CAF_LOG_TRACE("");
  std::string wildcard = "*";
  auto unsubscribe_all = [=](actor subscriber) {
    auto& subscribers = self->state.subscribers;
    auto ptr = actor_cast<strong_actor_ptr>(subscriber);
    auto i = subscribers.find(ptr);
    if (i == subscribers.end())
      return;
    for (auto& key : i->second)
      self->state.data[key].second.erase(ptr);
    subscribers.erase(i);
  };
  self->set_down_handler([=](down_msg& dm) {
    CAF_LOG_TRACE(CAF_ARG(dm));
    auto ptr = actor_cast<strong_actor_ptr>(dm.source);
    if (ptr)
      unsubscribe_all(actor_cast<actor>(std::move(ptr)));
  });
  return {
    // set a key/value pair
    [=](put_atom, const std::string& key, message& msg) {
      CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(msg));
      if (key == "*")
        return;
      auto& vp = self->state.data[key];
      vp.first = std::move(msg);
      for (auto& subscriber_ptr : vp.second) {
        // we never put a nullptr in our map
        auto subscriber = actor_cast<actor>(subscriber_ptr);
        if (subscriber != self->current_sender())
          self->send(subscriber, update_atom::value, key, vp.second);
      }
      // also iterate all subscribers for '*'
      for (auto& subscriber : self->state.data[wildcard].second)
        if (subscriber != self->current_sender())
          self->send(actor_cast<actor>(subscriber), update_atom::value,
                     key, vp.second);
    },
    // get a key/value pair
    [=](get_atom, std::string& key) -> message {
      CAF_LOG_TRACE(CAF_ARG(key));
      if (key == wildcard) {
        std::vector<std::pair<std::string, message>> msgs;
        for (auto& kvp : self->state.data)
          if (kvp.first != "*")
            msgs.emplace_back(kvp.first, kvp.second.first);
        return make_message(std::move(msgs));
      }
      auto i = self->state.data.find(key);
      return make_message(std::move(key),
                          i != self->state.data.end() ? i->second.first
                                                      : make_message());
    },
    // subscribe to a key
    [=](subscribe_atom, const std::string& key) {
      auto subscriber = actor_cast<strong_actor_ptr>(self->current_sender());
      CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(subscriber));
      if (!subscriber)
        return;
      self->state.data[key].second.insert(subscriber);
      auto& subscribers = self->state.subscribers;
      auto i = subscribers.find(subscriber);
      if (i != subscribers.end()) {
        i->second.insert(key);
      } else {
        self->monitor(subscriber);
        subscribers.emplace(subscriber, kvstate::topic_set{key});
      }
    },
    // unsubscribe from a key
    [=](unsubscribe_atom, const std::string& key) {
      auto subscriber = actor_cast<strong_actor_ptr>(self->current_sender());
      if (!subscriber)
        return;
      CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(subscriber));
      if (key == wildcard) {
        unsubscribe_all(actor_cast<actor>(std::move(subscriber)));
        return;
      }
      self->state.subscribers[subscriber].erase(key);
      self->state.data[key].second.erase(subscriber);
    },
    // get a 'named' actor from local registry
    [=](get_atom, atom_value name) {
      return self->home_system().registry().get(name);
    }
  };
}

behavior spawn_serv_impl(event_based_actor* self) {
  CAF_LOG_TRACE("");
  return {
    [=](spawn_atom, const std::string& name,
        message& args, actor_system::mpi& xs)
    -> expected<strong_actor_ptr> {
      CAF_LOG_TRACE(CAF_ARG(name) << CAF_ARG(args));
      return self->system().spawn<strong_actor_ptr>(name, std::move(args),
                                                    self->context(), true, &xs);
    }
  };
}

class dropping_execution_unit : public execution_unit {
public:
  dropping_execution_unit(actor_system* sys) : execution_unit(sys) {
    // nop
  }

  void exec_later(resumable*) override {
    // should not happen in the first place
    CAF_LOG_ERROR("actor registry actor called exec_later during shutdown");
  }
};

} // namespace <anonymous>

actor_system::module::~module() {
  // nop
}

actor_system::actor_system(actor_system_config& cfg)
    : ids_(0),
      types_(*this),
      logger_(*this),
      registry_(*this),
      groups_(*this),
      middleman_(nullptr),
      dummy_execution_unit_(this),
      await_actors_before_shutdown_(true),
      detached(0),
      cfg_(cfg) {
  CAF_SET_LOGGER_SYS(this);
  for (auto& f : cfg.module_factories) {
    auto mod_ptr = f(*this);
    modules_[mod_ptr->id()].reset(mod_ptr);
  }
  auto& mmptr = modules_[module::middleman];
  if (mmptr)
    middleman_ = reinterpret_cast<io::middleman*>(mmptr->subtype_ptr());
  auto& clptr = modules_[module::opencl_manager];
  if (clptr)
    opencl_manager_ = reinterpret_cast<opencl::manager*>(clptr->subtype_ptr());
  auto& sched = modules_[module::scheduler];
  using share = scheduler::coordinator<policy::work_sharing>;
  using steal = scheduler::coordinator<policy::work_stealing>;
  using profiled_share = scheduler::profiled_coordinator<policy::work_sharing>;
  using profiled_steal = scheduler::profiled_coordinator<policy::work_stealing>;
  // set scheduler only if not explicitly loaded by user
  if (!sched) {
    enum sched_conf {
      stealing          = 0x0001,
      sharing           = 0x0002,
      profiled          = 0x0100,
      profiled_stealing = 0x0101,
      profiled_sharing  = 0x0102
    };
    sched_conf sc = stealing;
    if (cfg.scheduler_policy == atom("sharing"))
      sc = sharing;
    else if (cfg.scheduler_policy != atom("stealing"))
      std::cerr << "[WARNING] " << deep_to_string(cfg.scheduler_policy)
                << " is an unrecognized scheduler pollicy, "
                   "falling back to 'stealing' (i.e. work-stealing)"
                << std::endl;
    if (cfg.scheduler_enable_profiling)
      sc = static_cast<sched_conf>(sc | profiled);
    switch (sc) {
      default: // any invalid configuration falls back to work stealing
        sched.reset(new steal(*this));
        break;
      case sharing:
        sched.reset(new share(*this));
        break;
      case profiled_stealing:
        sched.reset(new profiled_steal(*this));
        break;
      case profiled_sharing:
        sched.reset(new profiled_share(*this));
        break;
    }
  }
  // initialize state for each module and give each module the opportunity
  // to influence the system configuration, e.g., by adding more types
  for (auto& mod : modules_)
    if (mod)
      mod->init(cfg);
  groups_.init(cfg);
  // spawn config and spawn servers (lazily to not access the scheduler yet)
  static constexpr auto Flags = hidden + lazy_init;
  spawn_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(spawn_serv_impl));
  config_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(config_serv_impl));
  // fire up remaining modules
  logger_.start();
  registry_.start();
  registry_.put(atom("SpawnServ"), spawn_serv_);
  registry_.put(atom("ConfigServ"), config_serv_);
  for (auto& mod : modules_)
    if (mod)
      mod->start();
  groups_.start();
}

actor_system::~actor_system() {
  if (await_actors_before_shutdown_)
    await_all_actors_done();
  // shutdown system-level servers
  anon_send_exit(spawn_serv_, exit_reason::user_shutdown);
  anon_send_exit(config_serv_, exit_reason::user_shutdown);
  // release memory as soon as possible
  spawn_serv_ = nullptr;
  config_serv_ = nullptr;
  registry_.erase(atom("SpawnServ"));
  registry_.erase(atom("ConfigServ"));
  // group module is the first one, relies on MM
  groups_.stop();
  // stop modules in reverse order
  for (auto i = modules_.rbegin(); i != modules_.rend(); ++i)
    if (*i)
      (*i)->stop();
  await_detached_threads();
  registry_.stop();
  logger_.stop();
  CAF_SET_LOGGER_SYS(nullptr);
}

/// Returns the host-local identifier for this system.
const node_id& actor_system::node() const {
  return node_;
}

/// Returns the scheduler instance.
scheduler::abstract_coordinator& actor_system::scheduler() {
  using ptr = scheduler::abstract_coordinator*;
  return *static_cast<ptr>(modules_[module::scheduler].get());
}

caf::logger& actor_system::logger() {
  return logger_;
}

actor_registry& actor_system::registry() {
  return registry_;
}

const uniform_type_info_map& actor_system::types() const {
  return types_;
}

std::string actor_system::render(const error& x) const {
  if (!x)
    return to_string(x);
  auto& xs = config().error_renderers;
  auto i = xs.find(x.category());
  if (i != xs.end())
    return i->second(x.code(), x.category(), x.context());
  return to_string(x);
}

group_manager& actor_system::groups() {
  return groups_;
}

bool actor_system::has_middleman() const {
  return middleman_ != nullptr;
}

io::middleman& actor_system::middleman() {
  if (!middleman_)
    CAF_RAISE_ERROR("cannot access middleman: module not loaded");
  return *middleman_;
}

bool actor_system::has_opencl_manager() const {
  return opencl_manager_ != nullptr;
}

opencl::manager& actor_system::opencl_manager() const {
  if (!opencl_manager_)
    CAF_RAISE_ERROR("cannot access opencl manager: module not loaded");
  return *opencl_manager_;
}

scoped_execution_unit* actor_system::dummy_execution_unit() {
  return &dummy_execution_unit_;
}

actor_id actor_system::next_actor_id() {
  return ++ids_;
}

actor_id actor_system::latest_actor_id() const {
  return ids_.load();
}

void actor_system::await_all_actors_done() const {
  registry_.await_running_count_equal(0);
}

void actor_system::inc_detached_threads() {
  ++detached;
}

void actor_system::dec_detached_threads() {
  std::unique_lock<std::mutex> guard{detached_mtx};
  if (--detached == 0)
    detached_cv.notify_all();
}

void actor_system::await_detached_threads() {
  std::unique_lock<std::mutex> guard{detached_mtx};
  while (detached != 0)
    detached_cv.wait(guard);
}

expected<strong_actor_ptr>
actor_system::dyn_spawn_impl(const std::string& name, message& args,
                             execution_unit* ctx, bool check_interface,
                             optional<const mpi&> expected_ifs) {
  CAF_LOG_TRACE(CAF_ARG(name) << CAF_ARG(args) << CAF_ARG(check_interface)
                << CAF_ARG(expected_ifs));
  if (name.empty())
    return sec::invalid_argument;
  auto& fs = cfg_.actor_factories;
  auto i = fs.find(name);
  if (i == fs.end())
    return sec::unknown_type;
  actor_config cfg{ctx ? ctx : &dummy_execution_unit_};
  auto res = i->second(cfg, args);
  if (!res.first)
    return sec::cannot_spawn_actor_from_arguments;
  if (check_interface && !assignable(res.second, *expected_ifs))
    return sec::unexpected_actor_messaging_interface;
  return std::move(res.first);
}

} // namespace caf
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2014                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/detail/message_data.hpp"

namespace caf {
namespace detail {

message_data::message_data() {
  // nop
}

bool message_data::equals(const message_data& other) const {
  if (this == &other) {
    return true;
  }
  auto n = size();
  if (n != other.size()) {
    return false;
  }
  // step 1, get and compare type names
  std::vector<const char*> type_names;
  for (size_t i = 0; i < n; ++i) {
    auto lhs = uniform_name_at(i);
    auto rhs = other.uniform_name_at(i);
    if (lhs != rhs && strcmp(lhs, rhs) != 0) {
      return false; // type mismatch
    }
    type_names.push_back(lhs);
  }
  // step 2: compare each value individually
  for (size_t i = 0; i < n; ++i) {
    auto uti = uniform_type_info::from(type_names[i]);
    if (!uti->equals(at(i), other.at(i))) {
      return false;
    }
  }
  return true;
}

const void* message_data::native_data() const {
  return nullptr;
}

void* message_data::mutable_native_data() {
  return nullptr;
}

std::string message_data::tuple_type_names() const {
  std::string result = "@<>";
  for (size_t i = 0; i < size(); ++i) {
    result += "+";
    result += uniform_name_at(i);
  }
  return result;
}

message_data* message_data::ptr::get_detached() {
  auto p = m_ptr.get();
  if (!p->unique()) {
    auto np = p->copy();
    m_ptr.reset(np);
    return np;
  }
  return p;
}

} // namespace detail
} // namespace caf
<commit_msg>Add missing include<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2014                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/detail/message_data.hpp"

#include <cstring>

namespace caf {
namespace detail {

message_data::message_data() {
  // nop
}

bool message_data::equals(const message_data& other) const {
  if (this == &other) {
    return true;
  }
  auto n = size();
  if (n != other.size()) {
    return false;
  }
  // step 1, get and compare type names
  std::vector<const char*> type_names;
  for (size_t i = 0; i < n; ++i) {
    auto lhs = uniform_name_at(i);
    auto rhs = other.uniform_name_at(i);
    if (lhs != rhs && strcmp(lhs, rhs) != 0) {
      return false; // type mismatch
    }
    type_names.push_back(lhs);
  }
  // step 2: compare each value individually
  for (size_t i = 0; i < n; ++i) {
    auto uti = uniform_type_info::from(type_names[i]);
    if (!uti->equals(at(i), other.at(i))) {
      return false;
    }
  }
  return true;
}

const void* message_data::native_data() const {
  return nullptr;
}

void* message_data::mutable_native_data() {
  return nullptr;
}

std::string message_data::tuple_type_names() const {
  std::string result = "@<>";
  for (size_t i = 0; i < size(); ++i) {
    result += "+";
    result += uniform_name_at(i);
  }
  return result;
}

message_data* message_data::ptr::get_detached() {
  auto p = m_ptr.get();
  if (!p->unique()) {
    auto np = p->copy();
    m_ptr.reset(np);
    return np;
  }
  return p;
}

} // namespace detail
} // namespace caf
<|endoftext|>


<commit_before><commit_msg>fixed assert<commit_after><|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "dragtool.h"

#include "formeditorscene.h"
#include "formeditorview.h"
#include "itemutilfunctions.h"
#include <customdraganddrop.h>
#include <metainfo.h>
#include <rewritingexception.h>

#include "resizehandleitem.h"

#include <QApplication>
#include <QGraphicsSceneMouseEvent>
#include <QtDebug>
#include <QMessageBox>
#include <QTimer>

namespace QmlDesigner {

namespace Internal {
void TimerHandler::clearMoveDelay()
{
    m_dragTool->clearMoveDelay();
}

}

DragTool::DragTool(FormEditorView *editorView)
    : AbstractFormEditorTool(editorView),
    m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
    m_selectionIndicator(editorView->scene()->manipulatorLayerItem()),
    m_timerHandler(new Internal::TimerHandler(this)),
    m_blockMove(false)
{
//    view()->setCursor(Qt::SizeAllCursor);
}

DragTool::~DragTool()
{

}

void DragTool::clear()
{
    m_moveManipulator.clear();
    m_selectionIndicator.clear();
    m_movingItem.clear();
}

void DragTool::mousePressEvent(const QList<QGraphicsItem*> &,
                                            QGraphicsSceneMouseEvent *)
{

}

void DragTool::mouseMoveEvent(const QList<QGraphicsItem*> &,
                                           QGraphicsSceneMouseEvent *)
{

}

void DragTool::hoverMoveEvent(const QList<QGraphicsItem*> &,
                        QGraphicsSceneMouseEvent * /*event*/)
{

}

void DragTool::keyPressEvent(QKeyEvent *)
{

}

void DragTool::keyReleaseEvent(QKeyEvent *)
{

}

void DragTool::mouseReleaseEvent(const QList<QGraphicsItem*> &/*itemList*/,
                                 QGraphicsSceneMouseEvent *)
{

}

void DragTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> & /*itemList*/,
                                              QGraphicsSceneMouseEvent * /*event*/)
{

}

void DragTool::itemsAboutToRemoved(const QList<FormEditorItem*> & /* removedItemList */)
{

}

void DragTool::selectedItemsChanged(const QList<FormEditorItem*> &)
{

}

void DragTool::updateMoveManipulator()
{
    if (m_moveManipulator.isActive())
        return;
}

void DragTool::beginWithPoint(const QPointF &beginPoint)
{
    m_movingItem = scene()->itemForQmlItemNode(m_dragNode);

    m_moveManipulator.setItem(m_movingItem.data());
    m_moveManipulator.begin(beginPoint);

}

void DragTool::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, QmlItemNode parentNode, QPointF scenePos)
{
    MetaInfo metaInfo = MetaInfo::global();

    FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
    QPointF pos = parentItem->mapFromScene(scenePos);

    m_dragNode = view()->createQmlItemNode(itemLibraryEntry, pos, parentNode);

    Q_ASSERT(m_dragNode.modelNode().isValid());

    QList<QmlItemNode> nodeList;
    nodeList.append(m_dragNode);
    m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));

    QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
}

void DragTool::createQmlItemNodeFromImage(const QString &imageName, QmlItemNode parentNode, QPointF scenePos)
{
    if (!parentNode.isValid())
        return;

    MetaInfo metaInfo = MetaInfo::global();

    FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
    QPointF pos = parentItem->mapFromScene(scenePos);

    m_dragNode = view()->createQmlItemNodeFromImage(imageName, pos, parentNode);

    QList<QmlItemNode> nodeList;
    nodeList.append(m_dragNode);
    m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));

    QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
}

FormEditorItem* DragTool::calculateContainer(const QPointF &point, FormEditorItem * currentItem)
{
    QList<QGraphicsItem *> list = scene()->items(point);
    foreach (QGraphicsItem *item, list) {
         FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
         if (formEditorItem && formEditorItem != currentItem && formEditorItem->isContainer())
             return formEditorItem;
    }

    if (scene()->rootFormEditorItem() && scene()->rootFormEditorItem()->boundingRect().adjusted(-100, -100, 100, 100).contains(point))
        return scene()->rootFormEditorItem();
    return 0;
}

void DragTool::formEditorItemsChanged(const QList<FormEditorItem*> & itemList)
{
    if (m_movingItem && itemList.contains(m_movingItem.data())) {
        QList<FormEditorItem*> updateItemList;
        updateItemList.append(m_movingItem.data());
        m_selectionIndicator.updateItems(updateItemList);
    }
}

void DragTool::clearMoveDelay()
{
    m_blockMove = false;
    if  (m_dragNode.isValid())
        beginWithPoint(m_startPoint);
}

void DragTool::dropEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
        end(event->scenePos());
        //Q_ASSERT(m_token.isValid());
        try {
            m_rewriterTransaction.commit();
        } catch (RewritingException &e) {
            QMessageBox::warning(0, "Error", e.description());
        }
        if (m_dragNode.isValid()) {
            QList<QmlItemNode> nodeList;
            nodeList.append(m_dragNode);
            view()->setSelectedQmlItemNodes(nodeList);
        }
        m_dragNode = ModelNode();
        view()->changeToSelectionTool();
    }
}

void DragTool::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
        event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        if (!m_rewriterTransaction.isValid()) {
            view()->clearSelectedModelNodes();
            m_rewriterTransaction = view()->beginRewriterTransaction();
        }
    }
}

void DragTool::dragLeaveEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
        if (m_dragNode.isValid())
            m_dragNode.destroy();
        end(event->scenePos());

        try {
            m_rewriterTransaction.commit();
        } catch (RewritingException &e) {
            QMessageBox::warning(0, "Error", e.description());
        }

        QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
        QList<QmlItemNode> nodeList;
        view()->setSelectedQmlItemNodes(nodeList);
        view()->changeToSelectionTool();
    }
}

static ItemLibraryEntry itemLibraryEntryFromData(const QByteArray &data)
{
    QDataStream stream(data);

    ItemLibraryEntry itemLibraryEntry;
    stream >> itemLibraryEntry;

    return itemLibraryEntry;
}

void DragTool::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
{
    if (m_blockMove)
        return;
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
        QPointF scenePos = event->scenePos();
        if  (m_dragNode.isValid()) {

            FormEditorItem *parentItem = calculateContainer(event->scenePos() + QPoint(2, 2));
            if (!parentItem) {      //if there is no parent any more - the use left the scene
                end(event->scenePos());
                QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
                m_dragNode.destroy(); //delete the node then
                return;
            }
            //move
            move(event->scenePos());
        } else {
            //create new node  if container
            if (m_dragNode.modelNode().isValid())
                return;

            FormEditorItem *parentItem = calculateContainer(event->scenePos());
            if (!parentItem)
                return;
            QmlItemNode parentNode;
            if (parentItem)
                parentNode = parentItem->qmlItemNode();

            if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
                Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo").isEmpty());
                ItemLibraryEntry itemLibraryEntry = itemLibraryEntryFromData(event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo"));
                createQmlItemNode(itemLibraryEntry, parentNode, event->scenePos());
            } else if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
                Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.libraryresource").isEmpty());
                QString imageName = QString::fromLatin1((event->mimeData()->data("application/vnd.bauhaus.libraryresource")));
                createQmlItemNodeFromImage(imageName, parentNode, event->scenePos());
            } else Q_ASSERT(false);
            m_blockMove = true;
            m_startPoint = event->scenePos();
            QTimer::singleShot(100, m_timerHandler.data(), SLOT(clearMoveDelay()));
        }
    }
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
    }
}

void  DragTool::end(QPointF scenePos)
{
    m_moveManipulator.end(scenePos);
    clear();
}

void  DragTool::move(QPointF scenePos)
{
    if (!m_movingItem)
        return;

    FormEditorItem *containerItem = calculateContainer(scenePos - QPoint(2, 2), m_movingItem.data());
    if (containerItem &&
       containerItem != m_movingItem->parentItem()) {

        m_moveManipulator.reparentTo(containerItem);
    }

    //MoveManipulator::Snapping useSnapping = MoveManipulator::NoSnapping;
    MoveManipulator::Snapping useSnapping = MoveManipulator::UseSnapping;
   /* if (event->modifiers().testFlag(Qt::ControlModifier) != view()->isSnapButtonChecked())
        useSnapping = MoveManipulator::UseSnapping;*/

    m_moveManipulator.update(scenePos, useSnapping, MoveManipulator::UseBaseState);
}

}
<commit_msg>QmlDesigner.dragAndDrop: properly add imports<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "dragtool.h"

#include "formeditorscene.h"
#include "formeditorview.h"
#include "itemutilfunctions.h"
#include <customdraganddrop.h>
#include <metainfo.h>
#include <rewritingexception.h>

#include "resizehandleitem.h"

#include <QApplication>
#include <QGraphicsSceneMouseEvent>
#include <QtDebug>
#include <QMessageBox>
#include <QTimer>

namespace QmlDesigner {

namespace Internal {
void TimerHandler::clearMoveDelay()
{
    m_dragTool->clearMoveDelay();
}

}

DragTool::DragTool(FormEditorView *editorView)
    : AbstractFormEditorTool(editorView),
    m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
    m_selectionIndicator(editorView->scene()->manipulatorLayerItem()),
    m_timerHandler(new Internal::TimerHandler(this)),
    m_blockMove(false)
{
//    view()->setCursor(Qt::SizeAllCursor);
}

DragTool::~DragTool()
{

}

void DragTool::clear()
{
    m_moveManipulator.clear();
    m_selectionIndicator.clear();
    m_movingItem.clear();
}

void DragTool::mousePressEvent(const QList<QGraphicsItem*> &,
                                            QGraphicsSceneMouseEvent *)
{

}

void DragTool::mouseMoveEvent(const QList<QGraphicsItem*> &,
                                           QGraphicsSceneMouseEvent *)
{

}

void DragTool::hoverMoveEvent(const QList<QGraphicsItem*> &,
                        QGraphicsSceneMouseEvent * /*event*/)
{

}

void DragTool::keyPressEvent(QKeyEvent *)
{

}

void DragTool::keyReleaseEvent(QKeyEvent *)
{

}

void DragTool::mouseReleaseEvent(const QList<QGraphicsItem*> &/*itemList*/,
                                 QGraphicsSceneMouseEvent *)
{

}

void DragTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> & /*itemList*/,
                                              QGraphicsSceneMouseEvent * /*event*/)
{

}

void DragTool::itemsAboutToRemoved(const QList<FormEditorItem*> & /* removedItemList */)
{

}

void DragTool::selectedItemsChanged(const QList<FormEditorItem*> &)
{

}

void DragTool::updateMoveManipulator()
{
    if (m_moveManipulator.isActive())
        return;
}

void DragTool::beginWithPoint(const QPointF &beginPoint)
{
    m_movingItem = scene()->itemForQmlItemNode(m_dragNode);

    m_moveManipulator.setItem(m_movingItem.data());
    m_moveManipulator.begin(beginPoint);

}

void DragTool::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, QmlItemNode parentNode, QPointF scenePos)
{
    MetaInfo metaInfo = MetaInfo::global();

    FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
    QPointF pos = parentItem->mapFromScene(scenePos);

    m_dragNode = view()->createQmlItemNode(itemLibraryEntry, pos, parentNode);

    Q_ASSERT(m_dragNode.modelNode().isValid());

    QList<QmlItemNode> nodeList;
    nodeList.append(m_dragNode);
    m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));

    QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
}

void DragTool::createQmlItemNodeFromImage(const QString &imageName, QmlItemNode parentNode, QPointF scenePos)
{
    if (!parentNode.isValid())
        return;

    MetaInfo metaInfo = MetaInfo::global();

    FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
    QPointF pos = parentItem->mapFromScene(scenePos);

    m_dragNode = view()->createQmlItemNodeFromImage(imageName, pos, parentNode);

    QList<QmlItemNode> nodeList;
    nodeList.append(m_dragNode);
    m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));

    QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
}

FormEditorItem* DragTool::calculateContainer(const QPointF &point, FormEditorItem * currentItem)
{
    QList<QGraphicsItem *> list = scene()->items(point);
    foreach (QGraphicsItem *item, list) {
         FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
         if (formEditorItem && formEditorItem != currentItem && formEditorItem->isContainer())
             return formEditorItem;
    }

    if (scene()->rootFormEditorItem() && scene()->rootFormEditorItem()->boundingRect().adjusted(-100, -100, 100, 100).contains(point))
        return scene()->rootFormEditorItem();
    return 0;
}

void DragTool::formEditorItemsChanged(const QList<FormEditorItem*> & itemList)
{
    if (m_movingItem && itemList.contains(m_movingItem.data())) {
        QList<FormEditorItem*> updateItemList;
        updateItemList.append(m_movingItem.data());
        m_selectionIndicator.updateItems(updateItemList);
    }
}

void DragTool::clearMoveDelay()
{
    m_blockMove = false;
    if  (m_dragNode.isValid())
        beginWithPoint(m_startPoint);
}

void DragTool::dropEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
        end(event->scenePos());
        //Q_ASSERT(m_token.isValid());
        try {
            m_rewriterTransaction.commit();
        } catch (RewritingException &e) {
            QMessageBox::warning(0, "Error", e.description());
        }
        if (m_dragNode.isValid()) {
            QList<QmlItemNode> nodeList;
            nodeList.append(m_dragNode);
            view()->setSelectedQmlItemNodes(nodeList);
        }
        m_dragNode = ModelNode();
        view()->changeToSelectionTool();
    }
}

static ItemLibraryEntry itemLibraryEntryFromData(const QByteArray &data)
{
    QDataStream stream(data);

    ItemLibraryEntry itemLibraryEntry;
    stream >> itemLibraryEntry;

    return itemLibraryEntry;
}

void DragTool::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
        event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {

        if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
            Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo").isEmpty());
            ItemLibraryEntry itemLibraryEntry = itemLibraryEntryFromData(event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo"));
            if (!itemLibraryEntry.requiredImport().isEmpty()) {
                const QString newImportUrl = itemLibraryEntry.requiredImport();
                const QString newImportVersion = QString("%1.%2").arg(QString::number(itemLibraryEntry.majorVersion()), QString::number(itemLibraryEntry.minorVersion()));
                Import newImport = Import::createLibraryImport(newImportUrl, newImportVersion);

                if (!view()->model()->imports().contains(newImport)) {
                    view()->model()->addImport(newImport);
                }

            }
        }

        if (!m_rewriterTransaction.isValid()) {
            view()->clearSelectedModelNodes();
            m_rewriterTransaction = view()->beginRewriterTransaction();
        }
    }
}

void DragTool::dragLeaveEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
        if (m_dragNode.isValid())
            m_dragNode.destroy();
        end(event->scenePos());

        try {
            m_rewriterTransaction.commit();
        } catch (RewritingException &e) {
            QMessageBox::warning(0, "Error", e.description());
        }

        QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
        QList<QmlItemNode> nodeList;
        view()->setSelectedQmlItemNodes(nodeList);
        view()->changeToSelectionTool();
    }
}

void DragTool::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
{
    if (m_blockMove)
        return;
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
        QPointF scenePos = event->scenePos();
        if  (m_dragNode.isValid()) {

            FormEditorItem *parentItem = calculateContainer(event->scenePos() + QPoint(2, 2));
            if (!parentItem) {      //if there is no parent any more - the use left the scene
                end(event->scenePos());
                QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
                m_dragNode.destroy(); //delete the node then
                return;
            }
            //move
            move(event->scenePos());
        } else {
            //create new node  if container
            if (m_dragNode.modelNode().isValid())
                return;

            FormEditorItem *parentItem = calculateContainer(event->scenePos());
            if (!parentItem)
                return;
            QmlItemNode parentNode;
            if (parentItem)
                parentNode = parentItem->qmlItemNode();

            if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
                Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo").isEmpty());
                ItemLibraryEntry itemLibraryEntry = itemLibraryEntryFromData(event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo"));
                createQmlItemNode(itemLibraryEntry, parentNode, event->scenePos());
            } else if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
                Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.libraryresource").isEmpty());
                QString imageName = QString::fromLatin1((event->mimeData()->data("application/vnd.bauhaus.libraryresource")));
                createQmlItemNodeFromImage(imageName, parentNode, event->scenePos());
            } else Q_ASSERT(false);
            m_blockMove = true;
            m_startPoint = event->scenePos();
            QTimer::singleShot(100, m_timerHandler.data(), SLOT(clearMoveDelay()));
        }
    }
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
    }
}

void  DragTool::end(QPointF scenePos)
{
    m_moveManipulator.end(scenePos);
    clear();
}

void  DragTool::move(QPointF scenePos)
{
    if (!m_movingItem)
        return;

    FormEditorItem *containerItem = calculateContainer(scenePos - QPoint(2, 2), m_movingItem.data());
    if (containerItem &&
       containerItem != m_movingItem->parentItem()) {

        m_moveManipulator.reparentTo(containerItem);
    }

    //MoveManipulator::Snapping useSnapping = MoveManipulator::NoSnapping;
    MoveManipulator::Snapping useSnapping = MoveManipulator::UseSnapping;
   /* if (event->modifiers().testFlag(Qt::ControlModifier) != view()->isSnapButtonChecked())
        useSnapping = MoveManipulator::UseSnapping;*/

    m_moveManipulator.update(scenePos, useSnapping, MoveManipulator::UseBaseState);
}

}
<|endoftext|>