<commit_before>#include "cinder/app/AppBasic.h"
#include "cinder/audio/Io.h"
#include "cinder/audio/Output.h"
#include "cinder/audio/FftProcessor.h"

#include "Resources.h"
using namespace ci;
using namespace ci::app;
using namespace std;

// We'll create a new Cinder Application by deriving from the AppBasic class
class AudioAnalysisSampleApp : public AppBasic {
 public:
	void setup();
	void draw();
	void drawWaveForm( audio::TrackRef track );
	void drawFft( audio::TrackRef track );
	void keyDown( KeyEvent e );

	audio::TrackRef mTrack1;
	audio::TrackRef mTrack2;
};

void AudioAnalysisSampleApp::setup()
{
	//mTrack1 = audio::Output::addTrack( audio::load( "C:\\code\\cinder\\samples\\AudioPlayback\\resources\\booyah.mp3" ) );
	//mTrack1->setPcmBuffering( true );
	mTrack1 = audio::Output::addTrack( audio::load( loadResource( RES_GUITAR ) ) );
	//mTrack1 = audio::Output::addTrack( audio::load( "../../../../AudioPlayback/resources/booyah.mp3" ) );
	mTrack1->setPcmBuffering( true );
	//mTrack2 = audio::Output::addTrack( audio::load( loadResource( RES_DRUMS ) ) );
	//mTrack2->setPcmBuffering( true );
}

void AudioAnalysisSampleApp::keyDown( KeyEvent e ) {
	if( e.getChar() == 'p' ) {
		( mTrack1->isPlaying() ) ? mTrack1->stop() : mTrack1->play();
	} else if( e.getChar() == 'c' ) {
		std::cout << audio::Output::getVolume() << std::endl;
		std::cout << mTrack1->getVolume() << std::endl;
	}
}

void AudioAnalysisSampleApp::drawWaveForm( audio::TrackRef track )
{
	audio::PcmBuffer32fRef aPcmBuffer = track->getPcmBuffer();
	if( ! aPcmBuffer ) {
		return;
	}

	uint32_t bufferSamples = aPcmBuffer->getSampleCount();
	audio::Buffer32fRef leftBuffer = aPcmBuffer->getChannelData( audio::CHANNEL_FRONT_LEFT );
	audio::Buffer32fRef rightBuffer = aPcmBuffer->getChannelData( audio::CHANNEL_FRONT_RIGHT );

	int displaySize = getWindowWidth();
	int endIdx = bufferSamples;

	float scale = displaySize / (float)endIdx;

	glColor3f( 1.0f, 0.5f, 0.25f );
	glBegin( GL_LINE_STRIP );
	for( int i = 0; i < endIdx; i++ ) {
		float y = ( ( leftBuffer->mData[i] - 1 ) * - 100 );
		glVertex2f( ( i * scale ) , y );
	}
	glEnd();

	glColor3f( 1.0f, 0.96f, 0.0f );
	glBegin( GL_LINE_STRIP );
	for( int i = 0; i < endIdx; i++ ) {
		float y = ( ( rightBuffer->mData[i] - 1 ) * - 100 );
		glVertex2f( ( i * scale ) , y );
	}
	glEnd();
}

void AudioAnalysisSampleApp::drawFft( audio::TrackRef track )
{
	float ht = 100.0f;
	uint16_t bandCount = 32;

	audio::PcmBuffer32fRef aPcmBuffer = track->getPcmBuffer();
	if( ! aPcmBuffer ) {
		return;
	}
	boost::shared_ptr<float> fftRef = audio::calculateFft( aPcmBuffer->getChannelData( audio::CHANNEL_FRONT_LEFT ), bandCount );
	if( ! fftRef ) {
		return;
	}

	float * fftBuffer = fftRef.get();

	for( int i = 0; i < ( bandCount ); i++ ) {
		float barY = fftBuffer[i] / bandCount * ht;
		glBegin( GL_QUADS );
			glColor3f( 255.0f, 255.0f, 0.0f );
			glVertex2f( i * 3, ht );
			glVertex2f( i * 3 + 1, ht );
			glColor3f( 0.0f, 255.0f, 0.0f );
			glVertex2f( i * 3 + 1, ht - barY );
			glVertex2f( i * 3, ht - barY );
		glEnd();
	}
}

void AudioAnalysisSampleApp::draw()
{
	gl::clear( Color( 0.0f, 0.0f, 0.0f ) );

	glPushMatrix();
		glTranslatef( 0.0, 0.0, 0.0 );
		drawFft( mTrack1 );
		//drawWaveForm( mTrack1 );
		glTranslatef( 0.0, 120.0, 0.0 );
		//drawFft( mTrack2 );
		//drawWaveForm( mTrack2 );
	glPopMatrix();
}

// This line tells Cinder to actually create the application
CINDER_APP_BASIC( AudioAnalysisSampleApp, RendererGl )
<commit_msg>cleaning up audio analysis sample<commit_after>#include "cinder/app/AppBasic.h"
#include "cinder/audio/Io.h"
#include "cinder/audio/Output.h"
#include "cinder/audio/FftProcessor.h"
#include "cinder/audio/PcmBuffer.h"

#include "Resources.h"
using namespace ci;
using namespace ci::app;
using namespace std;

// We'll create a new Cinder Application by deriving from the AppBasic class
class AudioAnalysisSampleApp : public AppBasic {
 public:
	void setup();
	void update();
	void draw();
	void keyDown( KeyEvent e );

	void drawWaveForm();
	void drawFft();

	audio::TrackRef mTrack;
	audio::PcmBuffer32fRef mPcmBuffer;
};

void AudioAnalysisSampleApp::setup()
{
	//add the audio track the default audio output
	mTrack = audio::Output::addTrack( audio::load( loadResource( RES_GUITAR ) ) );

	//you must enable enable PCM buffering on the track to be able to call getPcmBuffer on it later
	mTrack->setPcmBuffering( true );
}

void AudioAnalysisSampleApp::keyDown( KeyEvent e ) {
	if( e.getChar() == 'p' ) {
		( mTrack->isPlaying() ) ? mTrack->stop() : mTrack->play();
	}
}

void AudioAnalysisSampleApp::update()
{
	//get the latest pcm buffer from the track
	mPcmBuffer = mTrack->getPcmBuffer();
}

void AudioAnalysisSampleApp::draw()
{
	gl::clear( Color( 0.0f, 0.0f, 0.0f ) );

	glPushMatrix();
		glTranslatef( 0.0, 0.0, 0.0 );
		drawWaveForm();
#if defined( CINDER_MAC )
		glTranslatef( 0.0, 200.0, 0.0 );
		drawFft();
#endif
	glPopMatrix();
}

void AudioAnalysisSampleApp::drawWaveForm()
{
	//if the buffer is null, for example if this gets called before any PCM data has been buffered
	//don't do anything
	if( ! mPcmBuffer ) {
		return;
	}

	uint32_t bufferLength = mPcmBuffer->getSampleCount();
	audio::Buffer32fRef leftBuffer = mPcmBuffer->getChannelData( audio::CHANNEL_FRONT_LEFT );
	audio::Buffer32fRef rightBuffer = mPcmBuffer->getChannelData( audio::CHANNEL_FRONT_RIGHT );

	int displaySize = getWindowWidth();
	float scale = displaySize / (float)bufferLength;

	PolyLine<Vec2f>	leftBufferLine;
	PolyLine<Vec2f>	rightBufferLine;

	for( int i = 0; i < bufferLength; i++ ) {
		float x = ( i * scale );

		//get the PCM value from the left channel buffer
		float y = ( ( leftBuffer->mData[i] - 1 ) * - 100 );
		leftBufferLine.push_back( Vec2f( x , y) );

		y = ( ( rightBuffer->mData[i] - 1 ) * - 100 );
		rightBufferLine.push_back( Vec2f( x , y) );
	}
	gl::color( Color( 1.0f, 0.5f, 0.25f ) );
	gl::draw( leftBufferLine );
	gl::draw( rightBufferLine );

}

#if defined(CINDER_MAC)
void AudioAnalysisSampleApp::drawFft()
{
	float ht = 100.0f;
	uint16_t bandCount = 32;

	if( ! mPcmBuffer ) return;

	//use the most recent Pcm data to calculate the Fft
	boost::shared_ptr<float> fftRef = audio::calculateFft( mPcmBuffer->getChannelData( audio::CHANNEL_FRONT_LEFT ), bandCount );
	if( ! fftRef ) {
		return;
	}

	float * fftBuffer = fftRef.get();

	//draw the bands
	for( int i = 0; i < ( bandCount ); i++ ) {
		float barY = fftBuffer[i] / bandCount * ht;
		glBegin( GL_QUADS );
			glColor3f( 255.0f, 255.0f, 0.0f );
			glVertex2f( i * 3, ht );
			glVertex2f( i * 3 + 1, ht );
			glColor3f( 0.0f, 255.0f, 0.0f );
			glVertex2f( i * 3 + 1, ht - barY );
			glVertex2f( i * 3, ht - barY );
		glEnd();
	}
}
#endif

// This line tells Cinder to actually create the application
CINDER_APP_BASIC( AudioAnalysisSampleApp, RendererGl )
<|endoftext|>


<commit_before>#include "display_driver_ssd1306.h"

#define _BV(bit) (1 << (bit))

#define SSD_Command_Mode			0x00 	/* C0 and DC bit are 0 				 */
#define SSD_Data_Mode					0x40	/* C0 bit is 0 and DC bit is 1 */

#define SSD_Inverse_Display		0xA7

#define SSD_Display_Off				0xAE
#define SSD_Display_On				0xAF

#define SSD_Set_ContrastLevel	0x81

#define SSD_External_Vcc			0x01
#define SSD_Internal_Vcc			0x02

#define SSD_Activate_Scroll		0x2F
#define SSD_Deactivate_Scroll	0x2E

#define Scroll_Left						0x00
#define Scroll_Right					0x01

#define Scroll_2Frames		0x07
#define Scroll_3Frames		0x04
#define Scroll_4Frames		0x05
#define Scroll_5Frames		0x00
#define Scroll_25Frames		0x06
#define Scroll_64Frames		0x01
#define Scroll_128Frames	0x02
#define Scroll_256Frames	0x03

#define SSD1306_DISPLAYALLON_RESUME	0xA4
#define SSD1306_DISPLAYALLON 				0xA5

#define SSD1306_Normal_Display	0xA6

#define SSD1306_SETDISPLAYOFFSET 		0xD3
#define SSD1306_SETCOMPINS 					0xDA
#define SSD1306_SETVCOMDETECT 			0xDB
#define SSD1306_SETDISPLAYCLOCKDIV 	0xD5
#define SSD1306_SETPRECHARGE 				0xD9
#define SSD1306_SETMULTIPLEX 				0xA8
#define SSD1306_SETLOWCOLUMN 				0x00
#define SSD1306_SETHIGHCOLUMN 			0x10
#define SSD1306_SETSTARTLINE 				0x40
#define SSD1306_MEMORYMODE 					0x20
#define SSD1306_COMSCANINC 					0xC0
#define SSD1306_COMSCANDEC 					0xC8
#define SSD1306_SEGREMAP 						0xA0
#define SSD1306_CHARGEPUMP 					0x8D

