<commit_before>// LineSegment.cpp

#include "LineSegment.h"
#include "Triangle.h"
#include <wx/debug.h>

LineSegment::LineSegment( void )
{
	vertex[0].set( c3ga::vectorE3GA::coord_e1_e2_e3, 0.0, 0.0, 0.0 );
	vertex[1].set( c3ga::vectorE3GA::coord_e1_e2_e3, 0.0, 0.0, 0.0 );
}

LineSegment::LineSegment( const c3ga::vectorE3GA& vertex0, const c3ga::vectorE3GA& vertex1 )
{
	vertex[0] = vertex0;
	vertex[1] = vertex1;
}

/*virtual*/ LineSegment::~LineSegment( void )
{
}

bool LineSegment::TessellateTriangle( const Triangle& triangle, TriangleList& tessellatedTriangleList ) const
{
	VectorArray edgeHitArray;

	for( int i = 0; i < 3; i++ )
	{
		int j = ( i + 1 ) % 3;
		LineSegment edge;
		edge.vertex[0] = triangle.vertex[i].point;
		edge.vertex[1] = triangle.vertex[j].point;

		c3ga::vectorE3GA intersectionPoint;
		if( CalculateIntersectionWith( edge, intersectionPoint, false, true ) )
			edgeHitArray.push_back( intersectionPoint );
	}

	// 0 hits -- we don't cut the triangle.
	// 1 hit -- we're tangent and so don't cut.
	// 2 hits -- we may cut the triangle.
	// 3 hits -- we're tangential here too.
	if( edgeHitArray.size() != 2 )
		return false;

	LineSegment chord;
	chord.vertex[0] = *edgeHitArray.begin();
	chord.vertex[1] = edgeHitArray.back();

	if( !( chord.ContainsPoint( vertex[0] ) || chord.ContainsPoint( vertex[1] ) ||
		ContainsPoint( chord.vertex[0] ) || ContainsPoint( chord.vertex[1] ) ) )
	{
		return false;
	}

	// Get vertex list in CCW order.
	VectorArray vertexArray;	// TODO: May want to replace this with std::list< Triangle::Vertex >.

	for( int i = 0; i < 3; i++ )
	{
		int j = ( i + 1 ) % 3;
		LineSegment edge;
		edge.vertex[0] = triangle.vertex[i].point;
		edge.vertex[1] = triangle.vertex[j].point;

		vertexArray.push_back( edge.vertex[0] );

		// There may be duplicate vertices put on the list, but that's okay.
		for( int k = 0; k < 2; k++ )
			if( edge.ContainsPoint( chord.vertex[k] ) )
				vertexArray.push_back( chord.vertex[k] );	// TODO: New UVs may be as easy as lerps along edges.
	}

	wxASSERT( vertexArray.size() >= 5 );

	c3ga::vectorE3GA center( c3ga::vectorE3GA::coord_e1_e2_e3, 0.0, 0.0, 0.0 );
	for( int i = 0; i < vertexArray.size(); i++ )
		center += vertexArray[i];

	center = center * ( 1.0 / double( vertexArray.size() ) );

	double smallestDistance = 0.0;
	int bestVertex = -1;
	for( int i = 0; i < vertexArray.size(); i++ )
	{
		double distance = c3ga::norm( center - vertexArray[i] );
		if( bestVertex == -1 || distance < smallestDistance )
		{
			smallestDistance = distance;
			bestVertex = i;
		}
	}

	// This is not necessarily the best tessellation, but it should work.
	// I can conceive a recursive way of doing this, but I'm not sure what that gains us.
	for( int i = 0; i < vertexArray.size() - 2; i++ )
	{
		Triangle* triangle = new Triangle();
		triangle->vertex[0].point = vertexArray[ bestVertex ];
		triangle->vertex[1].point = vertexArray[ ( bestVertex + i + 1 ) % vertexArray.size() ];
		triangle->vertex[2].point = vertexArray[ ( bestVertex + i + 2 ) % vertexArray.size() ];
		if( triangle->IsDegenerate() )
			delete triangle;
		else
			tessellatedTriangleList.push_back( triangle );
	}

	return true;
}

double LineSegment::CalculateOrthogonalDistanceToLine( const c3ga::vectorE3GA& point ) const
{
	c3ga::vectorE3GA normal = c3ga::unit( vertex[1] - vertex[0] );
	c3ga::vectorE3GA vector = point - vertex[0];
	double distance = c3ga::norm( c3ga::lc( normal, c3ga::op( vector, normal ) ) );
	return distance;
}

bool LineSegment::CalculateIntersectionWith( const LineSegment& lineSegment, c3ga::vectorE3GA& intersectionPoint, bool mustHitThis, bool mustHitGiven ) const
{
	c3ga::bivectorE3GA bivector = CalculateLineVector() ^ lineSegment.CalculateLineVector();
	if( bivector.get_e1_e2() == 0.0 )
		return false;		// The line segments are parallel.  They either intersect not at all, in a single point, or an infinite number of points; we don't care?

	c3ga::vectorE3GA vector = bivector * c3ga::I3;
	intersectionPoint.set_e1( vector.get_e1() / vector.get_e3() );
	intersectionPoint.set_e2( vector.get_e2() / vector.get_e3() );
	intersectionPoint.set_e3( 0.0 );

	if( mustHitThis && !ContainsPoint( intersectionPoint ) )
		return false;

	if( mustHitGiven && !lineSegment.ContainsPoint( intersectionPoint ) )
		return false;

	return true;
}

c3ga::vectorE3GA LineSegment::CalculateLineVector( void ) const
{
	c3ga::vectorE3GA vector = vertex[1] - vertex[0];
	c3ga::vectorE3GA normal( c3ga::vectorE3GA::coord_e1_e2_e3, -vector.get_e2(), vector.get_e1(), 0.0 );
	normal = c3ga::unit( normal );
	double dot = c3ga::lc( vertex[0], normal );
	vector = normal - c3ga::vectorE3GA( c3ga::vectorE3GA::coord_e1_e2_e3, 0.0, 0.0, dot );
	return vector;
}

bool LineSegment::ContainsPoint( const c3ga::vectorE3GA& point, double eps /*= 1e-7*/ ) const
{
	double totalLength = c3ga::norm( point - vertex[0] ) + c3ga::norm( vertex[1] - point );
	double length = CalculateLength();
	if( fabs( totalLength - length ) < eps )
		return true;
	return false;
}

bool LineSegment::PointOnLine( const c3ga::vectorE3GA& point, double eps /*= 1e-7*/ ) const
{
	c3ga::vectorE3GA vector = CalculateLineVector();
	c3ga::vectorE3GA homogenizedPoint = point;
	homogenizedPoint.set_e3( 1.0 );
	double dot = c3ga::lc( homogenizedPoint, vector );
	if( fabs( dot ) < eps )
		return true;
	return false;
}

double LineSegment::CalculateLength( void ) const
{
	return c3ga::norm( vertex[1] - vertex[0] );
}

// LineSegment.cpp<commit_msg>fix a few bugs in the tessellator...still worried about stability<commit_after>// LineSegment.cpp

#include "LineSegment.h"
#include "Triangle.h"
#include <wx/debug.h>

LineSegment::LineSegment( void )
{
	vertex[0].set( c3ga::vectorE3GA::coord_e1_e2_e3, 0.0, 0.0, 0.0 );
	vertex[1].set( c3ga::vectorE3GA::coord_e1_e2_e3, 0.0, 0.0, 0.0 );
}

LineSegment::LineSegment( const c3ga::vectorE3GA& vertex0, const c3ga::vectorE3GA& vertex1 )
{
	vertex[0] = vertex0;
	vertex[1] = vertex1;
}

/*virtual*/ LineSegment::~LineSegment( void )
{
}

bool LineSegment::TessellateTriangle( const Triangle& triangle, TriangleList& tessellatedTriangleList ) const
{
	VectorArray edgeHitArray;
	double eps = 1e-7;

	for( int i = 0; i < 3; i++ )
	{
		int j = ( i + 1 ) % 3;
		LineSegment edge;
		edge.vertex[0] = triangle.vertex[i].point;
		edge.vertex[1] = triangle.vertex[j].point;

		c3ga::vectorE3GA intersectionPoint;
		if( CalculateIntersectionWith( edge, intersectionPoint, false, true ) )
		{
			int k;
			for( k = 0; k < edgeHitArray.size(); k++ )
				if( c3ga::norm( edgeHitArray[k] - intersectionPoint ) < eps )
					break;

			if( k == edgeHitArray.size() )
				edgeHitArray.push_back( intersectionPoint );
		}
	}

	// 0 hits -- we don't cut the triangle.
	// 1 hit -- we're tangent and so don't cut.
	// 2 distinct hits -- we may cut the triangle.
	// 3 distinct hits -- we're tangential here too.
	if( edgeHitArray.size() != 2 )
		return false;

	LineSegment chord;
	chord.vertex[0] = *edgeHitArray.begin();
	chord.vertex[1] = edgeHitArray.back();

	if( !( chord.ContainsPoint( vertex[0] ) || chord.ContainsPoint( vertex[1] ) ||
		ContainsPoint( chord.vertex[0] ) || ContainsPoint( chord.vertex[1] ) ) )
	{
		return false;
	}

	// Get vertex list in CCW order.
	VectorArray vertexArray;	// TODO: May want to replace this with std::list< Triangle::Vertex >.

	int sharedVertex = -1;

	for( int i = 0; i < 3; i++ )
	{
		int j = ( i + 1 ) % 3;
		LineSegment edge;
		edge.vertex[0] = triangle.vertex[i].point;
		edge.vertex[1] = triangle.vertex[j].point;

		vertexArray.push_back( edge.vertex[0] );

		// There may be duplicate vertices put on the list, but that's okay.
		for( int k = 0; k < 2; k++ )
		{
			if( edge.ContainsPoint( chord.vertex[k] ) )
			{
				// The shared vertex must be one of the two chord points.  Choose one arbitrarily.
				if( sharedVertex == -1 )
					sharedVertex = ( signed )vertexArray.size();

				vertexArray.push_back( chord.vertex[k] );	// TODO: New UVs may be as easy as lerps along edges.
			}
		}
	}

	wxASSERT( vertexArray.size() >= 5 );
	wxASSERT( sharedVertex >= 0 );

	for( int i = 0; i < vertexArray.size() - 2; i++ )
	{
		Triangle* triangle = new Triangle();
		triangle->vertex[0].point = vertexArray[ sharedVertex ];
		triangle->vertex[1].point = vertexArray[ ( sharedVertex + i + 1 ) % vertexArray.size() ];
		triangle->vertex[2].point = vertexArray[ ( sharedVertex + i + 2 ) % vertexArray.size() ];
		if( triangle->IsDegenerate() )
			delete triangle;
		else
			tessellatedTriangleList.push_back( triangle );
	}

	return true;
}