// Scrolling #defines
#define SSD1306_SET_VERTICAL_SCROLL_AREA 							0xA3
#define SSD1306_RIGHT_HORIZONTAL_SCROLL 							0x26
#define SSD1306_LEFT_HORIZONTAL_SCROLL 								0x27
#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 	0x29
#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL		0x2A

namespace gameAmbiance
{
    namespace hw
    {
        void display_driver_ssd1306::sendCommand(uint8_t c) const
        {
            _busDriver.sendCommand(_dcPin, c);
        }

        void display_driver_ssd1306::sendCommand(uint8_t c0, uint8_t c1) const
		{
            _busDriver.sendCommand(_dcPin, c0, c1);
		}

		void display_driver_ssd1306::sendCommand(uint8_t c0, uint8_t c1, uint8_t c2) const
		{
            _busDriver.sendCommand(_dcPin, c0, c1, c2);
		}

		void display_driver_ssd1306::sendData(uint8_t* buf, uint32_t len) const
		{
            _busDriver.sendCommand(_dcPin, buf, len);
		}

        display_driver_ssd1306::display_driver_ssd1306(const bus_driver_interface& busDriver, uint8_t dcPin, uint8_t rstPin, int16_t width, int16_t height)
            : _busDriver(busDriver)
            , _dcPin(dcPin)
            , _rstPin(rstPin)
            , _screenWidth(width)
            , _screenHeight(height)
            , _screenBuffer((uint8_t *)malloc((_screenWidth * _screenHeight / 8)))
        {
        }

        display_driver_ssd1306::~display_driver_ssd1306()
        {
            term();

            free(_screenBuffer);
            _screenBuffer = 0;
        }

        void display_driver_ssd1306::init()
        {
                        // SPI Reset
			// bcm2835_gpio_write(_pinRST, HIGH);
			// delay(1000);
			// bcm2835_gpio_write(_pinRST, LOW);
			// delay(10000);
			// bcm2835_gpio_write(_pinRST, HIGH);

            _busDriver.setPinOutputMode(_dcPin);
            _busDriver.setPinOutputMode(_rstPin);

            sendCommand(SSD_Display_Off);                    // 0xAE
            sendCommand(SSD1306_SETDISPLAYCLOCKDIV, 0x80);      // 0xD5 + the suggested ratio 0x80
            sendCommand(SSD1306_SETMULTIPLEX, 0x3F);
            sendCommand(SSD1306_SETDISPLAYOFFSET, 0x00);        // 0xD3 + no offset
            sendCommand(SSD1306_SETSTARTLINE | 0x0);            // line #0
            sendCommand(SSD1306_CHARGEPUMP, 0x14);
            sendCommand(SSD1306_MEMORYMODE, 0x00);              // 0x20 0x0 act like ks0108
            sendCommand(SSD1306_SEGREMAP | 0x1);
            sendCommand(SSD1306_COMSCANDEC);
            sendCommand(SSD1306_SETCOMPINS, 0x12);  // 0xDA
            sendCommand(SSD_Set_ContrastLevel, 0xCF);
            sendCommand(SSD1306_SETPRECHARGE, 0x22); // 0xd9
            sendCommand(SSD1306_SETVCOMDETECT, 0x40);  // 0xDB
            sendCommand(SSD1306_DISPLAYALLON_RESUME);    // 0xA4
            sendCommand(SSD1306_Normal_Display);         // 0xA6
            sendCommand(SSD_Display_On);
        }

        void display_driver_ssd1306::term()
        {
        }

        void display_driver_ssd1306::clear(uint32_t color)
        {
            int c = color ? 0xFF : 0x00;
            std::memset(_screenBuffer, c, _screenWidth*_screenHeight / 8);
        }

        void display_driver_ssd1306::setPixel(int16_t x, int16_t y, uint32_t color)
        {
            if ((x < 0) || (x >= _screenWidth) || (y < 0) || (y >= _screenHeight))
            {
                return;
            }

            // Get where to do the change in the buffer
            uint8_t * target = _screenBuffer + (x + (y / 8)*_screenWidth);

            // x is which column
            if (color)
                *target |= _BV((y % 8));
            else
                *target &= ~_BV((y % 8));
        }

        void display_driver_ssd1306::render()
        {
            _busDriver.sendCommand(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0
            _busDriver.sendCommand(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0
            _busDriver.sendCommand(SSD1306_SETSTARTLINE | 0x0); // line #0

            _busDriver.sendData(_screenBuffer, _screenWidth*_screenHeight/8);
        }
    }
}<commit_msg>Fix compilation errors<commit_after>#include "display_driver_ssd1306.h"

#define _BV(bit) (1 << (bit))

#define SSD_Command_Mode			0x00 	/* C0 and DC bit are 0 				 */
#define SSD_Data_Mode					0x40	/* C0 bit is 0 and DC bit is 1 */

#define SSD_Inverse_Display		0xA7

#define SSD_Display_Off				0xAE
#define SSD_Display_On				0xAF

#define SSD_Set_ContrastLevel	0x81

#define SSD_External_Vcc			0x01
#define SSD_Internal_Vcc			0x02

#define SSD_Activate_Scroll		0x2F
#define SSD_Deactivate_Scroll	0x2E

#define Scroll_Left						0x00
#define Scroll_Right					0x01

#define Scroll_2Frames		0x07
#define Scroll_3Frames		0x04
#define Scroll_4Frames		0x05
#define Scroll_5Frames		0x00
#define Scroll_25Frames		0x06
#define Scroll_64Frames		0x01
#define Scroll_128Frames	0x02
#define Scroll_256Frames	0x03

#define SSD1306_DISPLAYALLON_RESUME	0xA4
#define SSD1306_DISPLAYALLON 				0xA5

#define SSD1306_Normal_Display	0xA6

#define SSD1306_SETDISPLAYOFFSET 		0xD3
#define SSD1306_SETCOMPINS 					0xDA
#define SSD1306_SETVCOMDETECT 			0xDB
#define SSD1306_SETDISPLAYCLOCKDIV 	0xD5
#define SSD1306_SETPRECHARGE 				0xD9
#define SSD1306_SETMULTIPLEX 				0xA8
#define SSD1306_SETLOWCOLUMN 				0x00
#define SSD1306_SETHIGHCOLUMN 			0x10
#define SSD1306_SETSTARTLINE 				0x40
#define SSD1306_MEMORYMODE 					0x20
#define SSD1306_COMSCANINC 					0xC0
#define SSD1306_COMSCANDEC 					0xC8
#define SSD1306_SEGREMAP 						0xA0
#define SSD1306_CHARGEPUMP 					0x8D

// Scrolling #defines
#define SSD1306_SET_VERTICAL_SCROLL_AREA 							0xA3
#define SSD1306_RIGHT_HORIZONTAL_SCROLL 							0x26
#define SSD1306_LEFT_HORIZONTAL_SCROLL 								0x27
#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 	0x29
#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL		0x2A

namespace gameAmbiance
{
    namespace hw
    {
        void display_driver_ssd1306::sendCommand(uint8_t c) const
        {
            _busDriver.sendCommand(_dcPin, c);
        }

        void display_driver_ssd1306::sendCommand(uint8_t c0, uint8_t c1) const
		{
            _busDriver.sendCommand(_dcPin, c0, c1);
		}

		void display_driver_ssd1306::sendCommand(uint8_t c0, uint8_t c1, uint8_t c2) const
		{
            _busDriver.sendCommand(_dcPin, c0, c1, c2);
		}

		void display_driver_ssd1306::sendData(uint8_t* buf, uint32_t len) const
		{
            _busDriver.sendData(_dcPin, buf, len);
		}

        display_driver_ssd1306::display_driver_ssd1306(const bus_driver_interface& busDriver, uint8_t dcPin, uint8_t rstPin, int16_t width, int16_t height)
            : _busDriver(busDriver)
            , _dcPin(dcPin)
            , _rstPin(rstPin)
            , _screenWidth(width)
            , _screenHeight(height)
            , _screenBuffer((uint8_t *)malloc((_screenWidth * _screenHeight / 8)))
        {
        }

        display_driver_ssd1306::~display_driver_ssd1306()
        {
            term();

            free(_screenBuffer);
            _screenBuffer = 0;
        }

        void display_driver_ssd1306::init()
        {
                        // SPI Reset
			// bcm2835_gpio_write(_pinRST, HIGH);
			// delay(1000);
			// bcm2835_gpio_write(_pinRST, LOW);
			// delay(10000);
			// bcm2835_gpio_write(_pinRST, HIGH);

            _busDriver.setPinOutputMode(_dcPin);
            _busDriver.setPinOutputMode(_rstPin);

            sendCommand(SSD_Display_Off);                    // 0xAE
            sendCommand(SSD1306_SETDISPLAYCLOCKDIV, 0x80);      // 0xD5 + the suggested ratio 0x80
            sendCommand(SSD1306_SETMULTIPLEX, 0x3F);
            sendCommand(SSD1306_SETDISPLAYOFFSET, 0x00);        // 0xD3 + no offset
            sendCommand(SSD1306_SETSTARTLINE | 0x0);            // line #0
            sendCommand(SSD1306_CHARGEPUMP, 0x14);
            sendCommand(SSD1306_MEMORYMODE, 0x00);              // 0x20 0x0 act like ks0108
            sendCommand(SSD1306_SEGREMAP | 0x1);
            sendCommand(SSD1306_COMSCANDEC);
            sendCommand(SSD1306_SETCOMPINS, 0x12);  // 0xDA
            sendCommand(SSD_Set_ContrastLevel, 0xCF);
            sendCommand(SSD1306_SETPRECHARGE, 0x22); // 0xd9
            sendCommand(SSD1306_SETVCOMDETECT, 0x40);  // 0xDB
            sendCommand(SSD1306_DISPLAYALLON_RESUME);    // 0xA4
            sendCommand(SSD1306_Normal_Display);         // 0xA6
            sendCommand(SSD_Display_On);
        }

        void display_driver_ssd1306::term()
        {
        }

        void display_driver_ssd1306::clear(uint32_t color)
        {
            int c = color ? 0xFF : 0x00;
            memset(_screenBuffer, c, _screenWidth*_screenHeight / 8);
        }

        void display_driver_ssd1306::setPixel(int16_t x, int16_t y, uint32_t color)
        {
            if ((x < 0) || (x >= _screenWidth) || (y < 0) || (y >= _screenHeight))
            {
                return;
            }

            // Get where to do the change in the buffer
            uint8_t * target = _screenBuffer + (x + (y / 8)*_screenWidth);

            // x is which column
            if (color)
                *target |= _BV((y % 8));
            else
                *target &= ~_BV((y % 8));
        }

        void display_driver_ssd1306::render()
        {
            _busDriver.sendCommand((_uint8_t)(SSD1306_SETLOWCOLUMN | 0x0)); // low col = 0
            _busDriver.sendCommand((_uint8_t)(SSD1306_SETHIGHCOLUMN | 0x0)); // hi col = 0
            _busDriver.sendCommand((_uint8_t)(SSD1306_SETSTARTLINE | 0x0)); // line #0

            _busDriver.sendData(_screenBuffer, _screenWidth*_screenHeight/8);
        }
    }
}<|endoftext|>


<commit_before>/**
    @file Script.hpp
    @brief Class responsible for starting the game, creating an owner.
    @copyright LGPL. MIT License.
*/
#ifndef __SCRIPT__
#define __SCRIPT__

#include "Engine/Component.hpp"
#include "Engine/GameObject.hpp"

#include <utility>

class Script : public Component {
	public:

		// constructor and destructor
		Script(GameObject *owner);

		// pure virtual name getter
		virtual std::string GetComponentName() = 0;
};

#endif
<commit_msg>Fourth Application: Script.hpp             - Comments in the file of classes;             - Comments in its variables;<commit_after>/**
    @file Script.hpp
    @brief Class responsible for starting the game, creating an owner.
    @copyright LGPL. MIT License.
*/
#ifndef __SCRIPT__
#define __SCRIPT__

#include "Engine/Component.hpp"
#include "Engine/GameObject.hpp"

#include <utility>

class Script : public Component {
	public:

		// constructor and destructor.
		Script(GameObject *owner);

		// pure virtual name getter.
		virtual std::string GetComponentName() = 0;
};

#endif
<|endoftext|>


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

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#ifndef _SVX_UNOEDHLP_HXX
#include <svx/unoedhlp.hxx>
#endif
#ifndef _SVDOUTL_HXX
#include <svx/svdoutl.hxx>
#endif

#ifndef SD_ACCESSIBILITY_ACCESSIBLE_OUTLINE_EDIT_SOURCE_HXX
#include <AccessibleOutlineEditSource.hxx>
#endif
#ifndef SD_OUTLINE_VIEW_HXX
#include "OutlineView.hxx"
#endif

namespace accessibility
{

    AccessibleOutlineEditSource::AccessibleOutlineEditSource(
        SdrOutliner&    rOutliner,
        SdrView&        rView,
        OutlinerView& rOutlView,
        const ::Window& rViewWindow )
        : mrView( rView ),
          mrWindow( rViewWindow ),
          mpOutliner( &rOutliner ),
          mpOutlinerView( &rOutlView ),
          mTextForwarder( rOutliner, NULL ),
          mViewForwarder( rOutlView )
    {
        // register as listener - need to broadcast state change messages
        rOutliner.SetNotifyHdl( LINK(this, AccessibleOutlineEditSource, NotifyHdl) );
    }

    AccessibleOutlineEditSource::~AccessibleOutlineEditSource()
    {
        if( mpOutliner )
            mpOutliner->SetNotifyHdl( Link() );
        Broadcast( TextHint( SFX_HINT_DYING ) );
    }

    SvxEditSource* AccessibleOutlineEditSource::Clone() const
    {
        return NULL;
    }

    SvxTextForwarder* AccessibleOutlineEditSource::GetTextForwarder()
    {
        // TODO: maybe suboptimal
        if( IsValid() )
            return &mTextForwarder;
        else
            return NULL;
    }

    SvxViewForwarder* AccessibleOutlineEditSource::GetViewForwarder()
    {
        // TODO: maybe suboptimal
        if( IsValid() )
            return this;
        else
            return NULL;
    }

    SvxEditViewForwarder* AccessibleOutlineEditSource::GetEditViewForwarder( sal_Bool )
    {
        // TODO: maybe suboptimal
        if( IsValid() )
        {
            // ignore parameter, we're always in edit mode here
            return &mViewForwarder;
        }
        else
            return NULL;
    }

    void AccessibleOutlineEditSource::UpdateData()
    {
        // NOOP, since we're always working on the 'real' outliner,
        // i.e. changes are immediately reflected on the screen
    }

    SfxBroadcaster& AccessibleOutlineEditSource::GetBroadcaster() const
    {
        return *( const_cast< AccessibleOutlineEditSource* > (this) );
    }

    BOOL AccessibleOutlineEditSource::IsValid() const
    {
        if( mpOutliner && mpOutlinerView )
        {
            // Our view still on outliner?
            ULONG nCurrView, nViews;

            for( nCurrView=0, nViews=mpOutliner->GetViewCount(); nCurrView<nViews; ++nCurrView )
            {
                if( mpOutliner->GetView(nCurrView) == mpOutlinerView )
                    return sal_True;
            }
        }

        return sal_False;
    }

    Rectangle AccessibleOutlineEditSource::GetVisArea() const
    {
        if( IsValid() )
        {
            Rectangle aVisArea = mrView.GetVisibleArea( mrView.FindWin( const_cast< Window* > (&mrWindow) ) );

            MapMode aMapMode(mrWindow.GetMapMode());
            aMapMode.SetOrigin(Point());
            return mrWindow.LogicToPixel( aVisArea, aMapMode );
        }

        return Rectangle();
    }

    Point AccessibleOutlineEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
    {
        if( IsValid() && mrView.GetModel() )
        {
            Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
                                                      MapMode(mrView.GetModel()->GetScaleUnit()) ) );
            MapMode aMapMode(mrWindow.GetMapMode());
            aMapMode.SetOrigin(Point());
            return mrWindow.LogicToPixel( aPoint, aMapMode );
        }

        return Point();
    }

    Point AccessibleOutlineEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
    {
        if( IsValid() && mrView.GetModel() )
        {
            MapMode aMapMode(mrWindow.GetMapMode());
            aMapMode.SetOrigin(Point());
            Point aPoint( mrWindow.PixelToLogic( rPoint, aMapMode ) );
            return OutputDevice::LogicToLogic( aPoint,
                                               MapMode(mrView.GetModel()->GetScaleUnit()),
                                               rMapMode );
        }

        return Point();
    }

    void AccessibleOutlineEditSource::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
    {
        const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );

        if( pSdrHint )
        {
            switch( pSdrHint->GetKind() )
            {
                case HINT_MODELCLEARED:
                    // model is dying under us, going defunc
                    if( mpOutliner )
                        mpOutliner->SetNotifyHdl( Link() );
                    mpOutliner = NULL;
                    mpOutlinerView = NULL;
                    Broadcast( TextHint( SFX_HINT_DYING ) );
                    break;
            }
        }
    }

    IMPL_LINK(AccessibleOutlineEditSource, NotifyHdl, EENotify*, aNotify)
    {
        if( aNotify )
        {
            ::std::auto_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( aNotify) );

            if( aHint.get() )
                Broadcast( *aHint.get() );
        }

        return 0;
    }

} // end of namespace accessibility
<commit_msg>INTEGRATION: CWS aw024 (1.7.308); FILE MERGED 2006/09/21 22:53:58 aw 1.7.308.3: RESYNC: (1.8-1.9); FILE MERGED 2005/09/17 10:37:07 aw 1.7.308.2: RESYNC: (1.7-1.8); FILE MERGED 2005/05/19 12:11:20 aw 1.7.308.1: #i39529#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: AccessibleOutlineEditSource.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: ihi $ $Date: 2006-11-14 14:23:31 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#ifndef _SVX_UNOEDHLP_HXX
#include <svx/unoedhlp.hxx>
#endif
#ifndef _SVDOUTL_HXX
#include <svx/svdoutl.hxx>
#endif

#ifndef SD_ACCESSIBILITY_ACCESSIBLE_OUTLINE_EDIT_SOURCE_HXX
#include <AccessibleOutlineEditSource.hxx>
#endif
#ifndef SD_OUTLINE_VIEW_HXX
#include "OutlineView.hxx"
#endif

#ifndef _SDRPAINTWINDOW_HXX
#include <svx/sdrpaintwindow.hxx>
#endif

namespace accessibility
{

    AccessibleOutlineEditSource::AccessibleOutlineEditSource(
        SdrOutliner&    rOutliner,
        SdrView&        rView,
        OutlinerView& rOutlView,
        const ::Window& rViewWindow )
        : mrView( rView ),
          mrWindow( rViewWindow ),
          mpOutliner( &rOutliner ),
          mpOutlinerView( &rOutlView ),
          mTextForwarder( rOutliner, NULL ),
          mViewForwarder( rOutlView )
    {
        // register as listener - need to broadcast state change messages
        rOutliner.SetNotifyHdl( LINK(this, AccessibleOutlineEditSource, NotifyHdl) );
    }

    AccessibleOutlineEditSource::~AccessibleOutlineEditSource()
    {
        if( mpOutliner )
            mpOutliner->SetNotifyHdl( Link() );
        Broadcast( TextHint( SFX_HINT_DYING ) );
    }

    SvxEditSource* AccessibleOutlineEditSource::Clone() const
    {
        return NULL;
    }

    SvxTextForwarder* AccessibleOutlineEditSource::GetTextForwarder()
    {
        // TODO: maybe suboptimal
        if( IsValid() )
            return &mTextForwarder;
        else
            return NULL;
    }

    SvxViewForwarder* AccessibleOutlineEditSource::GetViewForwarder()
    {
        // TODO: maybe suboptimal
        if( IsValid() )
            return this;
        else
            return NULL;
    }

    SvxEditViewForwarder* AccessibleOutlineEditSource::GetEditViewForwarder( sal_Bool )
    {
        // TODO: maybe suboptimal
        if( IsValid() )
        {
            // ignore parameter, we're always in edit mode here
            return &mViewForwarder;
        }
        else
            return NULL;
    }

    void AccessibleOutlineEditSource::UpdateData()
    {
        // NOOP, since we're always working on the 'real' outliner,
        // i.e. changes are immediately reflected on the screen
    }

    SfxBroadcaster& AccessibleOutlineEditSource::GetBroadcaster() const
    {
        return *( const_cast< AccessibleOutlineEditSource* > (this) );
    }

    BOOL AccessibleOutlineEditSource::IsValid() const
    {
        if( mpOutliner && mpOutlinerView )
        {
            // Our view still on outliner?
            ULONG nCurrView, nViews;

            for( nCurrView=0, nViews=mpOutliner->GetViewCount(); nCurrView<nViews; ++nCurrView )
            {
                if( mpOutliner->GetView(nCurrView) == mpOutlinerView )
                    return sal_True;
            }
        }

        return sal_False;
    }

    Rectangle AccessibleOutlineEditSource::GetVisArea() const
    {
        if( IsValid() )
        {
            SdrPaintWindow* pPaintWindow = mrView.FindPaintWindow(mrWindow);
            Rectangle aVisArea;

            if(pPaintWindow)
            {
                aVisArea = pPaintWindow->GetVisibleArea();
            }

            MapMode aMapMode(mrWindow.GetMapMode());
            aMapMode.SetOrigin(Point());
            return mrWindow.LogicToPixel( aVisArea, aMapMode );
        }

        return Rectangle();
    }

    Point AccessibleOutlineEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
    {
        if( IsValid() && mrView.GetModel() )
        {
            Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
                                                      MapMode(mrView.GetModel()->GetScaleUnit()) ) );
            MapMode aMapMode(mrWindow.GetMapMode());
            aMapMode.SetOrigin(Point());
            return mrWindow.LogicToPixel( aPoint, aMapMode );
        }

        return Point();
    }

    Point AccessibleOutlineEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
    {
        if( IsValid() && mrView.GetModel() )
        {
            MapMode aMapMode(mrWindow.GetMapMode());
            aMapMode.SetOrigin(Point());
            Point aPoint( mrWindow.PixelToLogic( rPoint, aMapMode ) );
            return OutputDevice::LogicToLogic( aPoint,
                                               MapMode(mrView.GetModel()->GetScaleUnit()),
                                               rMapMode );
        }

        return Point();
    }

    void AccessibleOutlineEditSource::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
    {
        const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );

        if( pSdrHint )
        {
            switch( pSdrHint->GetKind() )
            {
                case HINT_MODELCLEARED:
                    // model is dying under us, going defunc
                    if( mpOutliner )
                        mpOutliner->SetNotifyHdl( Link() );
                    mpOutliner = NULL;
                    mpOutlinerView = NULL;
                    Broadcast( TextHint( SFX_HINT_DYING ) );
                    break;
            }
        }
    }

    IMPL_LINK(AccessibleOutlineEditSource, NotifyHdl, EENotify*, aNotify)
    {
        if( aNotify )
        {
            ::std::auto_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( aNotify) );

            if( aHint.get() )
                Broadcast( *aHint.get() );
        }

        return 0;
    }

} // end of namespace accessibility
<|endoftext|>