double LineSegment::CalculateOrthogonalDistanceToLine( const c3ga::vectorE3GA& point ) const
{
	c3ga::vectorE3GA normal = c3ga::unit( vertex[1] - vertex[0] );
	c3ga::vectorE3GA vector = point - vertex[0];
	double distance = c3ga::norm( c3ga::lc( normal, c3ga::op( vector, normal ) ) );
	return distance;
}

bool LineSegment::CalculateIntersectionWith( const LineSegment& lineSegment, c3ga::vectorE3GA& intersectionPoint, bool mustHitThis, bool mustHitGiven ) const
{
	c3ga::bivectorE3GA bivector = CalculateLineVector() ^ lineSegment.CalculateLineVector();
	if( bivector.get_e1_e2() == 0.0 )
		return false;		// The line segments are parallel.  They either intersect not at all, in a single point, or an infinite number of points; we don't care?

	c3ga::vectorE3GA vector = bivector * c3ga::I3;
	intersectionPoint.set_e1( vector.get_e1() / vector.get_e3() );
	intersectionPoint.set_e2( vector.get_e2() / vector.get_e3() );
	intersectionPoint.set_e3( 0.0 );

	if( mustHitThis && !ContainsPoint( intersectionPoint ) )
		return false;

	if( mustHitGiven && !lineSegment.ContainsPoint( intersectionPoint ) )
		return false;

	return true;
}

c3ga::vectorE3GA LineSegment::CalculateLineVector( void ) const
{
	c3ga::vectorE3GA vector = vertex[1] - vertex[0];
	c3ga::vectorE3GA normal( c3ga::vectorE3GA::coord_e1_e2_e3, -vector.get_e2(), vector.get_e1(), 0.0 );
	normal = c3ga::unit( normal );
	double dot = c3ga::lc( vertex[0], normal );
	vector = normal - c3ga::vectorE3GA( c3ga::vectorE3GA::coord_e1_e2_e3, 0.0, 0.0, dot );
	return vector;
}

bool LineSegment::ContainsPoint( const c3ga::vectorE3GA& point, double eps /*= 1e-7*/ ) const
{
	double totalLength = c3ga::norm( point - vertex[0] ) + c3ga::norm( vertex[1] - point );
	double length = CalculateLength();
	if( fabs( totalLength - length ) < eps )
		return true;
	return false;
}

bool LineSegment::PointOnLine( const c3ga::vectorE3GA& point, double eps /*= 1e-7*/ ) const
{
	c3ga::vectorE3GA vector = CalculateLineVector();
	c3ga::vectorE3GA homogenizedPoint = point;
	homogenizedPoint.set_e3( 1.0 );
	double dot = c3ga::lc( homogenizedPoint, vector );
	if( fabs( dot ) < eps )
		return true;
	return false;
}

double LineSegment::CalculateLength( void ) const
{
	return c3ga::norm( vertex[1] - vertex[0] );
}

// LineSegment.cpp<|endoftext|>


<commit_before>/*
 * Copyright (c) 2006 - 2018 Stephen F. Booth <me@sbooth.org>
 * See https://github.com/sbooth/SFBAudioEngine/blob/master/LICENSE.txt for license information
 */

#include <taglib/tfilestream.h>
#include <taglib/mp4file.h>

#include "MP4Metadata.h"
#include "CFWrapper.h"
#include "CFErrorUtilities.h"
#include "AddMP4TagToDictionary.h"
#include "SetMP4TagFromMetadata.h"
#include "AddAudioPropertiesToDictionary.h"
#include "CFDictionaryUtilities.h"

namespace {

	void RegisterMP4Metadata() __attribute__ ((constructor));
	void RegisterMP4Metadata()
	{
		SFB::Audio::Metadata::RegisterSubclass<SFB::Audio::MP4Metadata>();
	}

}

#pragma mark Static Methods

CFArrayRef SFB::Audio::MP4Metadata::CreateSupportedFileExtensions()
{
	CFStringRef supportedExtensions [] = { CFSTR("m4a"), CFSTR("mp4") };
	return CFArrayCreate(kCFAllocatorDefault, (const void **)supportedExtensions, 2, &kCFTypeArrayCallBacks);
}

CFArrayRef SFB::Audio::MP4Metadata::CreateSupportedMIMETypes()
{
	CFStringRef supportedMIMETypes [] = { CFSTR("audio/mpeg-4") };
	return CFArrayCreate(kCFAllocatorDefault, (const void **)supportedMIMETypes, 1, &kCFTypeArrayCallBacks);
}