<commit_before>/**
 * \file
 * \brief SignalsCatcherControlBlock class header
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-04-16
 */

#ifndef INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
#define INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_

#include "distortos/SignalAction.hpp"

namespace distortos
{

namespace synchronization
{

/// SignalsCatcherControlBlock class is a structure required by threads for "catching" and "handling" of signals
class SignalsCatcherControlBlock
{
public:

	/// association of signal number with SignalAction
	using Association = std::pair<uint8_t, SignalAction>;

	/// type of uninitialized storage for Association objects
	using Storage = std::aligned_storage<sizeof(Association), alignof(Association)>::type;

	/**
	 * \brief SignalsCatcherControlBlock's constructor
	 */

	constexpr SignalsCatcherControlBlock()
	{

	}
};

}	// namespace synchronization

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
<commit_msg>SignalsCatcherControlBlock: add member variables with pointers to beginning and end of ranges of SignalsCatcherControlBlock::Association objects and SignalsCatcherControlBlock::Storage objects<commit_after>/**
 * \file
 * \brief SignalsCatcherControlBlock class header
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-04-16
 */

#ifndef INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
#define INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_

#include "distortos/SignalAction.hpp"

namespace distortos
{

namespace synchronization
{

/// SignalsCatcherControlBlock class is a structure required by threads for "catching" and "handling" of signals
class SignalsCatcherControlBlock
{
public:

	/// association of signal number with SignalAction
	using Association = std::pair<uint8_t, SignalAction>;

	/// type of uninitialized storage for Association objects
	using Storage = std::aligned_storage<sizeof(Association), alignof(Association)>::type;

	/**
	 * \brief SignalsCatcherControlBlock's constructor
	 */

	constexpr SignalsCatcherControlBlock() :
			associationsBegin_{},
			storageBegin_{},
			storageEnd_{}
	{

	}

private:

	/// pointer to first element of range of Association objects
	Association* associationsBegin_;

	/// union binds \a associationsEnd_ and \a storageBegin_ - these point to the same address
	union
	{
		/// pointer to "one past the last" element of range of Association objects
		Association* associationsEnd_;

		/// pointer to first element of range of Storage objects
		Storage* storageBegin_;
	};

	/// pointer to "one past the last" element of range of Storage objects
	Storage* storageEnd_;
};

}	// namespace synchronization

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014  Daniel Vrátil <dvratil@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "merge.h"
#include "fetchhelper.h"
#include "imapstreamparser.h"
#include "storage/selectquerybuilder.h"
#include "storage/datastore.h"
#include "storage/transaction.h"
#include "storage/parthelper.h"
#include "storage/parttypehelper.h"
#include "storage/itemretriever.h"
#include "storage/partstreamer.h"
#include "connection.h"
#include "handlerhelper.h"
#include <response.h>

#include <libs/imapparser_p.h>
#include <libs/protocol_p.h>

#include <numeric>

using namespace Akonadi;
using namespace Akonadi::Server;

Merge::Merge()
  : AkAppend()
{
}

Merge::~Merge()
{
}

bool Merge::mergeItem( PimItem &newItem, PimItem &currentItem,
                       const ChangedAttributes &itemFlags,
                       const ChangedAttributes &itemTagsRID,
                       const ChangedAttributes &itemTagsGID )
{
    if ( !newItem.rev() > 0 ) {
        currentItem.setRev( newItem.rev() );
    }
    if ( !newItem.remoteId().isEmpty() && currentItem.remoteId() != newItem.remoteId() ) {
      currentItem.setRemoteId( newItem.remoteId() );
      mChangedParts << AKONADI_PARAM_REMOTEID;
    }
    if ( !newItem.remoteRevision().isEmpty() && currentItem.remoteRevision() != newItem.remoteRevision() ) {
      currentItem.setRemoteRevision( newItem.remoteRevision() );
      mChangedParts << AKONADI_PARAM_REMOTEREVISION;
    }
    if ( !newItem.gid().isEmpty() && currentItem.gid() != newItem.gid() ) {
      currentItem.setGid( newItem.gid() );
      mChangedParts << AKONADI_PARAM_GID;
    }
    if ( newItem.datetime().isValid() ) {
        currentItem.setDatetime( newItem.datetime() );
    }
    currentItem.setAtime( QDateTime::currentDateTime() );

    // Only mark dirty when merged from application
    currentItem.setDirty( !connection()->context()->resource().isValid() );

    const Collection col = Collection::retrieveById( newItem.collectionId() );
    if ( itemFlags.incremental ) {
      bool flagsAdded = false, flagsRemoved = false;
      if ( !itemFlags.added.isEmpty() ) {
        const Flag::List addedFlags = HandlerHelper::resolveFlags( itemFlags.added );
        DataStore::self()->appendItemsFlags( PimItem::List() << currentItem, addedFlags,
                                             &flagsAdded, true, col, true );
      }

      if ( !itemFlags.removed.isEmpty() ) {
        const Flag::List removedFlags = HandlerHelper::resolveFlags( itemFlags.removed );
        DataStore::self()->removeItemsFlags( PimItem::List() << currentItem, removedFlags,
                                             &flagsRemoved, true );
      }

      if ( flagsAdded || flagsRemoved ) {
        mChangedParts << AKONADI_PARAM_FLAGS;
      }
    } else if ( !itemFlags.added.isEmpty() ) {
      bool flagsChanged = false;
      const Flag::List flags = HandlerHelper::resolveFlags( itemFlags.added );
      DataStore::self()->setItemsFlags( PimItem::List() << currentItem, flags,
                                        &flagsChanged, true );
      if ( flagsChanged ) {
        mChangedParts << AKONADI_PARAM_FLAGS;
      }
    }

    if ( itemTagsRID.incremental ) {
      bool tagsAdded = false, tagsRemoved = false;
      if ( !itemTagsRID.added.isEmpty() ) {
        const Tag::List addedTags = HandlerHelper::resolveTagsByRID( itemTagsRID.added, connection()->context() );
        DataStore::self()->appendItemsTags( PimItem::List() << currentItem, addedTags,
                                            &tagsAdded, true, col, true );
      }

      if ( !itemTagsRID.removed.isEmpty() ) {
        const Tag::List removedTags = HandlerHelper::resolveTagsByRID( itemTagsRID.removed, connection()->context() );
        DataStore::self()->removeItemsTags( PimItem::List() << currentItem, removedTags,
                                            &tagsRemoved, true );
      }

      if ( tagsAdded || tagsRemoved ) {
        mChangedParts << AKONADI_PARAM_TAGS;
      }
    } else if ( !itemTagsRID.added.isEmpty() ) {
      bool tagsChanged = false;
      const Tag::List tags = HandlerHelper::resolveTagsByRID( itemTagsRID.added, connection()->context() );
      DataStore::self()->setItemsTags( PimItem::List() << currentItem, tags,
                                       &tagsChanged, true );
      if ( tagsChanged ) {
        mChangedParts << AKONADI_PARAM_TAGS;
      }
    }

    if ( itemTagsGID.incremental ) {
      bool tagsAdded = false, tagsRemoved = false;
      if ( !itemTagsGID.added.isEmpty() ) {
        const Tag::List addedTags = HandlerHelper::resolveTagsByGID( itemTagsGID.added );
        DataStore::self()->appendItemsTags( PimItem::List() << currentItem, addedTags,
                                            &tagsAdded, true, col, true );
      }

      if ( !itemTagsGID.removed.isEmpty() ) {
        const Tag::List removedTags = HandlerHelper::resolveTagsByGID( itemTagsGID.removed );
        DataStore::self()->removeItemsTags( PimItem::List() << currentItem, removedTags,
                                            &tagsRemoved, true );
      }

      if ( tagsAdded || tagsRemoved ) {
        mChangedParts << AKONADI_PARAM_TAGS;
      }
    } else if ( !itemTagsGID.added.isEmpty() ) {
      bool tagsChanged = false;
      const Tag::List tags = HandlerHelper::resolveTagsByGID( itemTagsGID.added );
      DataStore::self()->setItemsTags( PimItem::List() << currentItem, tags,
                                       &tagsChanged, true );
      if ( tagsChanged ) {
        mChangedParts << AKONADI_PARAM_TAGS;
      }
    }

    Part::List existingParts = Part::retrieveFiltered( Part::pimItemIdColumn(), currentItem.id() );
    QMap<QByteArray, qint64> partsSizes;
    Q_FOREACH ( const Part &part, existingParts ) {
      partsSizes.insert( PartTypeHelper::fullName( part.partType() ).toLatin1(), part.datasize() );
    }

    PartStreamer streamer(connection(), m_streamParser, currentItem);
    connect( &streamer, SIGNAL(responseAvailable(Akonadi::Server::Response)),
             this, SIGNAL(responseAvailable(Akonadi::Server::Response)) );
    m_streamParser->beginList();
    while ( !m_streamParser->atListEnd() ) {
      QByteArray partName;
      qint64 partSize;
      QByteArray command = m_streamParser->readString();
      bool changed = false;
      if ( command.isEmpty() ) {
        throw HandlerException( "Syntax error" );
      }

      if ( command.startsWith( '-' ) ) {
        command = command.mid( 1 );
        Q_FOREACH ( const Part &part, existingParts ) {
          if ( part.partType().name() == QString::fromUtf8( command ) ) {
            DataStore::self()->removeItemParts( currentItem, QList<QByteArray>() << command );
            mChangedParts << command;
            partsSizes.remove( command );
            break;
          }
        }
        break;
      } else if ( command.startsWith( '+' ) ) {
        command = command.mid( 1 );
      }

      if ( !streamer.stream( command, true, partName, partSize, &changed ) ) {
        return failureResponse( streamer.error() );
      }
      if ( changed ) {
        mChangedParts << partName;
        partsSizes.insert( partName, partSize );
      }
    }

    qint64 size = std::accumulate( partsSizes.begin(), partsSizes.end(), 0);
    currentItem.setSize( size );

    // Store all changes
    if ( !currentItem.update() ) {
      return failureResponse( "Failed to store merged item" );
    }

    return true;
}

bool Merge::notify( const PimItem &item, const Collection &collection )
{
    if ( !mChangedParts.isEmpty() ) {
      DataStore::self()->notificationCollector()->itemChanged( item, mChangedParts, collection );
    }

    return true;
}

bool Merge::sendResponse( const QByteArray &responseStr, const PimItem &item )
{
    ImapSet set;
    set.add( QVector<qint64>() << item.id() );
    Scope scope( Scope::Uid );
    scope.setUidSet( set );

    FetchScope fetchScope;
    // FetchHelper requires collection context
    fetchScope.setAllAttributes( true );
    fetchScope.setFullPayload( true );
    fetchScope.setAncestorDepth( 1 );
    fetchScope.setCacheOnly( true );
    fetchScope.setExternalPayloadSupported( true );
    fetchScope.setFlagsRequested( true );
    fetchScope.setGidRequested( true );
    fetchScope.setMTimeRequested( true );
    fetchScope.setRemoteIdRequested( true );
    fetchScope.setRemoteRevisionRequested( true );
    fetchScope.setSizeRequested( true );
    fetchScope.setTagsRequested( true );

    FetchHelper fetch( connection(), scope, fetchScope );
    connect( &fetch, SIGNAL(responseAvailable(Akonadi::Server::Response)),
             this, SIGNAL(responseAvailable(Akonadi::Server::Response)) );
    if ( !fetch.fetchItems( AKONADI_CMD_ITEMFETCH ) ) {
      return failureResponse( "Failed to retrieve merged item" );
    }

    Response response;
    response.setTag( tag() );
    response.setSuccess();
    response.setString( responseStr );
    Q_EMIT responseAvailable( response );
    return true;
}

bool Merge::parseStream()
{
    const QList<QByteArray> mergeParts = m_streamParser->readParenthesizedList();

    DataStore *db = DataStore::self();
    Transaction transaction( db );

    Collection parentCol;
    ChangedAttributes itemFlags, itemTagsRID, itemTagsGID;
    PimItem item;
    // Parse the rest of the command, assuming X-AKAPPEND syntax
    if ( !buildPimItem( item, parentCol, itemFlags, itemTagsRID, itemTagsGID ) ) {
      return false;
    }

    bool silent = false;

    // Merging is always restricted to the same collection and mimetype
    SelectQueryBuilder<PimItem> qb;
    qb.addValueCondition( PimItem::collectionIdColumn(), Query::Equals, parentCol.id() );
    qb.addValueCondition( PimItem::mimeTypeIdColumn(), Query::Equals, item.mimeTypeId() );
    Q_FOREACH ( const QByteArray &part, mergeParts ) {
      if ( part == AKONADI_PARAM_GID ) {
        qb.addValueCondition( PimItem::gidColumn(), Query::Equals, item.gid() );
      } else if ( part == AKONADI_PARAM_REMOTEID ) {
        qb.addValueCondition( PimItem::remoteIdColumn(), Query::Equals, item.remoteId() );
      } else if ( part == AKONADI_PARAM_SILENT ) {
        silent = true;
      } else {
        throw HandlerException( "Only merging by RID or GID is allowed" );
      }
    }

    if ( !qb.exec() ) {
      return failureResponse( "Failed to query database for item" );
    }

    QVector<PimItem> result = qb.result();
    if ( result.count() == 0 ) {
      // No item with such GID/RID exists, so call AkAppend::insert() and behave
      // like if this was a new item
      if ( !insertItem( item, parentCol, itemFlags.added, itemTagsRID.added, itemTagsGID.added ) ) {
        return false;
      }
      if ( !transaction.commit() ) {
        return failureResponse( "Failed to commit transaction" );
      }
      AkAppend::notify( item, parentCol );
      return AkAppend::sendResponse( "Append completed", item );

    } else if ( result.count() == 1 ) {
      // Item with matching GID/RID combination exists, so merge this item into it
      // and send itemChanged()
      PimItem existingItem = result.first();
      if ( !mergeItem( item, existingItem, itemFlags, itemTagsRID, itemTagsGID ) ) {
        return false;
      }
      if ( !transaction.commit() ) {
        return failureResponse( "Failed to commit transaction" );
      }

      notify( existingItem, parentCol );
      if ( silent ) {
          return AkAppend::sendResponse( "Merge completed", existingItem );
      } else {
          return sendResponse( "Merge completed", existingItem );
      }

    } else {
      Q_FOREACH (const PimItem &item, result) {
          qDebug() << item.id() << item.remoteId() << item.gid();
      }
      // Nor GID or RID are guaranteed to be unique, so make sure we don't merge
      // something we don't want
      return failureResponse( "Multiple merge candidates, aborting" );
    }
}

<commit_msg>Fix compiler warning in MERGE handler<commit_after>/*
 * Copyright (C) 2014  Daniel Vrátil <dvratil@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "merge.h"
#include "fetchhelper.h"
#include "imapstreamparser.h"
#include "storage/selectquerybuilder.h"
#include "storage/datastore.h"
#include "storage/transaction.h"
#include "storage/parthelper.h"
#include "storage/parttypehelper.h"
#include "storage/itemretriever.h"
#include "storage/partstreamer.h"
#include "connection.h"
#include "handlerhelper.h"
#include <response.h>

#include <libs/imapparser_p.h>
#include <libs/protocol_p.h>

#include <numeric>

using namespace Akonadi;
using namespace Akonadi::Server;

Merge::Merge()
  : AkAppend()
{
}

Merge::~Merge()
{
}

bool Merge::mergeItem( PimItem &newItem, PimItem &currentItem,
                       const ChangedAttributes &itemFlags,
                       const ChangedAttributes &itemTagsRID,
                       const ChangedAttributes &itemTagsGID )
{
    if ( newItem.rev() > 0 ) {
        currentItem.setRev( newItem.rev() );
    }
    if ( !newItem.remoteId().isEmpty() && currentItem.remoteId() != newItem.remoteId() ) {
      currentItem.setRemoteId( newItem.remoteId() );
      mChangedParts << AKONADI_PARAM_REMOTEID;
    }
    if ( !newItem.remoteRevision().isEmpty() && currentItem.remoteRevision() != newItem.remoteRevision() ) {
      currentItem.setRemoteRevision( newItem.remoteRevision() );
      mChangedParts << AKONADI_PARAM_REMOTEREVISION;
    }
    if ( !newItem.gid().isEmpty() && currentItem.gid() != newItem.gid() ) {
      currentItem.setGid( newItem.gid() );
      mChangedParts << AKONADI_PARAM_GID;
    }
    if ( newItem.datetime().isValid() ) {
        currentItem.setDatetime( newItem.datetime() );
    }
    currentItem.setAtime( QDateTime::currentDateTime() );

    // Only mark dirty when merged from application
    currentItem.setDirty( !connection()->context()->resource().isValid() );

    const Collection col = Collection::retrieveById( newItem.collectionId() );
    if ( itemFlags.incremental ) {
      bool flagsAdded = false, flagsRemoved = false;
      if ( !itemFlags.added.isEmpty() ) {
        const Flag::List addedFlags = HandlerHelper::resolveFlags( itemFlags.added );
        DataStore::self()->appendItemsFlags( PimItem::List() << currentItem, addedFlags,
                                             &flagsAdded, true, col, true );
      }

      if ( !itemFlags.removed.isEmpty() ) {
        const Flag::List removedFlags = HandlerHelper::resolveFlags( itemFlags.removed );
        DataStore::self()->removeItemsFlags( PimItem::List() << currentItem, removedFlags,
                                             &flagsRemoved, true );
      }

      if ( flagsAdded || flagsRemoved ) {
        mChangedParts << AKONADI_PARAM_FLAGS;
      }
    } else if ( !itemFlags.added.isEmpty() ) {
      bool flagsChanged = false;
      const Flag::List flags = HandlerHelper::resolveFlags( itemFlags.added );
      DataStore::self()->setItemsFlags( PimItem::List() << currentItem, flags,
                                        &flagsChanged, true );
      if ( flagsChanged ) {
        mChangedParts << AKONADI_PARAM_FLAGS;
      }
    }

    if ( itemTagsRID.incremental ) {
      bool tagsAdded = false, tagsRemoved = false;
      if ( !itemTagsRID.added.isEmpty() ) {
        const Tag::List addedTags = HandlerHelper::resolveTagsByRID( itemTagsRID.added, connection()->context() );
        DataStore::self()->appendItemsTags( PimItem::List() << currentItem, addedTags,
                                            &tagsAdded, true, col, true );
      }

      if ( !itemTagsRID.removed.isEmpty() ) {
        const Tag::List removedTags = HandlerHelper::resolveTagsByRID( itemTagsRID.removed, connection()->context() );
        DataStore::self()->removeItemsTags( PimItem::List() << currentItem, removedTags,
                                            &tagsRemoved, true );
      }

      if ( tagsAdded || tagsRemoved ) {
        mChangedParts << AKONADI_PARAM_TAGS;
      }
    } else if ( !itemTagsRID.added.isEmpty() ) {
      bool tagsChanged = false;
      const Tag::List tags = HandlerHelper::resolveTagsByRID( itemTagsRID.added, connection()->context() );
      DataStore::self()->setItemsTags( PimItem::List() << currentItem, tags,
                                       &tagsChanged, true );
      if ( tagsChanged ) {
        mChangedParts << AKONADI_PARAM_TAGS;
      }
    }

    if ( itemTagsGID.incremental ) {
      bool tagsAdded = false, tagsRemoved = false;
      if ( !itemTagsGID.added.isEmpty() ) {
        const Tag::List addedTags = HandlerHelper::resolveTagsByGID( itemTagsGID.added );
        DataStore::self()->appendItemsTags( PimItem::List() << currentItem, addedTags,
                                            &tagsAdded, true, col, true );
      }

      if ( !itemTagsGID.removed.isEmpty() ) {
        const Tag::List removedTags = HandlerHelper::resolveTagsByGID( itemTagsGID.removed );
        DataStore::self()->removeItemsTags( PimItem::List() << currentItem, removedTags,
                                            &tagsRemoved, true );
      }

      if ( tagsAdded || tagsRemoved ) {
        mChangedParts << AKONADI_PARAM_TAGS;
      }
    } else if ( !itemTagsGID.added.isEmpty() ) {
      bool tagsChanged = false;
      const Tag::List tags = HandlerHelper::resolveTagsByGID( itemTagsGID.added );
      DataStore::self()->setItemsTags( PimItem::List() << currentItem, tags,
                                       &tagsChanged, true );
      if ( tagsChanged ) {
        mChangedParts << AKONADI_PARAM_TAGS;
      }
    }

    Part::List existingParts = Part::retrieveFiltered( Part::pimItemIdColumn(), currentItem.id() );
    QMap<QByteArray, qint64> partsSizes;
    Q_FOREACH ( const Part &part, existingParts ) {
      partsSizes.insert( PartTypeHelper::fullName( part.partType() ).toLatin1(), part.datasize() );
    }

    PartStreamer streamer(connection(), m_streamParser, currentItem);
    connect( &streamer, SIGNAL(responseAvailable(Akonadi::Server::Response)),
             this, SIGNAL(responseAvailable(Akonadi::Server::Response)) );
    m_streamParser->beginList();
    while ( !m_streamParser->atListEnd() ) {
      QByteArray partName;
      qint64 partSize;
      QByteArray command = m_streamParser->readString();
      bool changed = false;
      if ( command.isEmpty() ) {
        throw HandlerException( "Syntax error" );
      }

      if ( command.startsWith( '-' ) ) {
        command = command.mid( 1 );
        Q_FOREACH ( const Part &part, existingParts ) {
          if ( part.partType().name() == QString::fromUtf8( command ) ) {
            DataStore::self()->removeItemParts( currentItem, QList<QByteArray>() << command );
            mChangedParts << command;
            partsSizes.remove( command );
            break;
          }
        }
        break;
      } else if ( command.startsWith( '+' ) ) {
        command = command.mid( 1 );
      }

      if ( !streamer.stream( command, true, partName, partSize, &changed ) ) {
        return failureResponse( streamer.error() );
      }
      if ( changed ) {
        mChangedParts << partName;
        partsSizes.insert( partName, partSize );
      }
    }

    qint64 size = std::accumulate( partsSizes.begin(), partsSizes.end(), 0);
    currentItem.setSize( size );

    // Store all changes
    if ( !currentItem.update() ) {
      return failureResponse( "Failed to store merged item" );
    }

    return true;
}

bool Merge::notify( const PimItem &item, const Collection &collection )
{
    if ( !mChangedParts.isEmpty() ) {
      DataStore::self()->notificationCollector()->itemChanged( item, mChangedParts, collection );
    }

    return true;
}

bool Merge::sendResponse( const QByteArray &responseStr, const PimItem &item )
{
    ImapSet set;
    set.add( QVector<qint64>() << item.id() );
    Scope scope( Scope::Uid );
    scope.setUidSet( set );

    FetchScope fetchScope;
    // FetchHelper requires collection context
    fetchScope.setAllAttributes( true );
    fetchScope.setFullPayload( true );
    fetchScope.setAncestorDepth( 1 );
    fetchScope.setCacheOnly( true );
    fetchScope.setExternalPayloadSupported( true );
    fetchScope.setFlagsRequested( true );
    fetchScope.setGidRequested( true );
    fetchScope.setMTimeRequested( true );
    fetchScope.setRemoteIdRequested( true );
    fetchScope.setRemoteRevisionRequested( true );
    fetchScope.setSizeRequested( true );
    fetchScope.setTagsRequested( true );

    FetchHelper fetch( connection(), scope, fetchScope );
    connect( &fetch, SIGNAL(responseAvailable(Akonadi::Server::Response)),
             this, SIGNAL(responseAvailable(Akonadi::Server::Response)) );
    if ( !fetch.fetchItems( AKONADI_CMD_ITEMFETCH ) ) {
      return failureResponse( "Failed to retrieve merged item" );
    }

    Response response;
    response.setTag( tag() );
    response.setSuccess();
    response.setString( responseStr );
    Q_EMIT responseAvailable( response );
    return true;
}

bool Merge::parseStream()
{
    const QList<QByteArray> mergeParts = m_streamParser->readParenthesizedList();

    DataStore *db = DataStore::self();
    Transaction transaction( db );

    Collection parentCol;
    ChangedAttributes itemFlags, itemTagsRID, itemTagsGID;
    PimItem item;
    // Parse the rest of the command, assuming X-AKAPPEND syntax
    if ( !buildPimItem( item, parentCol, itemFlags, itemTagsRID, itemTagsGID ) ) {
      return false;
    }

    bool silent = false;

    // Merging is always restricted to the same collection and mimetype
    SelectQueryBuilder<PimItem> qb;
    qb.addValueCondition( PimItem::collectionIdColumn(), Query::Equals, parentCol.id() );
    qb.addValueCondition( PimItem::mimeTypeIdColumn(), Query::Equals, item.mimeTypeId() );
    Q_FOREACH ( const QByteArray &part, mergeParts ) {
      if ( part == AKONADI_PARAM_GID ) {
        qb.addValueCondition( PimItem::gidColumn(), Query::Equals, item.gid() );
      } else if ( part == AKONADI_PARAM_REMOTEID ) {
        qb.addValueCondition( PimItem::remoteIdColumn(), Query::Equals, item.remoteId() );
      } else if ( part == AKONADI_PARAM_SILENT ) {
        silent = true;
      } else {
        throw HandlerException( "Only merging by RID or GID is allowed" );
      }
    }

    if ( !qb.exec() ) {
      return failureResponse( "Failed to query database for item" );
    }

    QVector<PimItem> result = qb.result();
    if ( result.count() == 0 ) {
      // No item with such GID/RID exists, so call AkAppend::insert() and behave
      // like if this was a new item
      if ( !insertItem( item, parentCol, itemFlags.added, itemTagsRID.added, itemTagsGID.added ) ) {
        return false;
      }
      if ( !transaction.commit() ) {
        return failureResponse( "Failed to commit transaction" );
      }
      AkAppend::notify( item, parentCol );
      return AkAppend::sendResponse( "Append completed", item );

    } else if ( result.count() == 1 ) {
      // Item with matching GID/RID combination exists, so merge this item into it
      // and send itemChanged()
      PimItem existingItem = result.first();
      if ( !mergeItem( item, existingItem, itemFlags, itemTagsRID, itemTagsGID ) ) {
        return false;
      }
      if ( !transaction.commit() ) {
        return failureResponse( "Failed to commit transaction" );
      }

      notify( existingItem, parentCol );
      if ( silent ) {
          return AkAppend::sendResponse( "Merge completed", existingItem );
      } else {
          return sendResponse( "Merge completed", existingItem );
      }

    } else {
      Q_FOREACH (const PimItem &item, result) {
          qDebug() << item.id() << item.remoteId() << item.gid();
      }
      // Nor GID or RID are guaranteed to be unique, so make sure we don't merge
      // something we don't want
      return failureResponse( "Multiple merge candidates, aborting" );
    }
}

<|endoftext|>


<commit_before>// Time echo -e "1 1\n1 2\n2 3\n3 4\n4 5" |./bacon playedin.csv
// time echo -e "1 1\n1 2" |./bacon playedin.csv

/*
Some numbers:
Max ActorID: 1971696
NRows: 17316773-1
Max MovieID: 1151758
*/

#include <iostream>
#include <ios>
#include <fstream>
#include <vector>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <list>
#include <forward_list>
#include <thread>
//#include <mutex>

#include <chrono>		// should allow high precision timing

using namespace std;

//static std::mutex barrier;

// BAD CODING!!! <3
//
int *actor_keys = new int[1971696];
int *act2mov_actors = new int[1971696];
int *act2mov_movies = new int[17316773-1];
int *mov2act_movies = new int[1151758];
int *mov2act_actors = new int[17316773-1]();

// Breadth-First Search
int BFS(
        int *actor_keys,
        int *act2mov_actors,
        int *act2mov_movies,
        int *mov2act_movies,
        int *mov2act_actors,
        size_t actorid2,
        forward_list<size_t> current_nodes,
        bool *visited
    ) {

    // If BFS is called on an empty list of nodes return -1
    if(current_nodes.empty()) {
        return -1;
    }

    // Now we want to find all neighbours of each of the current nodes
    forward_list<size_t> neighbours;

    // For all current actors
    for(size_t i : current_nodes) {
        // Get all movies

      // for better performance eliminate use of actor_keys while accessing the array
      // better use something like local IDs, i.e. number of occurance in the read list
      // and translate true ID to this number
      // this translation is only neede once when query is read
        for(size_t j = act2mov_actors[actor_keys[i]-1]; j < act2mov_actors[actor_keys[i]]; j++) {
            int movie = act2mov_movies[j];
            // For each movie find all actors
            for(size_t k=mov2act_movies[movie-1]; k<mov2act_movies[movie]; k++){
                size_t new_actor = mov2act_actors[k];
                // If he has not been inspected yet add him to neighbours

		// maybe use a more condensed data structure
                if(!visited[new_actor]) {
                    // If it is the actor2 we are looking for return 1 as distance
                    if(new_actor==actorid2){
                        return 1;
                    }
                    visited[new_actor] = 1;
                    neighbours.push_front(new_actor);
                }
            }
        }
    }

    // Now perform BFS on the neighbours we just found
    int count = BFS(
        actor_keys, act2mov_actors, act2mov_movies,
        mov2act_movies, mov2act_actors,
        actorid2, neighbours, visited);

    // If BFS returns -1 we pass that forward
    if(count == -1) {
        return -1;
    }
    // If BFS returns a distance we have to increase that distance by 1
    return ++count;
}

void BFSThread(size_t thread_a1, size_t thread_a2, int *dist_thread, size_t i){
    if(thread_a1 == thread_a2){
            dist_thread[i] = 0;
            return;
    }

    bool *visited = new bool[1971696]();
    // Boolean to save if actor i has been visited or not
    // Nodes are the ones we are visiting right now - We'll want to find their neighbours with each iteration of BFS
    // unordered_set<size_t> current_nodes;
    forward_list<size_t> current_nodes;
    // We start with only actorid1
    current_nodes.push_front(thread_a1);
    int dist;
    // Start Breadth-First-Search
    dist = BFS(
        actor_keys, act2mov_actors, act2mov_movies,
        mov2act_movies, mov2act_actors,
        thread_a2, current_nodes, visited);
    // Write on global dist variable
    // std::lock_guard<std::mutex> block_threads_until_finish_this_job(barrier);
    cout << "Process: " << i << " Distance: " << dist << endl;
    dist_thread[i] = dist;

    // delete unsused variable
    delete[] visited;
}

int main(int argc, char** argv) {

  // proper timing of actual code execution
  auto start_time = chrono::high_resolution_clock::now();

    // Movie to actor map - Will be replaced later
    vector<vector<size_t>> M(1151758+1);

    // Open file and figre out length
    int handle = open(argv[1],O_RDONLY);
    if (handle<0) return 1;
    lseek(handle,0,SEEK_END);
    long length = lseek(handle,0,SEEK_CUR);

    // Map file into address space
    auto data = static_cast<const char*>(mmap(nullptr,length,PROT_READ,MAP_SHARED,handle,0));
    auto dataLimit = data + length;

    /* Read file and create our datatypes
    We store the actor to movie relation in a CSR and movie to actor in a map
    */
    const char* line = data;
    int actor_index = -1;
    int m1_current = 0;
    int last_actor = 0;
    for (const char* current=data;current!=dataLimit;) {
        const char* last=line;
        unsigned column=0;
        size_t actor=0;
        size_t movie=0;
        for (;current!=dataLimit;++current) {
            char c=*current;
            if (c==',') {
                    last=current+1;
                    ++column;
            }else if (c=='\n') {
                // Insert entry into Movie->Actor Map
                M[movie].push_back(actor);

                /* Check if the actor is different to the last one
                If yes increase actor_index and add entry to actor_keys */
                if(actor != last_actor){
                    ++actor_index;
                    actor_keys[actor] = actor_index;
                }

                act2mov_actors[actor_index] = m1_current+1;
                // Insert movie to list
                act2mov_movies[m1_current] = movie;
                // Update index
                ++m1_current;

                last_actor = actor;
                ++current;
                break;
            }else if (column==0) {
                    actor=10*actor+c-'0';
            }else if (column==1) {
                    movie=10*movie+c-'0';
            }
        }
    }

    cout << "File eingelesen" << endl;
    // return 0;

    // Create CSR for movie to actor relation
    int iterator = 0;
    for(size_t movie_id=1; movie_id<=1151758; movie_id++){
        for(size_t actor : M.at(movie_id)){
            mov2act_actors[iterator] = actor;
            //mov2act_movies[movie_id] = ++iterator;
	    ++iterator;
        }
	// don't acces item too often
	mov2act_movies[movie_id] = iterator;
    }
    cout << "Created Movie to Actor!" << endl;
    // return 0;

    // While there is an input: read, store, compute
    size_t actorid1;
    size_t actorid2;
    vector<size_t> actor1;
    vector<size_t> actor2;

    // switch input
    // if there is a second argument read from this file
    // if not the use std::cin

    istream * input_stream = &cin;
    ifstream  f;

    if(argc > 2)
      {
	f.open(argv[2]);
	input_stream = &f;
	cout << "Read from file: " << argv[2] << endl;
      }

    while( (*input_stream >> actorid1) && (*input_stream >> actorid2) )
      {
	cout << "Input " << actorid1 << " : " <<  actorid2 << endl;
	actor1.push_back(actorid1);
	actor2.push_back(actorid2);
      }

    // while((cin >> actorid1) && (cin >> actorid2)) {
    //     actor1.push_front(actorid1);
    //     actor2.push_front(actorid2);
    // }

    size_t inputlen = actor1.size();
    int *distance = new int[inputlen];
    thread *thread_arr = new thread[inputlen];
    for(int time_counter = 0; time_counter<1; ++time_counter)
      {
	//size_t inputlen = actor1.size();
	//int *distance = new int[inputlen];
	//thread *thread_arr = new thread[inputlen];

    for(size_t i=0; i < inputlen; i++){
        thread_arr[i] = thread(BFSThread, actor1[i], actor2[i], distance, i);
    }
    cout << "Threading started" << endl;
    for(size_t i=0; i < inputlen; i++){
        thread_arr[i].join();
    }
      }
    // timing
    auto end_time = chrono::high_resolution_clock::now();

    auto passed_usecs = chrono::duration_cast<chrono::microseconds>(end_time - start_time);
    double elapsed_u = (double) passed_usecs.count();
    double elapsed = elapsed_u / (1000.0 * 1000.0);
    // cout << "Passed time: " << passed_usecs.count() << " microseconds" << endl << endl;
    cout << endl << "Passed time: " << elapsed << " seconds" << endl << endl;

    for(size_t j=0; j<inputlen; j++){
        cout << distance[j] << endl;
    }
    return 0;
}
<commit_msg>minor changes - same programm as after jonas but looked through some comments<commit_after>// Time echo -e "1 1\n1 2\n2 3\n3 4\n4 5" |./bacon playedin.csv
// time echo -e "1 1\n1 2" |./bacon playedin.csv

/*
Some numbers:
Max ActorID: 1971696
NRows: 17316773-1
Max MovieID: 1151758
*/

#include <iostream>
#include <ios>
#include <fstream>
#include <vector>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <list>
#include <forward_list>
#include <thread>
//#include <mutex>

#include <chrono>		// should allow high precision timing

using namespace std;

//static std::mutex barrier;

// BAD CODING!!! <3
//
int *actor_keys = new int[1971696];
int *act2mov_actors = new int[1971696];
int *act2mov_movies = new int[17316773-1];
int *mov2act_movies = new int[1151758];
int *mov2act_actors = new int[17316773-1]();

// Breadth-First Search
int BFS(
        int *actor_keys,
        int *act2mov_actors,
        int *act2mov_movies,
        int *mov2act_movies,
        int *mov2act_actors,
        size_t actorid2,
        forward_list<size_t> current_nodes,
        bool *visited
    ) {

    // If BFS is called on an empty list of nodes return -1
    if(current_nodes.empty()) {
        return -1;
    }

    // Now we want to find all neighbours of each of the current nodes
    forward_list<size_t> neighbours;

    // For all current actors
    for(size_t i : current_nodes) {
        // Get all movies

        // for better performance eliminate use of actor_keys while accessing the array
        // better use something like local IDs, i.e. number of occurance in the read list
        // and translate true ID to this number
        // this translation is only neede once when query is read
        for(size_t j = act2mov_actors[actor_keys[i]-1]; j < act2mov_actors[actor_keys[i]]; j++) {
            int movie = act2mov_movies[j];
            // For each movie find all actors
            for(size_t k=mov2act_movies[movie-1]; k<mov2act_movies[movie]; k++){
                size_t new_actor = mov2act_actors[k];
                // If he has not been inspected yet add him to neighbours

                // maybe use a more condensed data structure
                if(!visited[new_actor]) {
                    // If it is the actor2 we are looking for return 1 as distance
                    if(new_actor==actorid2){
                        return 1;
                    }
                    visited[new_actor] = 1;
                    neighbours.push_front(new_actor);
                }
            }
        }
    }

    // Now perform BFS on the neighbours we just found
    int count = BFS(
        actor_keys, act2mov_actors, act2mov_movies,
        mov2act_movies, mov2act_actors,
        actorid2, neighbours, visited);

    // If BFS returns -1 we pass that forward
    if(count == -1) {
        return -1;
    }
    // If BFS returns a distance we have to increase that distance by 1
    return ++count;
}

void BFSThread(size_t thread_a1, size_t thread_a2, int *dist_thread, size_t i){
    if(thread_a1 == thread_a2){
            dist_thread[i] = 0;
            return;
    }

    bool *visited = new bool[1971696]();
    // Boolean to save if actor i has been visited or not
    // Nodes are the ones we are visiting right now - We'll want to find their neighbours with each iteration of BFS
    // unordered_set<size_t> current_nodes;
    forward_list<size_t> current_nodes;
    // We start with only actorid1
    current_nodes.push_front(thread_a1);
    int dist;
    // Start Breadth-First-Search
    dist = BFS(
        actor_keys, act2mov_actors, act2mov_movies,
        mov2act_movies, mov2act_actors,
        thread_a2, current_nodes, visited);
    // Write on global dist variable
    // std::lock_guard<std::mutex> block_threads_until_finish_this_job(barrier);
    cout << "Process: " << i << " Distance: " << dist << endl;
    dist_thread[i] = dist;

    // delete unsused variable
    delete[] visited;
}

int main(int argc, char** argv) {

  // proper timing of actual code execution
  auto start_time = chrono::high_resolution_clock::now();

    // Movie to actor map - Will be replaced later
    vector<vector<size_t>> M(1151758+1);

    // Open file and figre out length
    int handle = open(argv[1],O_RDONLY);
    if (handle<0) return 1;
    lseek(handle,0,SEEK_END);
    long length = lseek(handle,0,SEEK_CUR);

    // Map file into address space
    auto data = static_cast<const char*>(mmap(nullptr,length,PROT_READ,MAP_SHARED,handle,0));
    auto dataLimit = data + length;

    /* Read file and create our datatypes
    We store the actor to movie relation in a CSR and movie to actor in a map
    */
    const char* line = data;
    int actor_index = -1;
    int m1_current = 0;
    int last_actor = 0;
    for (const char* current=data;current!=dataLimit;) {
        const char* last=line;
        unsigned column=0;
        size_t actor=0;
        size_t movie=0;
        for (;current!=dataLimit;++current) {
            char c=*current;
            if (c==',') {
                    last=current+1;
                    ++column;
            }else if (c=='\n') {
                // Insert entry into Movie->Actor Map
                M[movie].push_back(actor);

                /* Check if the actor is different to the last one
                If yes increase actor_index and add entry to actor_keys */
                if(actor != last_actor){
                    ++actor_index;
                    actor_keys[actor] = actor_index;
                }

                act2mov_actors[actor_index] = m1_current+1;
                // Insert movie to list
                act2mov_movies[m1_current] = movie;
                // Update index
                ++m1_current;

                last_actor = actor;
                ++current;
                break;
            }else if (column==0) {
                    actor=10*actor+c-'0';
            }else if (column==1) {
                    movie=10*movie+c-'0';
            }
        }
    }

    cout << "File eingelesen" << endl;

    // Create CSR for movie to actor relation
    int iterator = 0;
    for(size_t movie_id=1; movie_id<=1151758; movie_id++){
        for(size_t actor : M.at(movie_id)){
            mov2act_actors[iterator] = actor;
	    ++iterator;
        }
	mov2act_movies[movie_id] = iterator;
    }

    // While there is an input: read, store, compute
    size_t actorid1;
    size_t actorid2;
    vector<size_t> actor1;
    vector<size_t> actor2;

    // // switch input
    // // if there is a second argument read from this file
    // // if not the use std::cin
    // istream * input_stream = &cin;
    // ifstream  f;
    // if(argc > 2)
    //   {
    // f.open(argv[2]);
    // input_stream = &f;
    // cout << "Read from file: " << argv[2] << endl;
    //   }
    // while( (*input_stream >> actorid1) && (*input_stream >> actorid2) )
    //   {
    // cout << "Input " << actorid1 << " : " <<  actorid2 << endl;
    // actor1.push_back(actorid1);
    // actor2.push_back(actorid2);
    //   }

    while((cin >> actorid1) && (cin >> actorid2)) {
        actor1.push_back(actorid1);
        actor2.push_back(actorid2);
    }

    size_t inputlen = actor1.size();
    int *distance = new int[inputlen];
    thread *thread_arr = new thread[inputlen];
    for(int time_counter = 0; time_counter<1; ++time_counter){
        for(size_t i=0; i < inputlen; i++){
            thread_arr[i] = thread(BFSThread, actor1[i], actor2[i], distance, i);
        }
        cout << "Threading started" << endl;
        for(size_t i=0; i < inputlen; i++){
            thread_arr[i].join();
        }
    }

    // timing
    auto end_time = chrono::high_resolution_clock::now();

    auto passed_usecs = chrono::duration_cast<chrono::microseconds>(end_time - start_time);
    double elapsed_u = (double) passed_usecs.count();
    double elapsed = elapsed_u / (1000.0 * 1000.0);
    // cout << "Passed time: " << passed_usecs.count() << " microseconds" << endl << endl;
    cout << endl << "Passed time: " << elapsed << " seconds" << endl << endl;

    for(size_t j=0; j<inputlen; j++){
        cout << distance[j] << endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>#include "dream.h"

void dream_pars_default(dream_pars* p) {
  p->vflag = 0;
  p->maxEvals = 100000;
  p->optimAlg = 1;
  p->numChains = 5;
  p->fn = "";
  p->out_fn = "";
  p->appendFile = 0;
  p->report_interval = 1;
  p->diagnostics = 0;
  p->burnIn = 0;
  p->recalcLik = 0;
  p->noise = 0.05;
  p->bstar_zero = 1e-3;
  p->collapseOutliers = 1;
  p->gelmanEvals = 5000;
  p->loopSteps = 10;
  p->scaleReductionCrit = 1.01;
  p->deltaMax = 2;
  p->pCR_update = 1;
  p->nCR = 3;
  p->reenterBurnin = 0.2;
  p->fun = NULL;
  p->funPars = NULL;
}

void dream_pars_init_vars(dream_pars* p, size_t n) {
  p->nvar = n;
  p->nfree = n;
  p->varLo = (double*) calloc(n,sizeof(double));
  p->varHi = (double*) calloc(n,sizeof(double));
  p->varInit = (double*) calloc(n,sizeof(double));
  p->varLock = (int*) calloc(n,sizeof(int));
  p->varName = new string[n];
  p->scale = new char[n];
}

void dream_pars_free_vars(dream_pars* p) {
  free(p->varLo);
  free(p->varHi);
  free(p->varInit);
  free(p->varLock);
  delete[] p->varName;
  delete[] p->scale;
  p->nvar = 0;
  p->nfree = 0;
}

void dream_pars_read_json(dream_pars* p, rapidjson::Value& jpars) {
  // reading priors from JSON
  rapidjson::Value::MemberIterator m1;
  rapidjson::SizeType _rj;

  // find variable ranges
  rapidjson::Value::MemberIterator _d = jpars.FindMember("pars");
  if (_d == jpars.MemberEnd()) throw "pars";

  rapidjson::Value& d = _d->value;
  dream_pars_init_vars(p,d.Size());

  // variables
  for (rapidjson::SizeType i = 0; i < d.Size(); ++i) {
    m1 = d[i].FindMember("name");
    if (m1 != d[i].MemberEnd()) {
      if (! m1->value.IsString()) throw "Bad varible name.";
      else p->varName[i] = m1->value.GetString();
    }

    m1 = d[i].FindMember("limits");
    if (m1 != d[i].MemberEnd()) {
      if (! m1->value.IsArray()) throw "Bad variables limits.";
      if (m1->value.Size() != 2) throw "Bad variables limits.";
      _rj = 0; p->varLo[i] = m1->value[_rj].GetDouble();
      _rj = 1; p->varHi[i] = m1->value[_rj].GetDouble();
    }

    m1 = d[i].FindMember("lock");
    if (m1 != d[i].MemberEnd()) {
      if (! m1->value.IsDouble()) {
        throw "Locked variable isn't a double.";
      } else {
        p->varLock[i] = 1;
        p->varHi[i] = m1->value.GetDouble();
        p->varLo[i] = p->varHi[i];
        p->varInit[i] = p->varHi[i];
        --(p->nfree);
      }
    }

    m1 = d[i].FindMember("init");
    if (m1 != d[i].MemberEnd()) {
      if (! m1->value.IsDouble()) throw "Bad initial value.";
      p->varInit[i] = m1->value.GetDouble();
    }

    m1 = d[i].FindMember("scale");
    if (m1 != d[i].MemberEnd()) {
      if (! m1->value.IsString()) throw "Bad scale.";
      p->scale[i] = m1->value.GetString()[0];
    } else {
      p->scale[i] = 'n';
    }
  }

  p->deltaMax = (p->nfree-1)/2;

  rapidjson::Value::MemberIterator dream = jpars.FindMember("dream");
  if (dream == jpars.MemberEnd()) throw "No dream section in JSON.";

  rapidjson::Value& dv = dream->value;

  m1 = dv.FindMember("prefix");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsString()) throw "prefix";
    p->out_fn = m1->value.GetString();
  }

  m1 = dv.FindMember("num_chains");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "num_chains";
    p->numChains = m1->value.GetInt();
  }