bool SFB::Audio::MP4Metadata::HandlesFilesWithExtension(CFStringRef extension)
{
	if(nullptr == extension)
		return false;

	if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("m4a"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("mp4"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

bool SFB::Audio::MP4Metadata::HandlesMIMEType(CFStringRef mimeType)
{
	if(nullptr == mimeType)
		return false;

	if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/mpeg-4"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

SFB::Audio::Metadata::unique_ptr SFB::Audio::MP4Metadata::CreateMetadata(CFURLRef url)
{
	return unique_ptr(new MP4Metadata(url));
}

#pragma mark Creation and Destruction

SFB::Audio::MP4Metadata::MP4Metadata(CFURLRef url)
	: Metadata(url)
{}

#pragma mark Functionality

bool SFB::Audio::MP4Metadata::_ReadMetadata(CFErrorRef *error)
{
	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, FALSE, buf, PATH_MAX))
		return false;

	std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
	if(!stream->isOpen()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Input/output error"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	TagLib::MP4::File file(stream.get());
	if(!file.isValid()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an MPEG-4 file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MP4"));

	if(file.audioProperties()) {
		auto properties = file.audioProperties();
		AddAudioPropertiesToDictionary(mMetadata, properties);

		if(properties->bitsPerSample())
			AddIntToDictionary(mMetadata, kBitsPerChannelKey, properties->bitsPerSample());
		switch(properties->codec()) {
			case TagLib::MP4::AudioProperties::AAC:
				CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("AAC"));
				break;
			case TagLib::MP4::AudioProperties::ALAC:
				CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("Apple Lossless"));
				break;
			default:
				break;
		}
	}

	if(file.tag())
		AddMP4TagToDictionary(mMetadata, mPictures, file.tag());

	return true;
}

bool SFB::Audio::MP4Metadata::_WriteMetadata(CFErrorRef *error)
{
	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf));
	if(!stream->isOpen()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for writing."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Input/output error"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	TagLib::MP4::File file(stream.get(), false);
	if(!file.isValid()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an MPEG-4 file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	SetMP4TagFromMetadata(*this, file.tag());

	if(!file.save()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Unable to write metadata"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	return true;
}
<commit_msg>Added m4r extension<commit_after>/*
 * Copyright (c) 2006 - 2018 Stephen F. Booth <me@sbooth.org>
 * See https://github.com/sbooth/SFBAudioEngine/blob/master/LICENSE.txt for license information
 */

#include <taglib/tfilestream.h>
#include <taglib/mp4file.h>

#include "MP4Metadata.h"
#include "CFWrapper.h"
#include "CFErrorUtilities.h"
#include "AddMP4TagToDictionary.h"
#include "SetMP4TagFromMetadata.h"
#include "AddAudioPropertiesToDictionary.h"
#include "CFDictionaryUtilities.h"

namespace {

	void RegisterMP4Metadata() __attribute__ ((constructor));
	void RegisterMP4Metadata()
	{
		SFB::Audio::Metadata::RegisterSubclass<SFB::Audio::MP4Metadata>();
	}

}

#pragma mark Static Methods

CFArrayRef SFB::Audio::MP4Metadata::CreateSupportedFileExtensions()
{
	CFStringRef supportedExtensions [] = { CFSTR("m4a"), CFSTR("m4r"), CFSTR("mp4") };
	return CFArrayCreate(kCFAllocatorDefault, (const void **)supportedExtensions, 3, &kCFTypeArrayCallBacks);
}

CFArrayRef SFB::Audio::MP4Metadata::CreateSupportedMIMETypes()
{
	CFStringRef supportedMIMETypes [] = { CFSTR("audio/mpeg-4") };
	return CFArrayCreate(kCFAllocatorDefault, (const void **)supportedMIMETypes, 1, &kCFTypeArrayCallBacks);
}

bool SFB::Audio::MP4Metadata::HandlesFilesWithExtension(CFStringRef extension)
{
	if(nullptr == extension)
		return false;

	if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("m4a"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("m4r"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("mp4"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

bool SFB::Audio::MP4Metadata::HandlesMIMEType(CFStringRef mimeType)
{
	if(nullptr == mimeType)
		return false;

	if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/mpeg-4"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

SFB::Audio::Metadata::unique_ptr SFB::Audio::MP4Metadata::CreateMetadata(CFURLRef url)
{
	return unique_ptr(new MP4Metadata(url));
}

#pragma mark Creation and Destruction

SFB::Audio::MP4Metadata::MP4Metadata(CFURLRef url)
	: Metadata(url)
{}

#pragma mark Functionality

bool SFB::Audio::MP4Metadata::_ReadMetadata(CFErrorRef *error)
{
	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, FALSE, buf, PATH_MAX))
		return false;

	std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
	if(!stream->isOpen()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Input/output error"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	TagLib::MP4::File file(stream.get());
	if(!file.isValid()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an MPEG-4 file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MP4"));

	if(file.audioProperties()) {
		auto properties = file.audioProperties();
		AddAudioPropertiesToDictionary(mMetadata, properties);

		if(properties->bitsPerSample())
			AddIntToDictionary(mMetadata, kBitsPerChannelKey, properties->bitsPerSample());
		switch(properties->codec()) {
			case TagLib::MP4::AudioProperties::AAC:
				CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("AAC"));
				break;
			case TagLib::MP4::AudioProperties::ALAC:
				CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("Apple Lossless"));
				break;
			default:
				break;
		}
	}

	if(file.tag())
		AddMP4TagToDictionary(mMetadata, mPictures, file.tag());

	return true;
}

bool SFB::Audio::MP4Metadata::_WriteMetadata(CFErrorRef *error)
{
	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf));
	if(!stream->isOpen()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for writing."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Input/output error"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	TagLib::MP4::File file(stream.get(), false);
	if(!file.isValid()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an MPEG-4 file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	SetMP4TagFromMetadata(*this, file.tag());

	if(!file.save()) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Unable to write metadata"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	return true;
}
<|endoftext|>


<commit_before>/*
 * @author: jstuder
 *
 */
//from arduino #include <Servo.h>

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>

// Open the Maestro's virtual COM port.
//const char * device = "\\\\.\\USBSER000";  // Windows, "\\\\.\\COM6" also works
const char * device = "/dev/ttyACM0";  // Linux
//const char * device = "/dev/cu.usbmodem00034567";  // Mac OS X
int serialControl = open(device, O_RDWR | O_NOCTTY);

//the servo to counter the pitch of the drone
int pitch = 0;
int roll = 1;
const int PARALLEL = 50; //45 allows for 30 degrees of + and - with ease
const int PERPENDICULAR = PARALLEL + 90;

//A constant to control the speed of angle change, lower is faster
const int SPEED = 10;

// Gets the position of a Maestro channel.
// See the "Serial Servo Commands" section of the user's guide.
int maestroGetPosition(int serialControl, unsigned char channel)
{
  unsigned char command[] = {0x90, channel};
  if(write(serialControl, command, sizeof(command)) == -1)
  {
    perror("error writing");
    return -1;
  }

  unsigned char response[2];
  if(read(serialControl,response,2) != 2)
  {
    perror("error reading");
    return -1;
  }

  return response[0] + 256*response[1];
}

// Sets the target of a Maestro channel.
// See the "Serial Servo Commands" section of the user's guide.
// The units of 'target' are quarter-microseconds.
int maestroSetTarget(int serialControl, unsigned char channel, unsigned short target)
{
  unsigned char command[] = {0x84, channel, target & 0x7F, target >> 7 & 0x7F};
  if (write(serialControl, command, sizeof(command)) == -1)
  {
    perror("error writing");
    return -1;
  }
  return 0;
}

/*
 * @parameters
 *  byte angle -> the angle you want to go to
 *  int speed -> the sleep between a move of 1 degree (lower is faster)
 */
void goToAngle(byte pitchAngle, byte rollAngle, int speed);

/*
 * @parameters
 * bool isPLL -> true if gimbal needs to be parallel to the ground, false if it
 *               needs to be perpendicular
 * int xAdj -> pass a positive or negative value to adjust the left-right axis of the gimbal
 *             (modifies servo2)
 * int yAdj -> pass a positive or negative value to adjust the forward-backward axis of the gimbal
 *             (modifies pitch)
 */
void mntn(bool isPLL, byte rAdj, byte pAdj);

void setup()
{
  if (serialControl == -1)
  {
    perror(device);
    return 1;
  }

  #ifdef _WIN32
    _setmode(serialControl, _O_BINARY);
  #else
    struct termios options;
    tcgetattr(serialControl, &options);
    options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);
    options.c_oflag &= ~(ONLCR | OCRNL);
    options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tcsetattr(serialControl, TCSANOW, &options);
  #endif

  goToAngle(50, 40, SPEED); //sets the gimbal to parallel as default

}

bool sig_handler(int signo, byte & p, byte & r, bool & change)
{
  if (signo == SIGUSR1)
  {
    change = !change;
    p = 0;
    r = 0;
  }
}

void main()
{
  //used to track parallel or perpendicular
  static boolean isParallel = true;

  if (Serial.available())
  {
    //allows yChange to default to the previous value. If input is invalid the gimbal doesn't move.
    byte pChange = maestroGetPosition(serialControl, pitch);
    byte rChange = maestroGetPosition(serialControl, roll);

    //if SIGUSR1 is sent, allows the gimbal to switch orientation
    if (sig_handler(SIGUSR1, pChange, rChange, isParallel))
      {}
    else
      mntn(isParallel, rChange, pChange);
  }
}

void mntn(bool isPLL, byte rAdj, byte pAdj)
{
  //sets the new angle equal to the change from the old angle
  //runs if the gimbal needs to be parallel to the ground
  rAdj += 40;
  if (isPLL)
  {
    pAdj += PARALLEL;
    goToAngle(pAdj, rAdj, SPEED);
  }
  else if (!isPLL)
  {
    pAdj += PERPENDICULAR;
    goToAngle(pAdj, rAdj, SPEED);
  }
}

void goToAngle(byte pitchAngle, byte rollAngle, int speed)
{
  byte currentPAngle = maestroGetPosition(serialControl, pitch);
  byte currentRAngle = maestroGetPosition(serialControl, roll);
  if(pitchAngle > currentPAngle)
  {
    for (int i = currentPAngle; i < pitchAngle; i++)
    {
      maestroSetTarget(serialControl, pitch, i);
      sleep(speed);
    }
  }
  else
  {
    for (int i = currentPAngle; i > pitchAngle; i--)
    {
      maestroSetTarget(serialControl, pitch, i);
      sleep(speed);
    }
  }

  if(rollAngle > currentRAngle)
  {
    for (int i = currentRAngle; i < rollAngle; i++)
    {
      maestroSetTarget(serialControl, roll, i);
      sleep(speed);
    }
  }
  else
  {
    for (int i = currentRAngle; i > rollAngle; i--)
    {
      maestroSetTarget(serialControl, roll, i);
      sleep(speed);
    }
  }
}

<commit_msg>Update gimbal.cpp<commit_after>/*
 * @author: jstuder
 *
 */
//from arduino #include <Servo.h>

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>

// Open the Maestro's virtual COM port.
//const char * device = "\\\\.\\USBSER000";  // Windows, "\\\\.\\COM6" also works
const char * device = "/dev/ttyACM0";  // Linux
//const char * device = "/dev/cu.usbmodem00034567";  // Mac OS X
int serialControl = open(device, O_RDWR | O_NOCTTY);

//the servo to counter the pitch of the drone
int pitch = 0;
int roll = 1;
const int PARALLEL = 50; //45 allows for 30 degrees of + and - with ease
const int PERPENDICULAR = PARALLEL + 90;

//A constant to control the speed of angle change, lower is faster
const int SPEED = 10;

// Gets the position of a Maestro channel.
// See the "Serial Servo Commands" section of the user's guide.
int maestroGetPosition(int serialControl, unsigned char channel)
{
  unsigned char command[] = {0x90, channel};
  if(write(serialControl, command, sizeof(command)) == -1)
  {
    perror("error writing");
    return -1;
  }

  unsigned char response[2];
  if(read(serialControl,response,2) != 2)
  {
    perror("error reading");
    return -1;
  }

  return response[0] + 256*response[1];
}

// Sets the target of a Maestro channel.
// See the "Serial Servo Commands" section of the user's guide.
// The units of 'target' are quarter-microseconds.
int maestroSetTarget(int serialControl, unsigned char channel, unsigned short target)
{
  unsigned char command[] = {0x84, channel, target & 0x7F, target >> 7 & 0x7F};
  if (write(serialControl, command, sizeof(command)) == -1)
  {
    perror("error writing");
    return -1;
  }
  return 0;
}

/*
 * @parameters
 *  int angle -> the angle you want to go to
 *  int speed -> the sleep between a move of 1 degree (lower is faster)
 */
void goToAngle(int pitchAngle, int rollAngle, int speed);

/*
 * @parameters
 * bool isPLL -> true if gimbal needs to be parallel to the ground, false if it
 *               needs to be perpendicular
 * int xAdj -> pass a positive or negative value to adjust the left-right axis of the gimbal
 *             (modifies servo2)
 * int yAdj -> pass a positive or negative value to adjust the forward-backward axis of the gimbal
 *             (modifies pitch)
 */
void mntn(bool isPLL, int rAdj, int pAdj);

void setup()
{
  if (serialControl == -1)
  {
    perror(device);
    return 1;
  }

  #ifdef _WIN32
    _setmode(serialControl, _O_BINARY);
  #else
    struct termios options;
    tcgetattr(serialControl, &options);
    options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);
    options.c_oflag &= ~(ONLCR | OCRNL);
    options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tcsetattr(serialControl, TCSANOW, &options);
  #endif

  goToAngle(50, 40, SPEED); //sets the gimbal to parallel as default

}

bool sig_handler(int signo)
{
  if (signo == SIGUSR1)
  {
    return true;
  }
}

void main()
{
  //used to track parallel or perpendicular
  static bool isParallel = true;

  if (Serial.available())
  {
    //allows yChange to default to the previous value. If input is invalid the gimbal doesn't move.
    int pChange = maestroGetPosition(serialControl, pitch);
    int rChange = maestroGetPosition(serialControl, roll);

    //if SIGUSR1 is sent, allows the gimbal to switch orientation
    if (sig_handler(SIGUSR1))
    {
      isParallel = !isParallel;
      p = 0;
      r = 0;
    }
    else
      mntn(isParallel, rChange, pChange);
  }
}

void mntn(bool isPLL, int rAdj, int pAdj)
{
  //sets the new angle equal to the change from the old angle
  //runs if the gimbal needs to be parallel to the ground
  rAdj += 40;
  if (isPLL)
  {
    pAdj += PARALLEL;
    goToAngle(pAdj, rAdj, SPEED);
  }
  else if (!isPLL)
  {
    pAdj += PERPENDICULAR;
    goToAngle(pAdj, rAdj, SPEED);
  }
}

void goToAngle(int pitchAngle, int rollAngle, int speed)
{
  int currentPAngle = maestroGetPosition(serialControl, pitch);
  int currentRAngle = maestroGetPosition(serialControl, roll);
  if(pitchAngle > currentPAngle)
  {
    for (int i = currentPAngle; i < pitchAngle; i++)
    {
      maestroSetTarget(serialControl, pitch, i);
      sleep(speed);
    }
  }
  else
  {
    for (int i = currentPAngle; i > pitchAngle; i--)
    {
      maestroSetTarget(serialControl, pitch, i);
      sleep(speed);
    }
  }

  if(rollAngle > currentRAngle)
  {
    for (int i = currentRAngle; i < rollAngle; i++)
    {
      maestroSetTarget(serialControl, roll, i);
      sleep(speed);
    }
  }
  else
  {
    for (int i = currentRAngle; i > rollAngle; i--)
    {
      maestroSetTarget(serialControl, roll, i);
      sleep(speed);
    }
  }
}

<|endoftext|>


<commit_before>//
//  item.cpp
//  Parse
//
//  Created by Andrew Hunter on 30/04/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include "item.h"
#include "Lr/lr_item.h"

using namespace lr;
using namespace contextfree;

item* empty_item_constructor::construct() {
    return new empty_item();
}

void empty_item_constructor::destruct(item* i) {
    delete i;
}

/// \brief Destructor
item::~item() {
}

/// \brief Compares this item to another. Returns true if they are the same
bool item::operator==(const item& compareTo) const {
    return compareTo.type() == type() && compareTo.symbol() == symbol();
}

/// \brief Orders this item relative to another item
bool item::operator<(const item& compareTo) const {
    // Compare types
    int ourType     = type();
    int theirType   = compareTo.type();
    if (ourType < theirType) return true;
    if (theirType < ourType) return false;

    // Compare symbols
    return symbol() < compareTo.symbol();
}

/// \brief Comparison function, returns true if a is less than b
bool item::compare(const item& a, const item& b) {
    // Compare the kinds
    kind aKind = a.type();
    kind bKind = b.type();

    if (aKind < bKind) return true;
    if (aKind > bKind) return false;

    // For objects with an 'other' type, use RTTI to compare the underlying types
    if (aKind >= other) {
        // Compare the types of these items
        bool isBefore = typeid(a).before(typeid(b));

        // a is less than b if its type is before b
        if (isBefore) return true;

        // a is greater than b if the types aren't equal
        if (typeid(a) != typeid(b)) return false;

        // Call through to the items own less-than operator
        return a < b;
    }

    // For EBNF items, use the comparison operator built into the item
    if (aKind >= ebnf) {
        return a < b;
    }

    // For well-known kinds, we can just compare the symbols
    int aSym = a.symbol();
    int bSym = b.symbol();

    return aSym < bSym;
}

static const empty_item the_empty_item;
static item_container   an_empty_item_c((item*) &the_empty_item, false);

/// \brief Fills in the items that follow this one
void item::fill_follow(item_set& follow, const lr::lr1_item& item, const grammar& gram) const {
    // Work out what follows in the item
    const rule& rule        = *item.rule();
    int         offset      = item.offset();
    size_t      numItems    = rule.items().size();

    if (offset+1 >= numItems) {
        // The follow set is just the lookahead for this item
        follow = item.lookahead();
    } else {
        // The follow set is FIRST(following item)
        int followOffset = offset + 1;
        follow = gram.first(rule.items()[followOffset]);

        // Add further following items if the follow set can be empty, until we reach the end
        followOffset++;
        while (followOffset < numItems && follow.find(an_empty_item_c) != follow.end()) {
            // Remove the empty item
            follow.erase(an_empty_item_c);

            // Add the items from the next item in the rule
            const item_set& newItems = gram.first(rule.items()[followOffset]);
            follow.insert(newItems.begin(), newItems.end());

            // Move on to the next item
            followOffset++;
        }

        // If the empty set is still included, remove it and add the item lookahead
        // (Note that if the loop above terminated early, then the empty set can't be in the follow set at this point)
        if (followOffset >= numItems && follow.find(an_empty_item_c) != follow.end()) {
            follow.erase(an_empty_item_c);
            follow.insert(item.lookahead().begin(), item.lookahead().end());
        }
    }
}

/// \brief Adds a new item to the specified set. Returns true if the set was changed
///
/// If the item is the same as an existing item except for the lookahead, the lookaheads are merged and the
/// set is the same size.
bool item::add(lr1_item_set& state, const grammar& gram, const lr1_item_container& newItem) {
    // Create a variant of the item with no lookahead
    typedef lr1_item::lookahead_set lookahead_set;
    static lookahead_set emptyLookaheadSet;

    lr1_item_container noLookahead(new lr1_item(&gram, newItem->rule(), newItem->offset(), emptyLookaheadSet), true);

    // Search for the first item that is >= noLookahead (items with any lookahead will be greater than this item)
    lr1_item_set::iterator maybeExisting = state.lower_bound(noLookahead);

    // If there's no rule then we can just add the item
    if (maybeExisting == state.end()) {
        state.insert(newItem);
        return true;
    }

    // If the rule is not the same (using the rule identifier for performance) then we can just add the item
    if ((*maybeExisting)->offset() != newItem->offset()
        || (*maybeExisting)->rule()->identifier(gram) != newItem->rule()->identifier(gram)) {
        state.insert(newItem);
        return true;
    }

    // If there are any new lookahead items, then we need to merge the lookahead sets
    // TODO: is there a quicker way of detecting when the sets are similar?

    // If the sets are the same, then this item has already been added and there's nothing more to do
    if (newItem->lookahead().size() == (*maybeExisting)->lookahead().size()) {
        if (newItem->lookahead() == (*maybeExisting)->lookahead()) {
            return false;
        }
    }

    // Merge the sets, and update the item if the size changes
    lookahead_set   mergedLookahead((*maybeExisting)->lookahead());
    size_t          initialSize = mergedLookahead.size();

    mergedLookahead.insert(newItem->lookahead().begin(), newItem->lookahead().end());

    // If the merged set is the same size as before then there have been no changes (these lookahead items already existed)
    if (mergedLookahead.size() == initialSize) {
        return false;
    }

    // Replace the existing item with the merged item
    lr1_item_container mergedItem(new lr1_item(&gram, newItem->rule(), newItem->offset(), mergedLookahead), true);

    state.erase(maybeExisting);
    state.insert(mergedItem);

    return true;
}

/// \brief Adds a new LR(1) item to a closure, completing the closure as necessary
void item::insert_closure_item(const lr::lr1_item_container& newItem, lr::lr1_item_set& state, const grammar& gram) const {
    const rule& rule = *newItem->rule();

    // Recursively add the closure for the new items
    if (add(state, gram, newItem) && !rule.items().empty()) {
        const class item& initial = *rule.items()[0];
        if (initial.type() != item::terminal) {
            initial.closure(*newItem, state, gram);
        }
    }
}

/// \brief Computes the closure of this rule in the specified grammar
///
/// This is the set of spontaneously generated LR(0) items for this item, and is used to generate the closure when
/// producing a parser. This call is supplied the item for which the closure is being generated, and a set of states
/// to which new items can be added (and the grammar so rules can be looked up).
///
/// A spontaneously generated rule is one that is implied by this item. For example, if parser is trying to match the
/// nonterminal 'X', then the rules for that nonterminal are spontaneously generated.
void item::closure(const lr1_item& item, lr1_item_set& state, const grammar& gram) const {
    // Nothing to do by default
}
/// \brief True if a transition (new state) should be generated for this item
///
/// Should return false for any item that acts like the empty item
bool item::generate_transition() const {
    // True by default
    return true;
}
<commit_msg>Reset add to use the old version of itself (which creates lots of duplicates) as the new version is blatently not working at the moment.<commit_after>//
//  item.cpp
//  Parse
//
//  Created by Andrew Hunter on 30/04/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include "item.h"
#include "Lr/lr_item.h"

using namespace lr;
using namespace contextfree;

item* empty_item_constructor::construct() {
    return new empty_item();
}

void empty_item_constructor::destruct(item* i) {
    delete i;
}

/// \brief Destructor
item::~item() {
}

/// \brief Compares this item to another. Returns true if they are the same
bool item::operator==(const item& compareTo) const {
    return compareTo.type() == type() && compareTo.symbol() == symbol();
}

/// \brief Orders this item relative to another item
bool item::operator<(const item& compareTo) const {
    // Compare types
    int ourType     = type();
    int theirType   = compareTo.type();
    if (ourType < theirType) return true;
    if (theirType < ourType) return false;

    // Compare symbols
    return symbol() < compareTo.symbol();
}

/// \brief Comparison function, returns true if a is less than b
bool item::compare(const item& a, const item& b) {
    // Compare the kinds
    kind aKind = a.type();
    kind bKind = b.type();

    if (aKind < bKind) return true;
    if (aKind > bKind) return false;

    // For objects with an 'other' type, use RTTI to compare the underlying types
    if (aKind >= other) {
        // Compare the types of these items
        bool isBefore = typeid(a).before(typeid(b));

        // a is less than b if its type is before b
        if (isBefore) return true;

        // a is greater than b if the types aren't equal
        if (typeid(a) != typeid(b)) return false;

        // Call through to the items own less-than operator
        return a < b;
    }

    // For EBNF items, use the comparison operator built into the item
    if (aKind >= ebnf) {
        return a < b;
    }

    // For well-known kinds, we can just compare the symbols
    int aSym = a.symbol();
    int bSym = b.symbol();

    return aSym < bSym;
}

static const empty_item the_empty_item;
static item_container   an_empty_item_c((item*) &the_empty_item, false);

/// \brief Fills in the items that follow this one
void item::fill_follow(item_set& follow, const lr::lr1_item& item, const grammar& gram) const {
    // Work out what follows in the item
    const rule& rule        = *item.rule();
    int         offset      = item.offset();
    size_t      numItems    = rule.items().size();

    if (offset+1 >= numItems) {
        // The follow set is just the lookahead for this item
        follow = item.lookahead();
    } else {
        // The follow set is FIRST(following item)
        int followOffset = offset + 1;
        follow = gram.first(rule.items()[followOffset]);

        // Add further following items if the follow set can be empty, until we reach the end
        followOffset++;
        while (followOffset < numItems && follow.find(an_empty_item_c) != follow.end()) {
            // Remove the empty item
            follow.erase(an_empty_item_c);

            // Add the items from the next item in the rule
            const item_set& newItems = gram.first(rule.items()[followOffset]);
            follow.insert(newItems.begin(), newItems.end());

            // Move on to the next item
            followOffset++;
        }

        // If the empty set is still included, remove it and add the item lookahead
        // (Note that if the loop above terminated early, then the empty set can't be in the follow set at this point)
        if (followOffset >= numItems && follow.find(an_empty_item_c) != follow.end()) {
            follow.erase(an_empty_item_c);
            follow.insert(item.lookahead().begin(), item.lookahead().end());
        }
    }
}

/// \brief Adds a new item to the specified set. Returns true if the set was changed
///
/// If the item is the same as an existing item except for the lookahead, the lookaheads are merged and the
/// set is the same size.
bool item::add(lr1_item_set& state, const grammar& gram, const lr1_item_container& newItem) {
    // TODO: the stuff that follows fails to work :-/
    return state.insert(newItem).second;

    // Create a variant of the item with no lookahead
    typedef lr1_item::lookahead_set lookahead_set;
    static lookahead_set emptyLookaheadSet;

    lr1_item_container noLookahead(new lr1_item(&gram, newItem->rule(), newItem->offset(), emptyLookaheadSet), true);

    // Search for the first item that is >= noLookahead (items with any lookahead will be greater than this item)
    lr1_item_set::iterator maybeExisting = state.lower_bound(noLookahead);

    // If there's no rule then we can just add the item
    if (maybeExisting == state.end()) {
        state.insert(newItem);
        return true;
    }

    // If the rule is not the same (using the rule identifier for performance) then we can just add the item
    if ((*maybeExisting)->offset() != newItem->offset()
        || (*maybeExisting)->rule()->identifier(gram) != newItem->rule()->identifier(gram)) {
        state.insert(newItem);
        return true;
    }

    // If there are any new lookahead items, then we need to merge the lookahead sets
    // TODO: is there a quicker way of detecting when the sets are similar?

    // If the sets are the same, then this item has already been added and there's nothing more to do
    if (newItem->lookahead().size() == (*maybeExisting)->lookahead().size()) {
        if (newItem->lookahead() == (*maybeExisting)->lookahead()) {
            return false;
        }
    }

    // Merge the sets, and update the item if the size changes
    lookahead_set   mergedLookahead((*maybeExisting)->lookahead());
    size_t          initialSize = mergedLookahead.size();

    mergedLookahead.insert(newItem->lookahead().begin(), newItem->lookahead().end());

    // If the merged set is the same size as before then there have been no changes (these lookahead items already existed)
    if (mergedLookahead.size() == initialSize) {
        return false;
    }

    // Replace the existing item with the merged item
    lr1_item_container mergedItem(new lr1_item(&gram, newItem->rule(), newItem->offset(), mergedLookahead), true);

    state.erase(maybeExisting);
    state.insert(mergedItem);

    return true;
}

/// \brief Adds a new LR(1) item to a closure, completing the closure as necessary
void item::insert_closure_item(const lr::lr1_item_container& newItem, lr::lr1_item_set& state, const grammar& gram) const {
    const rule& rule = *newItem->rule();

    // Recursively add the closure for the new items
    if (add(state, gram, newItem) && !rule.items().empty()) {
        const class item& initial = *rule.items()[0];
        if (initial.type() != item::terminal) {
            initial.closure(*newItem, state, gram);
        }
    }
}

/// \brief Computes the closure of this rule in the specified grammar
///
/// This is the set of spontaneously generated LR(0) items for this item, and is used to generate the closure when
/// producing a parser. This call is supplied the item for which the closure is being generated, and a set of states
/// to which new items can be added (and the grammar so rules can be looked up).
///
/// A spontaneously generated rule is one that is implied by this item. For example, if parser is trying to match the
/// nonterminal 'X', then the rules for that nonterminal are spontaneously generated.
void item::closure(const lr1_item& item, lr1_item_set& state, const grammar& gram) const {
    // Nothing to do by default
}
/// \brief True if a transition (new state) should be generated for this item
///
/// Should return false for any item that acts like the empty item
bool item::generate_transition() const {
    // True by default
    return true;
}
<|endoftext|>


<commit_before>#include <vector>

#include <boost/lambda/lambda.hpp>

#include "Linq.h"
#include <iostream>

namespace CppLinq
{
	using namespace std;
	using boost::lambda::_1;

	struct Person
	{
		Person(const string& name, int age) :
			m_name(name), m_age(age)
		{

		}

		string m_name;
		int m_age;
	};

	class LinqTest
	{
	public:
		LinqTest()
		{
			m_guests.reset(new vector<Person>());

			m_guests->push_back(Person("John", 32));
			m_guests->push_back(Person("Mike", 28));
			m_guests->push_back(Person("Eliz", 27));
		}

		void PerformTest()
		{
			assert(from(m_guests).count() == 3);

			assert(from(m_guests).orderby<int>(&_1 ->* &Person::m_age, Descending).count() == 3);
			for (int i = 0; i < m_guests->size(); ++i)
			{
				cout << m_guests->at(i).m_name << ' ' << m_guests->at(i).m_age << endl;
			}

			assert(from(m_guests).where(&_1 ->* &Person::m_age > 30).count() == 1);

			assert(from(m_guests).select<int>(&_1 ->* &Person::m_age).count() == 3);
			shared_ptr<vector<int>> results = from(m_guests).select<int>(&_1 ->* &Person::m_age).get();
			assert(results->size() == 3);
			assert((*results)[0] == 32);

			assert(from(m_guests).group<int>(&_1 ->* &Person::m_age).count() == 3);

			vector<Person> people;
			people.push_back(Person("Joe", 20));
			assert(from(&people).group<int>(&_1 ->* &Person::m_age).count() == 1);

			m_guests->push_back(Person("Joe", 18));
			DataSet<vector<Person>> results2 = insert(from(m_guests).where(&_1 ->* &Person::m_age > 30)).into(from(m_guests).where(&_1 ->* &Person::m_name == "Joe"));
			assert(results2.count() == 2);
			shared_ptr<vector<int>> ages = results2.select<int>(&_1 ->* &Person::m_age).get();
			assert(count(ages->begin(), ages->end(), 32) == 1);
			assert(count(ages->begin(), ages->end(), 18) == 1);
		}

	private:
		shared_ptr<vector<Person>> m_guests;
	};
}

int main()
{
	CppLinq::LinqTest test;
	test.PerformTest();
}<commit_msg>Code refactoring<commit_after>#include <vector>
#include <iostream>

#include <boost/lambda/lambda.hpp>

#include "Linq.h"

namespace CppLinq
{
	using namespace std;
	using boost::lambda::_1;

	struct Person
	{
		Person(const string& name, int age) :
			m_name(name), m_age(age)
		{

		}

		string m_name;
		int m_age;
	};

	class LinqTest
	{
	public:
		LinqTest()
		{
			m_guests.reset(new vector<Person>());

			m_guests->push_back(Person("John", 32));
			m_guests->push_back(Person("Mike", 28));
			m_guests->push_back(Person("Eliz", 27));
		}

		void PerformTest() const
		{
			assert(from(m_guests).count() == 3);

			assert(from(m_guests).orderby<int>(&_1 ->* &Person::m_age, Descending).count() == 3);
			for (int i = 0; i < m_guests->size(); ++i)
			{
				cout << m_guests->at(i).m_name << ' ' << m_guests->at(i).m_age << endl;
			}

			assert(from(m_guests).where(&_1 ->* &Person::m_age > 30).count() == 1);

			assert(from(m_guests).select<int>(&_1 ->* &Person::m_age).count() == 3);
			shared_ptr<vector<int>> results = from(m_guests).select<int>(&_1 ->* &Person::m_age).get();
			assert(results->size() == 3);
			assert((*results)[0] == 32);

			assert(from(m_guests).group<int>(&_1 ->* &Person::m_age).count() == 3);

			vector<Person> people;
			people.push_back(Person("Joe", 20));
			assert(from(&people).group<int>(&_1 ->* &Person::m_age).count() == 1);

			m_guests->push_back(Person("Joe", 18));
			DataSet<vector<Person>> results2 = insert(from(m_guests).where(&_1 ->* &Person::m_age > 30)).into(from(m_guests).where(&_1 ->* &Person::m_name == "Joe"));
			assert(results2.count() == 2);
			shared_ptr<vector<int>> ages = results2.select<int>(&_1 ->* &Person::m_age).get();
			assert(count(ages->begin(), ages->end(), 32) == 1);
			assert(count(ages->begin(), ages->end(), 18) == 1);
		}

	private:
		shared_ptr<vector<Person>> m_guests;
	};
}

int main()
{
	CppLinq::LinqTest test;
	test.PerformTest();
}<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <qdebug.h>
#include <FilePrintStream.h>

namespace WTF {

void* fastMalloc(size_t size)
{
    return malloc(size);
}

void* fastRealloc(void* ptr, size_t size)
{
    return realloc(ptr, size);
}

void fastFree(void* ptr)
{
    free(ptr);
}

uint32_t cryptographicallyRandomNumber()
{
    return 0;
}

static FilePrintStream* s_dataFile;

void setDataFile(FILE* f)
{
    delete s_dataFile;
    s_dataFile = new FilePrintStream(f, FilePrintStream::Borrow);
}

FilePrintStream& dataFile()
{
    if (!s_dataFile)
        s_dataFile = new FilePrintStream(stderr, FilePrintStream::Borrow);
    return *s_dataFile;
}

void dataLogFV(const char* format, va_list args)
{
    char buffer[1024];
    vsnprintf(buffer, sizeof(buffer), format, args);
    qDebug("%s", buffer);
}

void dataLogF(const char* format, ...)
{
    char buffer[1024];
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    qDebug("%s", buffer);
}

void dataLogFString(const char* str)
{
    qDebug("%s", str);
}

}

extern "C" {

void WTFReportAssertionFailure(const char* /*file*/, int /*line*/, const char* /*function*/, const char* /*assertion*/)
{
}

void WTFReportBacktrace()
{
}

void WTFInvokeCrashHook()
{
}

}

#if ENABLE(ASSEMBLER) && CPU(X86) && !OS(MAC_OS_X)
#include <MacroAssemblerX86Common.h>

JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = JSC::MacroAssemblerX86Common::NotCheckedSSE2;
#endif

<commit_msg>wince: vsnprintf is not available, use qvsnprintf<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <qdebug.h>
#include <qbytearray.h> // qvsnprintf
#include <FilePrintStream.h>

namespace WTF {

void* fastMalloc(size_t size)
{
    return malloc(size);
}

void* fastRealloc(void* ptr, size_t size)
{
    return realloc(ptr, size);
}

void fastFree(void* ptr)
{
    free(ptr);
}

uint32_t cryptographicallyRandomNumber()
{
    return 0;
}

static FilePrintStream* s_dataFile;

void setDataFile(FILE* f)
{
    delete s_dataFile;
    s_dataFile = new FilePrintStream(f, FilePrintStream::Borrow);
}

FilePrintStream& dataFile()
{
    if (!s_dataFile)
        s_dataFile = new FilePrintStream(stderr, FilePrintStream::Borrow);
    return *s_dataFile;
}

void dataLogFV(const char* format, va_list args)
{
    char buffer[1024];
    qvsnprintf(buffer, sizeof(buffer), format, args);
    qDebug("%s", buffer);
}

void dataLogF(const char* format, ...)
{
    char buffer[1024];
    va_list args;
    va_start(args, format);
    qvsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    qDebug("%s", buffer);
}

void dataLogFString(const char* str)
{
    qDebug("%s", str);
}

}

extern "C" {

void WTFReportAssertionFailure(const char* /*file*/, int /*line*/, const char* /*function*/, const char* /*assertion*/)
{
}

void WTFReportBacktrace()
{
}

void WTFInvokeCrashHook()
{
}

}

#if ENABLE(ASSEMBLER) && CPU(X86) && !OS(MAC_OS_X)
#include <MacroAssemblerX86Common.h>

JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = JSC::MacroAssemblerX86Common::NotCheckedSSE2;
#endif

<|endoftext|>


<commit_before>/**************************************************************************
 * This file is property of and copyright by the Experimental Nuclear     *
 * Physics Group, Dep. of Physics                                         *
 * University of Oslo, Norway, 2007                                       *
 *                                                                        *
 * Author: Per Thomas Hille <perthi@fys.uio.no> for the ALICE HLT Project.*
 * Contributors are mentioned in the code where appropriate.              *
 * Please report bugs to perthi@fys.uio.no                                *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
#include "AliHLTPHOSFourierComponent.h"
#include "AliHLTPHOSFourier.h"
#include "AliHLTPHOSValidCellDataStruct.h"
#include "AliHLTPHOSRcuCellEnergyDataStruct.h"
#include "AliHLTPHOSSharedMemoryInterface.h"

#include "AliHLTPHOSRcuFFTDataStruct.h"

AliHLTPHOSFourierComponent gAliHLTPHOSFourierComponent;

AliHLTPHOSFourierComponent::AliHLTPHOSFourierComponent(): AliHLTPHOSRcuProcessor(),fFourierPtr(0), fShmPtr(0),fOutPtr(0)
{
  fFourierPtr = new AliHLTPHOSFourier();
  fShmPtr = new AliHLTPHOSSharedMemoryInterface();
}

AliHLTPHOSFourierComponent::~AliHLTPHOSFourierComponent()
{

}

int
AliHLTPHOSFourierComponent::Deinit()
{
  Logging(kHLTLogInfo, "HLT", "PHOS", ",Deinitializing AliHLTPHOSFourierComponent");
  return 0;
}

const char*
AliHLTPHOSFourierComponent::GetComponentID()
{
  return "PhosFourier";
  //     "PhosFourier"
}

AliHLTComponent*
AliHLTPHOSFourierComponent::Spawn()

{
  return new AliHLTPHOSFourierComponent;
}

void
AliHLTPHOSFourierComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
{
  const AliHLTComponentDataType* pType=fgkInputDataTypes;

  while (pType->fID!=0)
    {
      list.push_back(*pType);
      pType++;
    }
}

AliHLTComponentDataType
AliHLTPHOSFourierComponent::GetOutputDataType()
{
  return AliHLTPHOSDefinitions::fgkFourierTransform;
  // return AliHLTPHOSDefinitions::fgkCellEnergyDataType;
  // return kAliHLTMultipleDataType;
}

/*
int
AliHLTPHOSFourierComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
{
  tgtList.clear();
  tgtList.push_back(AliHLTPHOSDefinitions::fgkFourierTransform);
  //  tgtList.push_back(kAliHLTDataTypeHwAddr16);
  return tgtList.size();
}
*/

void
AliHLTPHOSFourierComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
{
 //  constBase =1;
//   inputMultiplier = 1;
  // constBase = 30;
  // inputMultiplier = 1.2;
  inputMultiplier = 0.1;
}

int
AliHLTPHOSFourierComponent::DoInit(int /*argc*/, const char** /*argv*/)
{
  cout << "AliHLTPHOSFourierComponent::DoInit !!!!!!!!!! " << endl;
  return 0;
}

/*
int
AliHLTPHOSFourierComponent::DoDeinit()
{

}
*/

int
AliHLTPHOSFourierComponent::DoEvent(const AliHLTComponentEventData& evtData,
				    const AliHLTComponentBlockData* blocks,
				    AliHLTComponentTriggerData& /*trigData*/,
				    AliHLTUInt8_t* outputPtr,
				    AliHLTUInt32_t& size,
				    AliHLTComponentBlockDataList& outputBlocks )
{
  fPhosEventCount ++;
  AliHLTPHOSValidCellDataStruct *currentChannel =0;
  UInt_t offset            = 0;
  UInt_t mysize            = 0;
  UInt_t tSize             = 0;
  const AliHLTComponentBlockData* iter = NULL;
  unsigned long ndx;
  UInt_t specification = 0;

  for( ndx = 0; ndx < evtData.fBlockCnt; ndx++ )
    {
      iter = blocks+ndx;
      if(iter->fDataType != AliHLTPHOSDefinitions::fgkCellEnergyDataType)
	{

	  continue;
	}

      specification = specification|iter->fSpecification;
      AliHLTPHOSRcuCellEnergyDataStruct *cellDataPtr = (AliHLTPHOSRcuCellEnergyDataStruct*)( iter->fPtr);
      AliHLTPHOSRcuFFTDataStruct *fourierOutPtr =  (AliHLTPHOSRcuFFTDataStruct*)outputPtr;
      fShmPtr->SetMemory(cellDataPtr);
      currentChannel = fShmPtr->NextChannel();

      while(currentChannel != 0)
	{
	  Int_t *data;
	  Int_t nsamples = 0;
	  data= fShmPtr->GetRawData(nsamples);
	  //	  fFourierPtr->ProcessFourier(data, nsamples, currentChannel->fZ, currentChannel->fX, currentChannel->fGain  );
	  currentChannel = fShmPtr->NextChannel();
	}

      *fourierOutPtr =  fFourierPtr->GetPSD();

      for(int i=0; i < 500; i++)
	{
	  if(i%16 == 0)
	    {
	      printf("\n");
	    }

	  cout << fourierOutPtr->fGlobalAccumulatedPSD[1][i] <<  "\t";
	}

      mysize += sizeof(AliHLTPHOSRcuFFTDataStruct);
      AliHLTComponentBlockData bd;
      bd.fOffset = offset;
      bd.fSize = mysize;
      bd.fDataType = AliHLTPHOSDefinitions::fgkFourierTransform;
      // bd.fSpecification = 0xFFFFFFFF;
      bd.fSpecification = specification;
      outputBlocks.push_back( bd );

      cout <<"size left is "<<  size  <<"  FourierComponenet: offset ="<< offset << "mysize =" << mysize << "specification =" << specification <<endl;

      tSize += mysize;

      outputPtr += mysize;

      if( tSize > size )
	{
	  cout <<"HLT::AliHLTFourierComponent::DoEvent Too much data Data written over allowed buffer. Amount written:"<< tSize<<"allowed amount"<< size << endl;
	  Logging( kHLTLogFatal, "HLT::AliHLTFourierComponent::DoEvent", "Too much data",
		   "Data written over allowed buffer. Amount written: %lu, allowed amount: %lu." , tSize, size );

	  return EMSGSIZE;
	}

    }

  return 0;

}
<commit_msg>Checking if git works<commit_after>/**************************************************************************
 * This file is property of and copyright by the Experimental Nuclear     *
 * Physics Group, Dep. of Physics                                         *
 * University of Oslo, Norway, 2007                                       *
 *                                                                        *
 * Author: Per Thomas Hille <perthi@fys.uio.no> for the ALICE HLT Project.*
 * Contributors are mentioned in the code where appropriate.              *
 * Please report bugs to perthi@fys.uio.no                                *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
#include "AliHLTPHOSFourierComponent.h"
#include "AliHLTPHOSFourier.h"
#include "AliHLTPHOSValidCellDataStruct.h"
#include "AliHLTPHOSRcuCellEnergyDataStruct.h"
#include "AliHLTPHOSSharedMemoryInterface.h"

#include "AliHLTPHOSRcuFFTDataStruct.h"

AliHLTPHOSFourierComponent gAliHLTPHOSFourierComponent;

AliHLTPHOSFourierComponent::AliHLTPHOSFourierComponent(): AliHLTPHOSRcuProcessor(),fFourierPtr(0), fShmPtr(0),fOutPtr(0)
{
  fFourierPtr = new AliHLTPHOSFourier();
  fShmPtr = new AliHLTPHOSSharedMemoryInterface();
}

AliHLTPHOSFourierComponent::~AliHLTPHOSFourierComponent()
{

}

int
AliHLTPHOSFourierComponent::Deinit()
{
  Logging(kHLTLogInfo, "HLT", "PHOS", ",Deinitializing AliHLTPHOSFourierComponent");
  return 0;
}

const char*
AliHLTPHOSFourierComponent::GetComponentID()
{
  return "PhosFourier";
  //     "PhosFourier"
}

AliHLTComponent*
AliHLTPHOSFourierComponent::Spawn()

{
  return new AliHLTPHOSFourierComponent;
}

void
AliHLTPHOSFourierComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
{
  const AliHLTComponentDataType* pType=fgkInputDataTypes;

  while (pType->fID!=0)
    {
      list.push_back(*pType);
      pType++;
    }
}

AliHLTComponentDataType
AliHLTPHOSFourierComponent::GetOutputDataType()
{
  return AliHLTPHOSDefinitions::fgkFourierTransform;
  // return AliHLTPHOSDefinitions::fgkCellEnergyDataType;
  // return kAliHLTMultipleDataType;
}

/*
int
AliHLTPHOSFourierComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
{
  tgtList.clear();
  tgtList.push_back(AliHLTPHOSDefinitions::fgkFourierTransform);
  //  tgtList.push_back(kAliHLTDataTypeHwAddr16);
  return tgtList.size();
}
*/

void
AliHLTPHOSFourierComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
{
 //  constBase =1;
//   inputMultiplier = 1;
  // constBase = 30;
  // inputMultiplier = 1.2;
  inputMultiplier = 0.1;
}

int
AliHLTPHOSFourierComponent::DoInit(int /*argc*/, const char** /*argv*/)
{
  cout << "AliHLTPHOSFourierComponent::DoInit !!!!!!!!!! " << endl;
  return 0;
}

/*
int
AliHLTPHOSFourierComponent::DoDeinit()
{

}
*/

int
AliHLTPHOSFourierComponent::DoEvent(const AliHLTComponentEventData& evtData,
				    const AliHLTComponentBlockData* blocks,
				    AliHLTComponentTriggerData& /*trigData*/,
				    AliHLTUInt8_t* outputPtr,
				    AliHLTUInt32_t& size,
				    AliHLTComponentBlockDataList& outputBlocks )
{
  fPhosEventCount ++;
  AliHLTPHOSValidCellDataStruct *currentChannel =0;
  UInt_t offset            = 0;
  UInt_t mysize            = 0;
  UInt_t tSize             = 0;
  const AliHLTComponentBlockData* iter = NULL;
  unsigned long ndx;
  UInt_t specification = 0;

  for( ndx = 0; ndx < evtData.fBlockCnt; ndx++ )
    {
      iter = blocks+ndx;
      if(iter->fDataType != AliHLTPHOSDefinitions::fgkCellEnergyDataType)
	{

	  continue;
	}

      specification = specification|iter->fSpecification;
      AliHLTPHOSRcuCellEnergyDataStruct *cellDataPtr = (AliHLTPHOSRcuCellEnergyDataStruct*)( iter->fPtr);
      AliHLTPHOSRcuFFTDataStruct *fourierOutPtr =  (AliHLTPHOSRcuFFTDataStruct*)outputPtr;
      fShmPtr->SetMemory(cellDataPtr);
      currentChannel = fShmPtr->NextChannel();

      while(currentChannel != 0)
	{
	  Int_t *data;
	  Int_t nsamples = 0;
	  data= fShmPtr->GetRawData(nsamples);
	  fFourierPtr->ProcessFourier(data, nsamples, currentChannel->fZ, currentChannel->fX, currentChannel->fGain  );
	  currentChannel = fShmPtr->NextChannel();
	}

      *fourierOutPtr =  fFourierPtr->GetPSD();

      for(int i=0; i < 500; i++)
	{
	  if(i%16 == 0)
	    {
	      printf("\n");
	    }

	  cout << fourierOutPtr->fGlobalAccumulatedPSD[1][i] <<  "\t";
	}

      mysize += sizeof(AliHLTPHOSRcuFFTDataStruct);
      AliHLTComponentBlockData bd;
      bd.fOffset = offset;
      bd.fSize = mysize;
      bd.fDataType = AliHLTPHOSDefinitions::fgkFourierTransform;
      // bd.fSpecification = 0xFFFFFFFF;
      bd.fSpecification = specification;
      outputBlocks.push_back( bd );

      cout <<"size left is "<<  size  <<"  FourierComponenet: offset ="<< offset << "mysize =" << mysize << "specification =" << specification <<endl;

      tSize += mysize;

      outputPtr += mysize;

      if( tSize > size )
	{
	  cout <<"HLT::AliHLTFourierComponent::DoEvent Too much data Data written over allowed buffer. Amount written:"<< tSize<<"allowed amount"<< size << endl;
	  Logging( kHLTLogFatal, "HLT::AliHLTFourierComponent::DoEvent", "Too much data",
		   "Data written over allowed buffer. Amount written: %lu, allowed amount: %lu." , tSize, size );

	  return EMSGSIZE;
	}

    }

  return 0;

}
<|endoftext|>


<commit_before>/*
 * This file is part of meego-keyboard
 *
 * Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 * used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 */

#include "fixture_virtualkeyboard.h"
#include "mimkeyarea.h"
#include "mimkey.h"
#include "mimabstractkey.h"
#include "mimkeyarea_p.h"

#include <QDebug>
#include <QString>
#include <QHash>

Q_EXPORT_PLUGIN2(fixture_virtualkeyboard, FixtureVirtualKeyboard)

FixtureVirtualKeyboard::FixtureVirtualKeyboard(QObject *parent)
    : QObject(parent)
{
}

FixtureVirtualKeyboard::~FixtureVirtualKeyboard()
{
}
/*!
 *  \brief execute is called when implementing a fixture from ruby matti
 */
bool FixtureVirtualKeyboard::execute(void *objectInstance,
                                     const QString &actionName,
                                     const QHash<QString, QString> &parameters,
                                     QString &stdOut)
{
    qDebug() << "FixtureVirtualKeyboard::execute action:" << actionName;

    if (objectInstance == 0) {
        stdOut = "This fixture can be called for MImAbstractKeyArea only!";
        return false;
    }

    QGraphicsItem *gItem = (QGraphicsItem*)objectInstance;
    const MImKeyArea *const widget =  qgraphicsitem_cast<MImKeyArea *>(gItem);

    if (!widget) {
        stdOut = "This fixture can be called for MImAbstractKeyArea only!";
        return false;
    }

    if (!parameters.contains("key") || parameters.value("key").isEmpty()) {
        stdOut = "action can be called only with valid argument: key ";
        return false;
    }

    const MImAbstractKey *button = 0;
    const QString key = QString(parameters.value("key"));

    MImKeyBinding::KeyAction action;
    bool keyAction = true;
    if (key == "Backspace") {
        action = MImKeyBinding::ActionBackspace;
    } else if (key == "Shift") {
        action = MImKeyBinding::ActionShift;
    } else if (key == "Sym") {
        action = MImKeyBinding::ActionSym;
    } else if (key == "+/-") {
        action = MImKeyBinding::ActionPlusMinusToggle;
    } else if (key == "*+") {
        action = MImKeyBinding::ActionCycle;
    } else if (key == "Space") {
        action = MImKeyBinding::ActionSpace;
    } else if (key == "Enter") {
        action = MImKeyBinding::ActionReturn;
    } else if (key == "Compose") {
        action = MImKeyBinding::ActionCompose;
    } else if (key == "AccentKeys") {
        action = MImKeyBinding::ActionSwitch;
    } else {
        keyAction = false;
    }

    if (actionName == "getPosition") {
            if (!keyAction){
                button = getKey(widget, key);
            } else {
                button = getKey(widget, action);
            }
            if (button) {
                const QRect rect = button->buttonRect().toRect();
                stdOut = QString("x=%1,y=%2,width=%3,height=%4")
                    .arg(rect.center().x())
                    .arg(rect.center().y())
                    .arg(rect.width())
                    .arg(rect.height());
                return true;
            }
    } else if (actionName == "getAttribute") {
        if (!parameters.contains("attribute") || parameters.value("attribute").isEmpty()) {
            stdOut = "attribute can be called only with valid argument: attribute ";
            return false;
        }
        const QString attribute = QString(parameters.value("attribute"));
        if (!keyAction){
            stdOut = getAttribute(widget, key, attribute);
        } else {
            stdOut = getAttribute(widget, action, attribute);
        }
        return true;
    }

    stdOut = "Could not get a proper button " + key;
    return false;
}

const MImAbstractKey * FixtureVirtualKeyboard::getKey(const MImKeyArea * const widget,
                                                      const QString &label) const
{
    Q_ASSERT(widget);

    foreach (const MImKeyAreaPrivate::KeyRow &row, widget->d_ptr->rowList) {
        foreach (const MImKey *key, row.keys) {
            if (key->label() == label) {
                return key;
            }
        }
    }

    return 0;
}

const MImAbstractKey * FixtureVirtualKeyboard::getKey(const MImKeyArea * const widget,
                                                      MImKeyBinding::KeyAction action) const
{
    Q_ASSERT(widget);

    foreach (const MImKeyAreaPrivate::KeyRow &row, widget->d_ptr->rowList) {
        foreach (const MImKey *key, row.keys) {
            if (key->binding().action() == action) {
                return key;
            }
        }
    }

    return 0;
}

QString FixtureVirtualKeyboard::getAttribute(const MImKeyArea * const widget,
                                             MImKeyBinding::KeyAction action,
                                             const QString &attribute)
{
    Q_ASSERT(widget);
    QString output;

    foreach (const MImKeyAreaPrivate::KeyRow &row, widget->d_ptr->rowList) {
        foreach (const MImKey *key, row.keys) {
            if (key->binding().action() == action) {
                if ( attribute == "label" ){
                    output = key->label();
                }
                break;
            }
        }
    }

    return output;
}

QString FixtureVirtualKeyboard::getAttribute(const MImKeyArea * const widget,
                                             const QString &label,
                                             const QString &attribute)
{
    Q_ASSERT(widget);
    QString output;

    foreach (const MImKeyAreaPrivate::KeyRow &row, widget->d_ptr->rowList) {
        foreach (const MImKey *key, row.keys) {
            if (key->label() == label) {
                if ( attribute == "label" ){
                    output = key->label();
                }
                break;
            }
        }
    }

    return output;
}

<commit_msg>Changes: Add "OnOffToggle" support in "fixture_virtualkeyboard".<commit_after>/*
 * This file is part of meego-keyboard
 *
 * Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 * used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 */

#include "fixture_virtualkeyboard.h"
#include "mimkeyarea.h"
#include "mimkey.h"
#include "mimabstractkey.h"
#include "mimkeyarea_p.h"

#include <QDebug>
#include <QString>
#include <QHash>

Q_EXPORT_PLUGIN2(fixture_virtualkeyboard, FixtureVirtualKeyboard)

FixtureVirtualKeyboard::FixtureVirtualKeyboard(QObject *parent)
    : QObject(parent)
{
}

FixtureVirtualKeyboard::~FixtureVirtualKeyboard()
{
}
/*!
 *  \brief execute is called when implementing a fixture from ruby matti
 */
bool FixtureVirtualKeyboard::execute(void *objectInstance,
                                     const QString &actionName,
                                     const QHash<QString, QString> &parameters,
                                     QString &stdOut)
{
    qDebug() << "FixtureVirtualKeyboard::execute action:" << actionName;

    if (objectInstance == 0) {
        stdOut = "This fixture can be called for MImAbstractKeyArea only!";
        return false;
    }

    QGraphicsItem *gItem = (QGraphicsItem*)objectInstance;
    const MImKeyArea *const widget =  qgraphicsitem_cast<MImKeyArea *>(gItem);

    if (!widget) {
        stdOut = "This fixture can be called for MImAbstractKeyArea only!";
        return false;
    }

    if (!parameters.contains("key") || parameters.value("key").isEmpty()) {
        stdOut = "action can be called only with valid argument: key ";
        return false;
    }

    const MImAbstractKey *button = 0;
    const QString key = QString(parameters.value("key"));

    MImKeyBinding::KeyAction action;
    bool keyAction = true;
    if (key == "Backspace") {
        action = MImKeyBinding::ActionBackspace;
    } else if (key == "Shift") {
        action = MImKeyBinding::ActionShift;
    } else if (key == "Sym") {
        action = MImKeyBinding::ActionSym;
    } else if (key == "+/-") {
        action = MImKeyBinding::ActionPlusMinusToggle;
    } else if (key == "*+") {
        action = MImKeyBinding::ActionCycle;
    } else if (key == "Space") {
        action = MImKeyBinding::ActionSpace;
    } else if (key == "Enter") {
        action = MImKeyBinding::ActionReturn;
    } else if (key == "Compose") {
        action = MImKeyBinding::ActionCompose;
    } else if (key == "AccentKeys") {
        action = MImKeyBinding::ActionSwitch;
    } else if (key == "OnOffToggle") {
        action = MImKeyBinding::ActionOnOffToggle;
    } else {
        keyAction = false;
    }

    if (actionName == "getPosition") {
            if (!keyAction){
                button = getKey(widget, key);
            } else {
                button = getKey(widget, action);
            }
            if (button) {
                const QRect rect = button->buttonRect().toRect();
                stdOut = QString("x=%1,y=%2,width=%3,height=%4")
                    .arg(rect.center().x())
                    .arg(rect.center().y())
                    .arg(rect.width())
                    .arg(rect.height());
                return true;
            }
    } else if (actionName == "getAttribute") {
        if (!parameters.contains("attribute") || parameters.value("attribute").isEmpty()) {
            stdOut = "attribute can be called only with valid argument: attribute ";
            return false;
        }
        const QString attribute = QString(parameters.value("attribute"));
        if (!keyAction){
            stdOut = getAttribute(widget, key, attribute);
        } else {
            stdOut = getAttribute(widget, action, attribute);
        }
        return true;
    }

    stdOut = "Could not get a proper button " + key;
    return false;
}

const MImAbstractKey * FixtureVirtualKeyboard::getKey(const MImKeyArea * const widget,
                                                      const QString &label) const
{
    Q_ASSERT(widget);

    foreach (const MImKeyAreaPrivate::KeyRow &row, widget->d_ptr->rowList) {
        foreach (const MImKey *key, row.keys) {
            if (key->label() == label) {
                return key;
            }
        }
    }

    return 0;
}

const MImAbstractKey * FixtureVirtualKeyboard::getKey(const MImKeyArea * const widget,
                                                      MImKeyBinding::KeyAction action) const
{
    Q_ASSERT(widget);

    foreach (const MImKeyAreaPrivate::KeyRow &row, widget->d_ptr->rowList) {
        foreach (const MImKey *key, row.keys) {
            if (key->binding().action() == action) {
                return key;
            }
        }
    }

    return 0;
}

QString FixtureVirtualKeyboard::getAttribute(const MImKeyArea * const widget,
                                             MImKeyBinding::KeyAction action,
                                             const QString &attribute)
{
    Q_ASSERT(widget);
    QString output;

    foreach (const MImKeyAreaPrivate::KeyRow &row, widget->d_ptr->rowList) {
        foreach (const MImKey *key, row.keys) {
            if (key->binding().action() == action) {
                if ( attribute == "label" ){
                    output = key->label();
                }
                break;
            }
        }
    }

    return output;
}

QString FixtureVirtualKeyboard::getAttribute(const MImKeyArea * const widget,
                                             const QString &label,
                                             const QString &attribute)
{
    Q_ASSERT(widget);
    QString output;

    foreach (const MImKeyAreaPrivate::KeyRow &row, widget->d_ptr->rowList) {
        foreach (const MImKey *key, row.keys) {
            if (key->label() == label) {
                if ( attribute == "label" ){
                    output = key->label();
                }
                break;
            }
        }
    }

    return output;
}

<|endoftext|>


<commit_before>#include <errno.h>
#include <sys/mman.h>
#include <unistd.h>

#include <cassert>
#include <cstring>

#include "../api/workload.h"

// Super ugly defines to do compile-time string concatonation X times...
#define REP0(x)
#define REP1(x)     x
#define REP2(x)     REP1(x) x
#define REP3(x)     REP2(x) x
#define REP4(x)     REP3(x) x
#define REP5(x)     REP4(x) x
#define REP6(x)     REP5(x) x
#define REP7(x)     REP6(x) x
#define REP8(x)     REP7(x) x
#define REP9(x)     REP8(x) x
#define REP10(x)    REP9(x) x

#define REP(hundreds, tens, ones, x) \
  REP##hundreds(REP10(REP10(x))) \
  REP##tens(REP10(x)) \
  REP##ones(x)

namespace fs_testing {
namespace user_tools {
namespace api {

namespace {

// We want exactly 4k of data for this.
static const unsigned int kTestDataSize = 4096;
// 4K of data plus one terminating byte.
static constexpr char kTestDataBlock[kTestDataSize + 1] =
  REP(1, 2, 8, "abcdefghijklmnopqrstuvwxyz123456");

}  // namespace

int WriteData(int fd, unsigned int offset, unsigned int size) {
  // Offset into a data block to start working at.
  const unsigned int rounded_offset =
    (offset + (kTestDataSize - 1)) & (~(kTestDataSize - 1));
  // Round down size to 4k for number of full pages to write.
  const unsigned int aligned_size =
    (size - (rounded_offset - offset)) & ~(kTestDataSize - 1);
  unsigned int num_written = 0;

  // The start of the write range is not aligned with our data blocks.
  // Therefore, we should write out part of a data block for this segment,
  // with the first character in the data block aligning with the data block
  // boundary.
  if (rounded_offset != offset) {
    // We should never write more than kTestDataSize of unaligned data at the
    // start.
    do {
      const unsigned int mod_offset =
        num_written + (offset & (kTestDataSize - 1));
      assert(mod_offset < kTestDataSize);

      int res = pwrite(fd, kTestDataBlock + mod_offset,
          rounded_offset - (offset + num_written), offset + num_written);
      if (res < 0) {
        return errno;
      }
      num_written += res;
    } while (offset + num_written < rounded_offset);
  }

  // Write out the required number of full pages for this request. The first
  // byte will be aligned with kTestDataSize.
  unsigned int aligned_written = 0;
  do {
    const unsigned int mod_offset = (aligned_written & (kTestDataSize - 1));
    // Write up to a full page of data at a time.
    int res = pwrite(fd, kTestDataBlock + mod_offset,
        kTestDataSize - mod_offset, offset + num_written);
    if (res < 0) {
      return errno;
    }
    num_written += res;
    aligned_written += res;
  } while (aligned_written < aligned_size);

  if (num_written == size) {
    return 0;
  }

  // Write out the last partial page of data. The first byte will be aligned
  // with kTestDataSize.
  unsigned int end_written = 0;
  do {
    assert(end_written < kTestDataSize);
    const unsigned int mod_offset = (end_written & (kTestDataSize - 1));
    int res = pwrite(fd, kTestDataBlock + mod_offset,
        size - num_written, offset + num_written);
    if (res < 0) {
      return errno;
    }
    num_written += res;
    end_written += res;
  } while (num_written < size);

  return 0;
}

int WriteDataMmap(int fd, unsigned int offset, unsigned int size) {
  const unsigned int map_size = size + (offset & ((1 << 12) - 1));
  char *filep = (char *) mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED,
      fd, offset & ~((1 << 12) - 1));
  if (filep == MAP_FAILED) {
    return -1;
  }

  // Offset into a data block to start working at.
  const unsigned int rounded_offset_diff =
    ((offset + (kTestDataSize - 1)) & (~(kTestDataSize - 1))) - offset;

  // The start of the write range is not aligned with our data blocks.
  // Therefore, we should write out part of a data block for this segment,
  // with the first character in the data block aligning with the data block
  // boundary.
  if (rounded_offset_diff != 0) {
    const char *file_start_offset = filep + (offset & ((1 << 12) - 1));
    const unsigned int test_data_offset = offset & (kTestDataSize - 1);
    memcpy((char *) file_start_offset, kTestDataBlock + test_data_offset,
        kTestDataSize - test_data_offset);
  }

  // Write out the rest of the data for this request. All writes from here out
  // will have their first byte aligned with kTestDataSize.
  unsigned int num_written = 0;
  while (num_written != size - rounded_offset_diff) {
    const unsigned int to_write =
      (num_written + kTestDataSize > size - rounded_offset_diff)
      ? size - rounded_offset_diff - num_written
      : kTestDataSize;
    memcpy(filep + rounded_offset_diff + num_written, kTestDataBlock,
        to_write);
    num_written += to_write;
  }

  if (msync(filep, map_size, MS_SYNC) < 0) {
    munmap(filep, map_size);
    return -1;
  }

  munmap(filep, map_size);
  return 0;
}

} // fs_testing
} // user_tools
} // api
<commit_msg>Change writedata function to work with <4K writes<commit_after>#include <errno.h>
#include <sys/mman.h>
#include <unistd.h>

#include <cassert>
#include <cstring>

#include "../api/workload.h"

// Super ugly defines to do compile-time string concatonation X times...
#define REP0(x)
#define REP1(x)     x
#define REP2(x)     REP1(x) x
#define REP3(x)     REP2(x) x
#define REP4(x)     REP3(x) x
#define REP5(x)     REP4(x) x
#define REP6(x)     REP5(x) x
#define REP7(x)     REP6(x) x
#define REP8(x)     REP7(x) x
#define REP9(x)     REP8(x) x
#define REP10(x)    REP9(x) x

#define REP(hundreds, tens, ones, x) \
  REP##hundreds(REP10(REP10(x))) \
  REP##tens(REP10(x)) \
  REP##ones(x)

namespace fs_testing {
namespace user_tools {
namespace api {

namespace {

// We want exactly 4k of data for this.
static const unsigned int kTestDataSize = 4096;
// 4K of data plus one terminating byte.
static constexpr char kTestDataBlock[kTestDataSize + 1] =
  REP(1, 2, 8, "abcdefghijklmnopqrstuvwxyz123456");

}  // namespace

int WriteData(int fd, unsigned int offset, unsigned int size) {
  // Offset into a data block to start working at.
  const unsigned int rounded_offset =
    (offset + (kTestDataSize - 1)) & (~(kTestDataSize - 1));
  // Round down size to 4k for number of full pages to write.

  const unsigned int aligned_size = (size > kTestDataSize) ? (size - (rounded_offset - offset)) & ~(kTestDataSize - 1): 0;
  unsigned int num_written = 0;

  // The start of the write range is not aligned with our data blocks.
  // Therefore, we should write out part of a data block for this segment,
  // with the first character in the data block aligning with the data block
  // boundary.
  if (rounded_offset != offset) {
    // We should never write more than kTestDataSize of unaligned data at the
    // start.
    while (offset + num_written < rounded_offset){
      const unsigned int mod_offset =
        num_written + (offset & (kTestDataSize - 1));
      assert(mod_offset < kTestDataSize);

      int res = pwrite(fd, kTestDataBlock + mod_offset,
          rounded_offset - (offset + num_written), offset + num_written);
      if (res < 0) {
        return errno;
      }
      num_written += res;
    }
  }

  // Write out the required number of full pages for this request. The first
  // byte will be aligned with kTestDataSize.
  unsigned int aligned_written = 0;
  while (aligned_written < aligned_size) {
    const unsigned int mod_offset = (aligned_written & (kTestDataSize - 1));
    // Write up to a full page of data at a time.
    int res = pwrite(fd, kTestDataBlock + mod_offset,
        kTestDataSize - mod_offset, offset + num_written);
    if (res < 0) {
      return errno;
    }
    num_written += res;
    aligned_written += res;
  }

  if (num_written == size) {
    return 0;
  }

  // Write out the last partial page of data. The first byte will be aligned
  // with kTestDataSize.
  unsigned int end_written = 0;
  while (num_written < size) {
    assert(end_written < kTestDataSize);
    const unsigned int mod_offset = (end_written & (kTestDataSize - 1));
    int res = pwrite(fd, kTestDataBlock + mod_offset,
        size - num_written, offset + num_written);
    if (res < 0) {
      return errno;
    }
    num_written += res;
    end_written += res;
  }

  return 0;
}

int WriteDataMmap(int fd, unsigned int offset, unsigned int size) {
  const unsigned int map_size = size + (offset & ((1 << 12) - 1));
  char *filep = (char *) mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED,
      fd, offset & ~((1 << 12) - 1));
  if (filep == MAP_FAILED) {
    return -1;
  }

  // Offset into a data block to start working at.
  const unsigned int rounded_offset_diff =
    ((offset + (kTestDataSize - 1)) & (~(kTestDataSize - 1))) - offset;

  // The start of the write range is not aligned with our data blocks.
  // Therefore, we should write out part of a data block for this segment,
  // with the first character in the data block aligning with the data block
  // boundary.
  if (rounded_offset_diff != 0) {
    const char *file_start_offset = filep + (offset & ((1 << 12) - 1));
    const unsigned int test_data_offset = offset & (kTestDataSize - 1);
    memcpy((char *) file_start_offset, kTestDataBlock + test_data_offset,
        kTestDataSize - test_data_offset);
  }

  // Write out the rest of the data for this request. All writes from here out
  // will have their first byte aligned with kTestDataSize.
  unsigned int num_written = 0;
  while (num_written != size - rounded_offset_diff) {
    const unsigned int to_write =
      (num_written + kTestDataSize > size - rounded_offset_diff)
      ? size - rounded_offset_diff - num_written
      : kTestDataSize;
    memcpy(filep + rounded_offset_diff + num_written, kTestDataBlock,
        to_write);
    num_written += to_write;
  }

  if (msync(filep, map_size, MS_SYNC) < 0) {
    munmap(filep, map_size);
    return -1;
  }

  munmap(filep, map_size);
  return 0;
}

} // fs_testing
} // user_tools
} // api
<|endoftext|>