  m1 = dv.FindMember("max_evals");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "max_evals";
    p->maxEvals = m1->value.GetInt();
  }

  m1 = dv.FindMember("burn_in");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "burn_in";
    p->burnIn = m1->value.GetInt();
  }

  m1 = dv.FindMember("recalc_lik");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "recalc_lik";
    p->recalcLik = m1->value.GetInt();
  }

  m1 = dv.FindMember("gelman_evals");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "gelman_evals";
    p->gelmanEvals = m1->value.GetInt();
  }

  m1 = dv.FindMember("vflag");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "vflag";
    p->vflag = m1->value.GetInt();
  }

  m1 = dv.FindMember("noise");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsDouble()) throw "noise";
    p->noise = m1->value.GetDouble();
  }
}

size_t dream_par_by_name(const dream_pars* p, string name) {
  size_t i = 0;
  while (i < p->nvar) {
    if (p->varName[i] == name) break;
    ++i;
  }
  return i;
}

<commit_msg>pars.<commit_after>#include "dream.h"

void dream_pars_default(dream_pars* p) {
  p->vflag = 0;
  p->maxEvals = 100000;
  p->optimAlg = 1;
  p->numChains = 5;
  p->fn = "";
  p->out_fn = "";
  p->appendFile = 0;
  p->report_interval = 1;
  p->diagnostics = 0;
  p->burnIn = 0;
  p->recalcLik = 0;
  p->noise = 0.05;
  p->bstar_zero = 1e-3;
  p->collapseOutliers = 1;
  p->gelmanEvals = 5000;
  p->loopSteps = 10;
  p->scaleReductionCrit = 1.01;
  p->deltaMax = 2;
  p->pCR_update = 1;
  p->nCR = 3;
  p->reenterBurnin = 0.2;
  p->fun = NULL;
  p->funPars = NULL;
}

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

void dream_pars_init_vars(dream_pars* p, size_t n) {
  p->nvar = n;
  p->nfree = n;
  p->varLo = (double*) calloc(n,sizeof(double));
  p->varHi = (double*) calloc(n,sizeof(double));
  p->varInit = (double*) calloc(n,sizeof(double));
  p->varLock = (int*) calloc(n,sizeof(int));
  p->varName = new string[n];
  p->scale = new char[n];
}

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

void dream_pars_free_vars(dream_pars* p) {
  free(p->varLo);
  free(p->varHi);
  free(p->varInit);
  free(p->varLock);
  delete[] p->varName;
  delete[] p->scale;
  p->nvar = 0;
  p->nfree = 0;
}

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

void dream_set_init(dream_pars* p, int n,
                    const double* init, const string* name,
                    const int* lock, const double* lo,
                    const double* hi, const char* scale)
{
  p->nvar = n;
  p->nfree = n;
  memcpy(p->varInit, init,  n*sizeof(double));
  memcpy(p->varName, name,  n*sizeof(string));
  memcpy(p->varLock, lock,  n*sizeof(int));
  memcpy(p->varLo,   lo,    n*sizeof(double));
  memcpy(p->varHi,   hi,    n*sizeof(double));
  memcpy(p->scale,   scale, n*sizeof(char));
  for (int i = 0; i < n; ++i) if (lock[i]) --(p->nfree);
  p->deltaMax = (p->nfree-1)/2;
}

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

void dream_pars_from_json(dream_pars* p, rapidjson::Value& jpars) {
  // DEPRECATED !!!!!!
  //  remove in next release...

  // reading priors from JSON
  rapidjson::Value::MemberIterator m1;
  rapidjson::SizeType _rj;

  // find variable ranges
  rapidjson::Value::MemberIterator _d = jpars.FindMember("pars");
  if (_d == jpars.MemberEnd()) throw "pars";

  size_t nshifts = 0;
  rapidjson::Value::MemberIterator _s = jpars.FindMember("shifts");
  if (_s == jpars.MemberEnd()) throw "shifts";
  else nshifts = _s->value.Size();

  rapidjson::Value& d = _d->value;
  dream_pars_init_vars(p,(nshifts+1)*d.Size());

  // variables
  size_t j = 0;
  string name = "";
  double lo = 0.0;
  double hi = 0.0;
  char scale = 'n';

  for (rapidjson::SizeType i = 0; i < d.Size(); ++i) {
    m1 = d[i].FindMember("name");
    if (m1 != d[i].MemberEnd()) {
      if (! m1->value.IsString()) {
        name = "";
        throw "Bad varible name.";
      } else {
        name = m1->value.GetString();
      }
    }

    m1 = d[i].FindMember("limits");
    if (m1 != d[i].MemberEnd()) {
      if (! m1->value.IsArray()) throw "Bad variables limits.";
      if (! m1->value.Size() == 2) throw "Bad variables limits.";
      _rj = 0; lo = m1->value[_rj].GetDouble();
      _rj = 1; hi = m1->value[_rj].GetDouble();
    }

    p->varName[j] = name;
    p->varLo[j] = lo;
    p->varHi[j] = hi;
    p->scale[i] = scale;

    m1 = d[i].FindMember("scale");
    if (m1 != d[i].MemberEnd()) {
      if (! m1->value.IsString()) throw "Bad scale.";
      scale = m1->value.GetString()[0];
    } else {
    }

    m1 = d[i].FindMember("lock");
    if (m1 != d[i].MemberEnd()) {
      if (m1->value.IsArray()) {
        if (m1->value.Size() != nshifts) throw "varSize";
        for (size_t k = 0; k < nshifts; ++k) {
          p->varName[j] = name;
          p->varLock[j] = 1;
          p->varHi[j] = m1->value[k].GetDouble();
          p->varLo[j] = p->varHi[i];
          p->varInit[j] = p->varHi[j];
          --(p->nfree);
          ++j;
        }
      } else if (m1->value.IsDouble()) {
        p->varName[j] = name;
        p->varLock[j] = 1;
        p->varHi[j] = m1->value.GetDouble();
        p->varLo[j] = p->varHi[j];
        p->varInit[j] = p->varHi[j];
        --(p->nfree);
        ++j;
      } else {
        throw "Locked variable isn't a double or an array.";
      }
    } else {
      m1 = d[i].FindMember("init");
      p->varInit[i] = m1->value.GetDouble();
      if (m1->value.IsArray()) {
        if (m1->value.Size() != nshifts) throw "varSize";
        for (size_t k = 0; k < nshifts; ++k) {
          p->varName[j] = name;
          p->varLock[j] = 0;
          p->varHi[j] = hi;
          p->varLo[j] = lo;
          p->varInit[j] = m1->value[k].GetDouble();
          ++j;
        }
      } else if (m1->value.IsDouble()) {
        p->varName[j] = name;
        p->varLock[j] = 0;
        p->varHi[j] = hi;
        p->varLo[j] = lo;
        p->varInit[j] = m1->value.GetDouble();
        ++j;
      } else {
        throw "Init variable isn't a double or an array.";
      }
    }
  }

  p->deltaMax = (p->nfree-1)/2;

}

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

void dream_pars_read_json(dream_pars* p, rapidjson::Value& jpars) {
  // reading priors from JSON
  rapidjson::Value::MemberIterator m1;
  rapidjson::SizeType _rj;

  rapidjson::Value::MemberIterator dream = jpars.FindMember("dream");
  if (dream == jpars.MemberEnd()) throw "No dream section in JSON.";

  rapidjson::Value& dv = dream->value;

  m1 = dv.FindMember("prefix");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsString()) throw "prefix";
    p->out_fn = m1->value.GetString();
  }

  m1 = dv.FindMember("num_chains");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "num_chains";
    p->numChains = m1->value.GetInt();
  }

  m1 = dv.FindMember("max_evals");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "max_evals";
    p->maxEvals = m1->value.GetInt();
  }

  m1 = dv.FindMember("burn_in");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "burn_in";
    p->burnIn = m1->value.GetInt();
  }

  m1 = dv.FindMember("recalc_lik");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "recalc_lik";
    p->recalcLik = m1->value.GetInt();
  }

  m1 = dv.FindMember("gelman_evals");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "gelman_evals";
    p->gelmanEvals = m1->value.GetInt();
  }

  m1 = dv.FindMember("vflag");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsInt()) throw "vflag";
    p->vflag = m1->value.GetInt();
  }

  m1 = dv.FindMember("noise");
  if (m1 != dv.MemberEnd()) {
    if (! m1->value.IsDouble()) throw "noise";
    p->noise = m1->value.GetDouble();
  }
}

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

size_t dream_par_by_name(const dream_pars* p, string name) {
  size_t i = 0;
  while (i < p->nvar) {
    if (p->varName[i] == name) break;
    ++i;
  }
  return i;
}

<|endoftext|>


<commit_before><commit_msg>fix sfx2 with Library_merged<commit_after><|endoftext|>