<commit_before>
#include <iostream>
#include "polylines.h"
#include "geometry.h"
#include "mesh.h"
#include "clipper.h"
#include "libtess2/tesselator.h"
#include <core/contract.h>
#include <core/scope_guard.h>

namespace
{
	constexpr double PI = 3.14159265358979323846;
}

namespace draw
{

////////////////////////////////////////

polylines::polylines( void )
{
}

////////////////////////////////////////

void polylines::new_polyline( void )
{
	if ( _lines.empty() )
		_lines.emplace_back();
	if ( !_lines.back().empty() )
		_lines.emplace_back();
}

////////////////////////////////////////

void polylines::move_to( const core::point &p )
{
	if ( _lines.empty() )
		_lines.emplace_back();
	if ( !_lines.back().empty() )
		_lines.emplace_back();

	_lines.back().push_back( p );
}

////////////////////////////////////////

void polylines::line_to( const core::point &p )
{
	precondition( !_lines.empty(), "no point to start from" );
	precondition( !_lines.back().empty(), "no point to start from" );
	_lines.back().push_back( p );
}

////////////////////////////////////////

void polylines::quadratic_to( const core::point &p1, const core::point &p2 )
{
	precondition( !_lines.empty(), "no point to start from" );
	precondition( !_lines.back().empty(), "no point to start from" );
	add_quadratic( _lines.back().back(), p1, p2, _lines.back() );
}

////////////////////////////////////////

void polylines::cubic_to( const core::point &p1, const core::point &p2, const core::point &p3 )
{
	precondition( !_lines.empty(), "no point to start from" );
	precondition( !_lines.back().empty(), "no point to start from" );
	add_cubic( _lines.back().back(), p1, p2, p3, _lines.back() );
}

////////////////////////////////////////

void polylines::arc_to( const core::point &center, double radius, double angle1, double angle2 )
{
	precondition( !_lines.empty(), "no point to start from" );
	add_arc( center, radius, angle1, angle2, _lines.back() );
}

////////////////////////////////////////

/*
void polylines::arc_to( const point &center, const point &radius, double angle1, double angle2 )
{
	_points.push_back( center );
	_points.push_back( radius );
	_points.emplace_back( angle1, angle2 );
	_actions.push_back( action::ARC );
}
*/

////////////////////////////////////////

void polylines::add_point( const core::point &p )
{
	precondition( !_lines.empty(), "no point to start from" );
	_lines.back().push_back( p );
}

////////////////////////////////////////

void polylines::close( void )
{
	precondition( !_lines.empty(), "no polyline to close" );
	_lines.back().close();
	_lines.emplace_back();
}

////////////////////////////////////////

polylines polylines::stroked( double width )
{
	using namespace ClipperLib;
	Path subj;
	Paths solution;

	polylines result;
	for ( const auto &line: _lines )
	{
		subj.clear();
		for ( const auto &p: line )
			subj << IntPoint( p.x() * 100 + 0.5, p.y() * 100 + 0.5 );
		if ( line.closed() )
			subj << IntPoint( line.front().x() * 100 + 0.5, line.front().y() * 100 + 0.5 );

		ClipperOffset co;
		co.AddPath( subj, jtRound, etOpenRound );
		solution.clear();
		co.Execute( solution, width * 50 );

		for ( auto path: solution )
		{
			result.new_polyline();
			for ( const auto &p: path )
				result.add_point( { p.X / 100.0, p.Y / 100.0 } );
			result.close();
		}
	}

	return result;
}

////////////////////////////////////////

polylines polylines::offset( double width )
{
	using namespace ClipperLib;
	Path subj;
	Paths solution;

	polylines result;
	for ( const auto &line: _lines )
	{
		subj.clear();
		for ( const auto &p: line )
			subj << IntPoint( p.x() * 100 + 0.5, p.y() * 100 + 0.5 );

		ClipperOffset co;
		co.AddPath( subj, jtRound, line.closed() ? etClosedPolygon : etOpenRound );
		solution.clear();
		co.Execute( solution, width * 100 );

		for ( const auto &path: solution )
		{
			result.new_polyline();
			for ( const auto &p: path )
				result.add_point( { p.X / 100.0, p.Y / 100.0 } );
			result.close();
		}
	}

	return result;
}

////////////////////////////////////////

mesh<core::point> polylines::debug( void )
{
	mesh<core::point> result;
	for ( const auto &line: _lines )
	{
		if ( line.closed() )
			result.begin( gl::primitive::LINE_LOOP );
		else
			result.begin( gl::primitive::LINE_STRIP );
		for ( const auto &p: line )
			result.push_back( p );
		result.end();
	}

	return result;
}

////////////////////////////////////////

namespace {
	void *stdAlloc( void *data, unsigned int size )
	{
		return malloc( size );
	}

	void stdFree( void *data, void *ptr )
	{
		free( ptr );
	}

}

mesh<core::point> polylines::filled( void )
{
	precondition( !_lines.empty(), "no polylines" );

	using namespace ClipperLib;
	Path subj;
	Clipper clip;
	for ( const auto &line: _lines )
	{
		if ( !line.empty() )
		{
			subj.clear();
			for ( const auto &p: line )
				subj << IntPoint( p.x() * 100 + 0.5, p.y() * 100 + 0.5 );
			clip.AddPath( subj, ptSubject, line.closed() );
		}
	}

	Paths solution;
	clip.Execute( ctUnion, solution );

	TESSalloc ma;
	memset( &ma, 0, sizeof(ma) );
	ma.memalloc = &stdAlloc;
	ma.memfree = &stdFree;

	TESStesselator *tess = tessNewTess( &ma );
	if ( !tess )
		throw std::runtime_error( "tesselator creation failed" );
	on_scope_exit += [=]() { tessDeleteTess( tess ); };

	std::vector<TESSreal> tmp;
	for ( auto path: solution )
	{
		tmp.clear();
		for ( size_t p = 0; p < path.size(); ++p )
		{
			tmp.push_back( path[p].X / 100.0 );
			tmp.push_back( path[p].Y / 100.0 );
		}
		tessAddContour( tess, 2, tmp.data(), sizeof(float)*2, tmp.size()/2 );
	}

	if ( !tessTesselate( tess, TESS_WINDING_POSITIVE, TESS_POLYGONS, 3, 2, nullptr ) )
		throw std::runtime_error( "tesselation failed" );

	const float *verts = tessGetVertices( tess );
	const int *elems = tessGetElements( tess );
	const int nelems = tessGetElementCount( tess );

	// TODO use element array when it's added to the GL library
	mesh<core::point> m;
	m.begin( gl::primitive::TRIANGLES );
	for ( int i = 0; i < nelems; ++i )
	{
		const int *p = &elems[i*3];
		for ( int j = 0; j < 3 && p[j] != TESS_UNDEF; ++j )
			m.push_back( { verts[p[j]*2], verts[p[j]*2+1] } );
	}
	m.end();

	return m;
}

////////////////////////////////////////

}

<commit_msg>Removed unused constant.<commit_after>
#include <iostream>
#include "polylines.h"
#include "geometry.h"
#include "mesh.h"
#include "clipper.h"
#include "libtess2/tesselator.h"
#include <core/contract.h>
#include <core/scope_guard.h>

namespace draw
{

////////////////////////////////////////

polylines::polylines( void )
{
}

////////////////////////////////////////

void polylines::new_polyline( void )
{
	if ( _lines.empty() )
		_lines.emplace_back();
	if ( !_lines.back().empty() )
		_lines.emplace_back();
}

////////////////////////////////////////

void polylines::move_to( const core::point &p )
{
	if ( _lines.empty() )
		_lines.emplace_back();
	if ( !_lines.back().empty() )
		_lines.emplace_back();

	_lines.back().push_back( p );
}

////////////////////////////////////////

void polylines::line_to( const core::point &p )
{
	precondition( !_lines.empty(), "no point to start from" );
	precondition( !_lines.back().empty(), "no point to start from" );
	_lines.back().push_back( p );
}

////////////////////////////////////////

void polylines::quadratic_to( const core::point &p1, const core::point &p2 )
{
	precondition( !_lines.empty(), "no point to start from" );
	precondition( !_lines.back().empty(), "no point to start from" );
	add_quadratic( _lines.back().back(), p1, p2, _lines.back() );
}

////////////////////////////////////////

void polylines::cubic_to( const core::point &p1, const core::point &p2, const core::point &p3 )
{
	precondition( !_lines.empty(), "no point to start from" );
	precondition( !_lines.back().empty(), "no point to start from" );
	add_cubic( _lines.back().back(), p1, p2, p3, _lines.back() );
}

////////////////////////////////////////

void polylines::arc_to( const core::point &center, double radius, double angle1, double angle2 )
{
	precondition( !_lines.empty(), "no point to start from" );
	add_arc( center, radius, angle1, angle2, _lines.back() );
}

////////////////////////////////////////

/*
void polylines::arc_to( const point &center, const point &radius, double angle1, double angle2 )
{
	_points.push_back( center );
	_points.push_back( radius );
	_points.emplace_back( angle1, angle2 );
	_actions.push_back( action::ARC );
}
*/

////////////////////////////////////////

void polylines::add_point( const core::point &p )
{
	precondition( !_lines.empty(), "no point to start from" );
	_lines.back().push_back( p );
}

////////////////////////////////////////

void polylines::close( void )
{
	precondition( !_lines.empty(), "no polyline to close" );
	_lines.back().close();
	_lines.emplace_back();
}

////////////////////////////////////////

polylines polylines::stroked( double width )
{
	using namespace ClipperLib;
	Path subj;
	Paths solution;

	polylines result;
	for ( const auto &line: _lines )
	{
		subj.clear();
		for ( const auto &p: line )
			subj << IntPoint( p.x() * 100 + 0.5, p.y() * 100 + 0.5 );
		if ( line.closed() )
			subj << IntPoint( line.front().x() * 100 + 0.5, line.front().y() * 100 + 0.5 );

		ClipperOffset co;
		co.AddPath( subj, jtRound, etOpenRound );
		solution.clear();
		co.Execute( solution, width * 50 );

		for ( auto path: solution )
		{
			result.new_polyline();
			for ( const auto &p: path )
				result.add_point( { p.X / 100.0, p.Y / 100.0 } );
			result.close();
		}
	}

	return result;
}

////////////////////////////////////////

polylines polylines::offset( double width )
{
	using namespace ClipperLib;
	Path subj;
	Paths solution;

	polylines result;
	for ( const auto &line: _lines )
	{
		subj.clear();
		for ( const auto &p: line )
			subj << IntPoint( p.x() * 100 + 0.5, p.y() * 100 + 0.5 );

		ClipperOffset co;
		co.AddPath( subj, jtRound, line.closed() ? etClosedPolygon : etOpenRound );
		solution.clear();
		co.Execute( solution, width * 100 );

		for ( const auto &path: solution )
		{
			result.new_polyline();
			for ( const auto &p: path )
				result.add_point( { p.X / 100.0, p.Y / 100.0 } );
			result.close();
		}
	}

	return result;
}

////////////////////////////////////////

mesh<core::point> polylines::debug( void )
{
	mesh<core::point> result;
	for ( const auto &line: _lines )
	{
		if ( line.closed() )
			result.begin( gl::primitive::LINE_LOOP );
		else
			result.begin( gl::primitive::LINE_STRIP );
		for ( const auto &p: line )
			result.push_back( p );
		result.end();
	}

	return result;
}

////////////////////////////////////////

namespace {
	void *stdAlloc( void *data, unsigned int size )
	{
		return malloc( size );
	}

	void stdFree( void *data, void *ptr )
	{
		free( ptr );
	}

}

mesh<core::point> polylines::filled( void )
{
	precondition( !_lines.empty(), "no polylines" );

	using namespace ClipperLib;
	Path subj;
	Clipper clip;
	for ( const auto &line: _lines )
	{
		if ( !line.empty() )
		{
			subj.clear();
			for ( const auto &p: line )
				subj << IntPoint( p.x() * 100 + 0.5, p.y() * 100 + 0.5 );
			clip.AddPath( subj, ptSubject, line.closed() );
		}
	}

	Paths solution;
	clip.Execute( ctUnion, solution );

	TESSalloc ma;
	memset( &ma, 0, sizeof(ma) );
	ma.memalloc = &stdAlloc;
	ma.memfree = &stdFree;

	TESStesselator *tess = tessNewTess( &ma );
	if ( !tess )
		throw std::runtime_error( "tesselator creation failed" );
	on_scope_exit += [=]() { tessDeleteTess( tess ); };

	std::vector<TESSreal> tmp;
	for ( auto path: solution )
	{
		tmp.clear();
		for ( size_t p = 0; p < path.size(); ++p )
		{
			tmp.push_back( path[p].X / 100.0 );
			tmp.push_back( path[p].Y / 100.0 );
		}
		tessAddContour( tess, 2, tmp.data(), sizeof(float)*2, tmp.size()/2 );
	}

	if ( !tessTesselate( tess, TESS_WINDING_POSITIVE, TESS_POLYGONS, 3, 2, nullptr ) )
		throw std::runtime_error( "tesselation failed" );

	const float *verts = tessGetVertices( tess );
	const int *elems = tessGetElements( tess );
	const int nelems = tessGetElementCount( tess );

	// TODO use element array when it's added to the GL library
	mesh<core::point> m;
	m.begin( gl::primitive::TRIANGLES );
	for ( int i = 0; i < nelems; ++i )
	{
		const int *p = &elems[i*3];
		for ( int j = 0; j < 3 && p[j] != TESS_UNDEF; ++j )
			m.push_back( { verts[p[j]*2], verts[p[j]*2+1] } );
	}
	m.end();

	return m;
}

////////////////////////////////////////

}

<|endoftext|>


<commit_before>/*
 * libjingle
 * Copyright 2014 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

#if defined(LIBPEERCONNECTION_LIB) || defined(LIBPEERCONNECTION_IMPLEMENTATION)

#include "talk/media/webrtc/webrtcmediaengine.h"
#include "talk/media/webrtc/webrtcvideoengine.h"
#include "talk/media/webrtc/webrtcvideoengine2.h"
#include "talk/media/webrtc/webrtcvoiceengine.h"
#include "webrtc/system_wrappers/interface/field_trial.h"

namespace cricket {

class WebRtcMediaEngine
    : public CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine> {
 public:
  WebRtcMediaEngine() {}
  WebRtcMediaEngine(webrtc::AudioDeviceModule* adm,
                    webrtc::AudioDeviceModule* adm_sc,
                    WebRtcVideoEncoderFactory* encoder_factory,
                    WebRtcVideoDecoderFactory* decoder_factory) {
    voice_.SetAudioDeviceModule(adm, adm_sc);
    video_.SetExternalEncoderFactory(encoder_factory);
    video_.SetExternalDecoderFactory(decoder_factory);
  }
};

class WebRtcMediaEngine2
    : public CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine2> {
 public:
  WebRtcMediaEngine2(webrtc::AudioDeviceModule* adm,
                     webrtc::AudioDeviceModule* adm_sc,
                     WebRtcVideoEncoderFactory* encoder_factory,
                     WebRtcVideoDecoderFactory* decoder_factory) {
    voice_.SetAudioDeviceModule(adm, adm_sc);
    video_.SetExternalDecoderFactory(decoder_factory);
    video_.SetExternalEncoderFactory(encoder_factory);
  }
};

}  // namespace cricket

WRME_EXPORT
cricket::MediaEngineInterface* CreateWebRtcMediaEngine(
    webrtc::AudioDeviceModule* adm,
    webrtc::AudioDeviceModule* adm_sc,
    cricket::WebRtcVideoEncoderFactory* encoder_factory,
    cricket::WebRtcVideoDecoderFactory* decoder_factory) {
  return new cricket::WebRtcMediaEngine2(adm, adm_sc, encoder_factory,
                                         decoder_factory);
}

WRME_EXPORT
void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) {
  delete media_engine;
}

namespace cricket {

// Used by ChannelManager when no media engine is passed in to it
// explicitly (acts as a default).
MediaEngineInterface* WebRtcMediaEngineFactory::Create() {
  return new cricket::WebRtcMediaEngine();
}

// Used by PeerConnectionFactory to create a media engine passed into
// ChannelManager.
MediaEngineInterface* WebRtcMediaEngineFactory::Create(
    webrtc::AudioDeviceModule* adm,
    webrtc::AudioDeviceModule* adm_sc,
    WebRtcVideoEncoderFactory* encoder_factory,
    WebRtcVideoDecoderFactory* decoder_factory) {
  return CreateWebRtcMediaEngine(adm, adm_sc, encoder_factory, decoder_factory);
}

}  // namespace cricket

#endif  // defined(LIBPEERCONNECTION_LIB) ||
        // defined(LIBPEERCONNECTION_IMPLEMENTATION)
<commit_msg>Revert 8809 "Set WebRtcVideoEngine2 as the WebRtcMediaEngine." content_browsertests started failing around the time the change landed and rolls are failing now. I'm going to try rolling this back, start a roll, and then re-land.<commit_after>/*
 * libjingle
 * Copyright 2014 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

#if defined(LIBPEERCONNECTION_LIB) || defined(LIBPEERCONNECTION_IMPLEMENTATION)

#include "talk/media/webrtc/webrtcmediaengine.h"
#include "talk/media/webrtc/webrtcvideoengine.h"
#include "talk/media/webrtc/webrtcvideoengine2.h"
#include "talk/media/webrtc/webrtcvoiceengine.h"
#include "webrtc/system_wrappers/interface/field_trial.h"

namespace cricket {

class WebRtcMediaEngine
    : public CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine> {
 public:
  WebRtcMediaEngine() {}
  WebRtcMediaEngine(webrtc::AudioDeviceModule* adm,
                    webrtc::AudioDeviceModule* adm_sc,
                    WebRtcVideoEncoderFactory* encoder_factory,
                    WebRtcVideoDecoderFactory* decoder_factory) {
    voice_.SetAudioDeviceModule(adm, adm_sc);
    video_.SetExternalEncoderFactory(encoder_factory);
    video_.SetExternalDecoderFactory(decoder_factory);
  }
};

class WebRtcMediaEngine2
    : public CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine2> {
 public:
  WebRtcMediaEngine2(webrtc::AudioDeviceModule* adm,
                     webrtc::AudioDeviceModule* adm_sc,
                     WebRtcVideoEncoderFactory* encoder_factory,
                     WebRtcVideoDecoderFactory* decoder_factory) {
    voice_.SetAudioDeviceModule(adm, adm_sc);
    video_.SetExternalDecoderFactory(decoder_factory);
    video_.SetExternalEncoderFactory(encoder_factory);
  }
};

}  // namespace cricket

WRME_EXPORT
cricket::MediaEngineInterface* CreateWebRtcMediaEngine(
    webrtc::AudioDeviceModule* adm,
    webrtc::AudioDeviceModule* adm_sc,
    cricket::WebRtcVideoEncoderFactory* encoder_factory,
    cricket::WebRtcVideoDecoderFactory* decoder_factory) {
  if (webrtc::field_trial::FindFullName("WebRTC-NewVideoAPI") == "Enabled") {
    return new cricket::WebRtcMediaEngine2(adm, adm_sc, encoder_factory,
                                           decoder_factory);
  }
  return new cricket::WebRtcMediaEngine(adm, adm_sc, encoder_factory,
                                        decoder_factory);
}

WRME_EXPORT
void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) {
  delete media_engine;
}

namespace cricket {

// Used by ChannelManager when no media engine is passed in to it
// explicitly (acts as a default).
MediaEngineInterface* WebRtcMediaEngineFactory::Create() {
  return new cricket::WebRtcMediaEngine();
}

// Used by PeerConnectionFactory to create a media engine passed into
// ChannelManager.
MediaEngineInterface* WebRtcMediaEngineFactory::Create(
    webrtc::AudioDeviceModule* adm,
    webrtc::AudioDeviceModule* adm_sc,
    WebRtcVideoEncoderFactory* encoder_factory,
    WebRtcVideoDecoderFactory* decoder_factory) {
  return CreateWebRtcMediaEngine(adm, adm_sc, encoder_factory, decoder_factory);
}

}  // namespace cricket

#endif  // defined(LIBPEERCONNECTION_LIB) ||
        // defined(LIBPEERCONNECTION_IMPLEMENTATION)
<|endoftext|>


<commit_before>/*
The MIT License (MIT)
Copyright (c) 2015 University of Central Florida's Computer Software Engineering
Scalable & Secure Systems (CSE - S3) Lab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string>
#include <fstream>
#include <iostream>

#include "connection.h"

#define MAXDATASIZE 100

/************************************************************************
 * Temp struct holder for results
 ************************************************************************/
/** Used to hold result before parsing into objects **/
struct ResultHolder {
  char metaDataPacket[MESSAGE_SIZE];
  char resultPacket[MESSAGE_SIZE];
};

/*************************************************************************
 * Private Helper Functions                                              *
 *************************************************************************/
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

/**
 * Builds a network packet with the passed in parameters.
 * This network packet is necessary to send data across sockets.
 * @param type The type of command being passed.
 * @param command The command being sent to the server
 * @return a CommandPacket containing the information to be sent across the socket.
 */
CommandPacket buildPacket(CommandType type, std::string command) {
  CommandPacket commandPacket;
  // command needs to be made into char[]
  strncpy(commandPacket.message, command.c_str(), sizeof(commandPacket.message));
  commandPacket.message[sizeof(commandPacket.message) -1] = 0;
  commandPacket.commandType = type;
  commandPacket.terminator = THE_TERMINATOR;

  return commandPacket;
}

/**
 * Parses result packet and builds a vector of ResultRow s
 * @param packet The result packet to parse
 * @return a vector<ResultRow> containing the parsed data
 */
std::vector<libomdb::ResultRow> parseData(ResultPacket packet) {
  std::vector<libomdb::ResultRow> rows;
  // Each of the columns is 64bits, packet.resultSize is number of bytes
  // 8 bits to a byte, so 8 bytes per column, therefore number of columns
  // is packet.resultSize / 8
  uint32_t rowSizeInBytes = packet.rowLen * 8;
  uint32_t numberOfRows = (packet.resultSize / rowSizeInBytes);
  uint64_t* dataPointer = &packet.data[0];
  for (uint i = 0; i < numberOfRows; ++i) {
    libomdb::ResultRow row;
    for (uint j = 0; j < packet.rowLen; ++i) {
      int64_t* col;
      memcpy(col, dataPointer, 8); //Move the next 8 bytes into col
      row.push_back(*col);
      dataPointer += 2; // Move pointer up 8 bytes. dataPointer++ moves 4 bytes?
    }
    rows.push_back(row);
  }

  return rows;
}

/**
 * Parses a ResultMetaDataPacket and builds a list of MetaDataColumns which is
 * the core of the ResultMetaData class.
 * @param packet
 * @return A vector<MetaDataColumn> describing a result set
 */
std::vector<libomdb::MetaDataColumn> parseMetaData(ResultMetaDataPacket packet) {
  std::vector<libomdb::MetaDataColumn> metaDataColumns;
  for (uint i = 0; i < packet.numColumns; ++i) {
    libomdb::MetaDataColumn column;
    column.label = std::string(packet.columns[i].name);
    column.sqlType = packet.columns[i].type;
  }
  return metaDataColumns;
}

libomdb::CommandResult parseCommandResult(ResultHolder result) {
  //TODO: build CommandResult requires parsing neils string
}

/**
 * TODO: Add error checking
 */
libomdb::Result parseQueryResult(ResultHolder holder) {
  ResultMetaDataPacket resultMetaDataPacket =
      DeserializeResultMetaDataPacket(holder.metaDataPacket);

  ResultPacket resultPacket = DeserializeResultPacket(holder.resultPacket);

  // Build result object;
  std::vector<libomdb::ResultRow> rows = parseData(resultPacket);
  std::vector<libomdb::MetaDataColumn> metaDataColumns =
      parseMetaData(resultMetaDataPacket);
  libomdb::ResultMetaData metaData =
      libomdb::ResultMetaData::buildResultMetaDataObject(metaDataColumns);
  return libomdb::Result::buildResultObject(rows, metaData);
}

/**
 * Sends message across the socket passed in
 * @param message The message to send to the server
 * @param socket The file descriptor of the listening socket
 */
ResultHolder sendMessage(CommandPacket packet, int socket) {
  // Need to convert message to c string in order to send it.
  char message[MESSAGE_SIZE];
  memcpy(message, &packet, sizeof(packet));
  std::cout << "Message being sent: " << message <<std::endl;
  // const char* c_message = message.c_str();
  std::cout << "Attempting to send message to socket" << socket << std::endl;
  int bytes_sent = send(socket, message, sizeof message, 0);
  std::cout<< "Bytes sent: " << bytes_sent << std::endl;
  if (bytes_sent == -1) {
    perror("send");
    ResultHolder emptyHolder;
    return emptyHolder;
  }

  // Wait for receipt of message;
  /*
   * Results will now come in this order:
   * 1.) ResultMetaDataPacket
   * 2.) ResultPacket
   *
   * Build a struct containing both and return it.
   */
  ResultHolder holder;

  int bytes_recieved = recv(socket, holder.metaDataPacket, sizeof(holder.metaDataPacket), 0);
  std::cout << "Bytes relieved: " << bytes_recieved << std::endl;
  if (bytes_recieved == -1) {
    perror("recv");
    ResultHolder emptyHolder;
    return emptyHolder;
  }

  // Now receive result packet
  bytes_recieved = recv(socket, holder.resultPacket, sizeof(holder.resultPacket), 0);
  if (bytes_recieved == -1) {
    perror("recv");
    ResultHolder emptyHolder;
    return emptyHolder;
  }

  return holder;
}

/*************************************************************************
 * ConnectionMetaData Implementations                                    *
 *************************************************************************/
libomdb::ConnectionMetaData::ConnectionMetaData(std::string dbName, bool isValid)
        :m_databaseName(dbName), m_isValid(isValid) {}

std::string libomdb::ConnectionMetaData::getDbName() {
  return this->m_databaseName;
}

bool libomdb::ConnectionMetaData::isValid() {
  return this->m_isValid;
}

/*************************************************************************
 * Connection Implementations                                            *
 *************************************************************************/
libomdb::Connection libomdb::Connection::buildConnectionObj(uint16_t socket, char* buffer) {
  // TODO: Parse connection string and create new Connection object
  ConnectionPacket packet = DeserializeConnectionPacket(buffer);
  libomdb::ConnectionMetaData* connectionMetaData = new libomdb::ConnectionMetaData(packet.name, true);
  return  *new libomdb::Connection(socket, *connectionMetaData);

}

  // TODO: Break up this monstrosity.
libomdb::Connection libomdb::Connection::connect(std::string hostname,
                                                 uint16_t port,
                                                 std::string db) {
  int sockfd, numbytes;
  char buf[MAXDATASIZE];
  struct addrinfo hints, *servinfo, *p;
  int rv;
  char s[INET6_ADDRSTRLEN];

  // Convert hostname to c string
  const char* connection_ip = hostname.c_str();

  //Convert port to c string.
  const char* port_string = std::to_string(port).c_str();

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  if ((rv = getaddrinfo(connection_ip, port_string,
                        &hints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo: %d\n", rv);
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return errorConnection();
  }

  // loop through all the results and connect to the first we can
  for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype,
                                p->ai_protocol)) == -1) {
        perror("client: socket");
        continue;
      }

    if (::connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
      close(sockfd);
      perror("client: connect");
      continue;
    }

    break;
  }

  if (p == NULL) {
    fprintf(stderr, "client: failed to connect\n");
    return errorConnection();
  }

  inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
                                                          s, sizeof s);
  printf("client: connecting to %s\n", s);
  freeaddrinfo(servinfo); // all done with this structure

  if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
    perror("recv");
    return errorConnection();
  }

  buf[numbytes] = '\0';

  printf("client: received '%s'\n",buf);
  std::string dbConnectString = "k:"+db;
  const char* dbString = dbConnectString.c_str();
  // Sending the name of the database to the server.
  int bytesSent = send(sockfd, dbString, dbConnectString.length(), 0);
  if (bytesSent == -1) {
    perror("send");
    return errorConnection();
  }

  int bytesReceived = recv(sockfd, buf, MAXDATASIZE -1, 0);
  if (bytesReceived == -1) {
    perror("recv");
    return errorConnection();
  }

  buf[bytesReceived] = '\0';
  printf("client received response from server: %s\n", buf);

  return libomdb::Connection::buildConnectionObj(sockfd, buf);
}

void libomdb::Connection::disconnect() {
  close(this->m_socket_fd);
}

libomdb::CommandResult libomdb::Connection::executeCommand(std::string command) {
  CommandPacket packet = buildPacket(CommandType::DB_COMMAND, command);
  return parseCommandResult(sendMessage(packet, this->m_socket_fd));
}

libomdb::Result libomdb::Connection::executeQuery(std::string query) {
  CommandPacket packet = buildPacket(CommandType::SQL_STATEMENT, query);
  return parseQueryResult(sendMessage(packet, this->m_socket_fd));
}

libomdb::ConnectionMetaData libomdb::Connection::getMetaData() {
  return this->m_metaData;
}

void libomdb::Connection::setMetaData(libomdb::ConnectionMetaData data) {
  this->m_metaData = data;
}

libomdb::Connection::Connection(uint64_t socket_fd, ConnectionMetaData metaData)
        :m_metaData(metaData), m_socket_fd(socket_fd) {}<commit_msg>Added functionality for parseCommandResult<commit_after>/*
The MIT License (MIT)
Copyright (c) 2015 University of Central Florida's Computer Software Engineering
Scalable & Secure Systems (CSE - S3) Lab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string>
#include <fstream>
#include <iostream>

#include "connection.h"

#define MAXDATASIZE 100

/************************************************************************
 * Temp struct holder for results
 ************************************************************************/
/** Used to hold result before parsing into objects **/
struct ResultHolder {
  char metaDataPacket[MESSAGE_SIZE];
  char resultPacket[MESSAGE_SIZE];
};

/*************************************************************************
 * Private Helper Functions                                              *
 *************************************************************************/
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

/**
 * Builds a network packet with the passed in parameters.
 * This network packet is necessary to send data across sockets.
 * @param type The type of command being passed.
 * @param command The command being sent to the server
 * @return a CommandPacket containing the information to be sent across the socket.
 */
CommandPacket buildPacket(CommandType type, std::string command) {
  CommandPacket commandPacket;
  // command needs to be made into char[]
  strncpy(commandPacket.message, command.c_str(), sizeof(commandPacket.message));
  commandPacket.message[sizeof(commandPacket.message) -1] = 0;
  commandPacket.commandType = type;
  commandPacket.terminator = THE_TERMINATOR;

  return commandPacket;
}

/**
 * Parses result packet and builds a vector of ResultRow s
 * @param packet The result packet to parse
 * @return a vector<ResultRow> containing the parsed data
 */
std::vector<libomdb::ResultRow> parseData(ResultPacket packet) {
  std::vector<libomdb::ResultRow> rows;
  // Each of the columns is 64bits, packet.resultSize is number of bytes
  // 8 bits to a byte, so 8 bytes per column, therefore number of columns
  // is packet.resultSize / 8
  uint32_t rowSizeInBytes = packet.rowLen * 8;
  uint32_t numberOfRows = (packet.resultSize / rowSizeInBytes);
  uint64_t* dataPointer = &packet.data[0];
  for (uint i = 0; i < numberOfRows; ++i) {
    libomdb::ResultRow row;
    for (uint j = 0; j < packet.rowLen; ++i) {
      int64_t* col = new int64_t;
      memcpy(col, dataPointer, 8); //Move the next 8 bytes into col
      row.push_back(*col);
      delete(col); // TODO: Do I need this?
      dataPointer += 2; // Move pointer up 8 bytes. dataPointer++ moves 4 bytes?
    }
    rows.push_back(row);
  }

  return rows;
}

/**
 * Parses a ResultMetaDataPacket and builds a list of MetaDataColumns which is
 * the core of the ResultMetaData class.
 * @param packet
 * @return A vector<MetaDataColumn> describing a result set
 */
std::vector<libomdb::MetaDataColumn> parseMetaData(ResultMetaDataPacket packet) {
  std::vector<libomdb::MetaDataColumn> metaDataColumns;
  for (uint i = 0; i < packet.numColumns; ++i) {
    libomdb::MetaDataColumn column;
    column.label = std::string(packet.columns[i].name);
    column.sqlType = packet.columns[i].type;
  }
  return metaDataColumns;
}

/**
 * Parses a ResultHolder and builds a CommandResult from the contents
 * @param result The ResultHolder to parse
 * @return A CommandResult with parsed data
 */
libomdb::CommandResult parseCommandResult(ResultHolder result) {
  //ResultMetaDataPacket metaDataPacket = DeserializeResultMetaDataPacket(result.metaDataPacket);
  ResultPacket packet = DeserializeResultPacket(result.resultPacket);
  libomdb::CommandResult commandResult;
  commandResult.isSuccess = packet.status == ResultStatus::OK;
  commandResult.numAffected = packet.resultSize; // TODO: Confirm with neil
  return commandResult;
}

/**
 * TODO: Add error checking
 */
libomdb::Result parseQueryResult(ResultHolder holder) {
  ResultMetaDataPacket resultMetaDataPacket =
      DeserializeResultMetaDataPacket(holder.metaDataPacket);

  ResultPacket resultPacket = DeserializeResultPacket(holder.resultPacket);

  // Build result object;
  std::vector<libomdb::ResultRow> rows = parseData(resultPacket);
  std::vector<libomdb::MetaDataColumn> metaDataColumns =
      parseMetaData(resultMetaDataPacket);
  libomdb::ResultMetaData metaData =
      libomdb::ResultMetaData::buildResultMetaDataObject(metaDataColumns);
  return libomdb::Result::buildResultObject(rows, metaData);
}

/**
 * Sends message across the socket passed in
 * @param message The message to send to the server
 * @param socket The file descriptor of the listening socket
 */
ResultHolder sendMessage(CommandPacket packet, int socket) {
  // Need to convert message to c string in order to send it.
  char message[MESSAGE_SIZE];
  memcpy(message, &packet, sizeof(packet));
  std::cout << "Message being sent: " << message <<std::endl;
  // const char* c_message = message.c_str();
  std::cout << "Attempting to send message to socket" << socket << std::endl;
  int bytes_sent = send(socket, message, sizeof message, 0);
  std::cout<< "Bytes sent: " << bytes_sent << std::endl;
  if (bytes_sent == -1) {
    perror("send");
    ResultHolder emptyHolder;
    return emptyHolder;
  }

  // Wait for receipt of message;
  /*
   * Results will now come in this order:
   * 1.) ResultMetaDataPacket
   * 2.) ResultPacket
   *
   * Build a struct containing both and return it.
   */
  ResultHolder holder;

  int bytes_recieved = recv(socket, holder.metaDataPacket, sizeof(holder.metaDataPacket), 0);
  std::cout << "Bytes relieved: " << bytes_recieved << std::endl;
  if (bytes_recieved == -1) {
    perror("recv");
    ResultHolder emptyHolder;
    return emptyHolder;
  }

  // Now receive result packet
  bytes_recieved = recv(socket, holder.resultPacket, sizeof(holder.resultPacket), 0);
  if (bytes_recieved == -1) {
    perror("recv");
    ResultHolder emptyHolder;
    return emptyHolder;
  }

  return holder;
}

/*************************************************************************
 * ConnectionMetaData Implementations                                    *
 *************************************************************************/
libomdb::ConnectionMetaData::ConnectionMetaData(std::string dbName, bool isValid)
        :m_databaseName(dbName), m_isValid(isValid) {}

std::string libomdb::ConnectionMetaData::getDbName() {
  return this->m_databaseName;
}

bool libomdb::ConnectionMetaData::isValid() {
  return this->m_isValid;
}

/*************************************************************************
 * Connection Implementations                                            *
 *************************************************************************/
libomdb::Connection libomdb::Connection::buildConnectionObj(uint16_t socket, char* buffer) {
  ConnectionPacket packet = DeserializeConnectionPacket(buffer);
  libomdb::ConnectionMetaData* connectionMetaData = new libomdb::ConnectionMetaData(packet.name, true);
  return  *new libomdb::Connection(socket, *connectionMetaData);

}

  // TODO: Break up this monstrosity.
libomdb::Connection libomdb::Connection::connect(std::string hostname,
                                                 uint16_t port,
                                                 std::string db) {
  int sockfd, numbytes;
  char buf[MAXDATASIZE];
  struct addrinfo hints, *servinfo, *p;
  int rv;
  char s[INET6_ADDRSTRLEN];

  // Convert hostname to c string
  const char* connection_ip = hostname.c_str();

  //Convert port to c string.
  const char* port_string = std::to_string(port).c_str();

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  if ((rv = getaddrinfo(connection_ip, port_string,
                        &hints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo: %d\n", rv);
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return errorConnection();
  }

  // loop through all the results and connect to the first we can
  for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype,
                                p->ai_protocol)) == -1) {
        perror("client: socket");
        continue;
      }

    if (::connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
      close(sockfd);
      perror("client: connect");
      continue;
    }

    break;
  }

  if (p == NULL) {
    fprintf(stderr, "client: failed to connect\n");
    return errorConnection();
  }

  inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
                                                          s, sizeof s);
  printf("client: connecting to %s\n", s);
  freeaddrinfo(servinfo); // all done with this structure

  if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
    perror("recv");
    return errorConnection();
  }

  buf[numbytes] = '\0';

  printf("client: received '%s'\n",buf);
  std::string dbConnectString = "k:"+db;
  const char* dbString = dbConnectString.c_str();
  // Sending the name of the database to the server.
  int bytesSent = send(sockfd, dbString, dbConnectString.length(), 0);
  if (bytesSent == -1) {
    perror("send");
    return errorConnection();
  }

  int bytesReceived = recv(sockfd, buf, MAXDATASIZE -1, 0);
  if (bytesReceived == -1) {
    perror("recv");
    return errorConnection();
  }

  buf[bytesReceived] = '\0';
  printf("client received response from server: %s\n", buf);

  return libomdb::Connection::buildConnectionObj(sockfd, buf);
}

void libomdb::Connection::disconnect() {
  close(this->m_socket_fd);
}

libomdb::CommandResult libomdb::Connection::executeCommand(std::string command) {
  CommandPacket packet = buildPacket(CommandType::DB_COMMAND, command);
  return parseCommandResult(sendMessage(packet, this->m_socket_fd));
}

libomdb::Result libomdb::Connection::executeQuery(std::string query) {
  CommandPacket packet = buildPacket(CommandType::SQL_STATEMENT, query);
  return parseQueryResult(sendMessage(packet, this->m_socket_fd));
}

libomdb::ConnectionMetaData libomdb::Connection::getMetaData() {
  return this->m_metaData;
}

void libomdb::Connection::setMetaData(libomdb::ConnectionMetaData data) {
  this->m_metaData = data;
}

libomdb::Connection::Connection(uint64_t socket_fd, ConnectionMetaData metaData)
        :m_metaData(metaData), m_socket_fd(socket_fd) {}<|endoftext|>


<commit_before><commit_msg>Median of array<commit_after><|endoftext|>


<commit_before>#include <devices/m35fd.hpp>

#include <cassert>

namespace cpu {

namespace m35fd {

// M35FD class ****************************************************************

M35FD::M35FD() : state(STATE_CODES::NO_MEDIA), error(ERROR_CODES::NONE),
                 busy_cycles(0)
{ }

M35FD::~M35FD()
{
    if (floppy)
        eject();
}

void M35FD::attachTo (DCPU* cpu, size_t index)
{
    this->IHardware::attachTo(cpu, index);
    if (floppy) {
        state = floppy->isProtected() ?
                    STATE_CODES::READY_WP : STATE_CODES::READY;
    } else {
        state = STATE_CODES::NO_MEDIA;
    }

    error = ERROR_CODES::NONE;
}

bool M35FD::checkInterrupt (uint16_t& msg)
{
    if (this->msg != 0 && true) {
        msg = this->msg;
        return true;
    }
    return false;
}

unsigned M35FD::handleInterrupt()
{
    if (cpu == NULL)
        return 0;

    switch (static_cast<COMMANDS>(cpu->getA())) {
    case COMMANDS::POLL :
        cpu->setB(static_cast<uint16_t>(state));
        cpu->setC(static_cast<uint16_t>(error));
        LOG_DEBUG << "[M35FD] polling E:" << static_cast<uint16_t>(state) <<
                                    " R:" << static_cast<uint16_t>(error);
        break;

    case COMMANDS::SET_INTERRUPT :
        msg = cpu->getX();
        break;

    case COMMANDS::READ_SECTOR :
        if (state == STATE_CODES::READY || state == STATE_CODES::READY_WP) {
            if (! floppy) { // This not should happen never, but...
                state = STATE_CODES::NO_MEDIA;
                error = ERROR_CODES::BROKEN;
                cpu->setB(0);
                LOG_ERROR << "[M35FD] Something weird happen trying to Read";
                break;
            }
            floppy->read(cpu->getX(), cpu->getY(), busy_cycles);
            state = STATE_CODES::BUSY;
            error = ERROR_CODES::NONE;
            cpu->setB(1);

        } else {
            if (state == STATE_CODES::NO_MEDIA) {
                error = ERROR_CODES::NO_MEDIA;
            } else if (state == STATE_CODES::BUSY) {
                error = ERROR_CODES::BUSY;
            }

            LOG_DEBUG << "[M35FD] Reading set to Error: "
                        << static_cast<int>(error);
            cpu->setB(0);
        }
        break;

    case COMMANDS::WRITE_SECTOR :
        if (state == STATE_CODES::READY) {
            if (! floppy) { // This not should happen never, but...
                state = STATE_CODES::NO_MEDIA;
                error = ERROR_CODES::BROKEN;
                cpu->setB(0);
                LOG_ERROR << "[M35FD] Something weird happen trying to Write";
                break;
            }
            floppy->write(cpu->getX(), cpu->getY(), busy_cycles);
            state = STATE_CODES::BUSY;
            error = ERROR_CODES::NONE;
            cpu->setB(1);
        } else {
            if (state == STATE_CODES::NO_MEDIA) {
                error = ERROR_CODES::NO_MEDIA;
            } else if (state == STATE_CODES::READY_WP) {
                error = ERROR_CODES::PROTECTED;
            } else if (state == STATE_CODES::BUSY) {
                error = ERROR_CODES::BUSY;
            }

            LOG_DEBUG << "[M35FD] Writing set to Error: "
                        << static_cast<int>(error);
            cpu->setB(0);
        }
        break;

    default:
        break;
    }

    return 0;
}

void M35FD::tick()
{
    if (busy_cycles > 0) {
        busy_cycles--;
        // Read/write 1 word each 3 cycles. A bit more faster that the suposed
        // specs speeds, but more easy to do
        if (floppy && busy_cycles % 3)
            floppy->tick();

    } else if (floppy) {
        state = floppy->isProtected() ?
            STATE_CODES::READY_WP : STATE_CODES::READY;
    }
}

void M35FD::insertFloppy (std::shared_ptr<M35_Floppy> floppy)
{
    if (this->floppy)
        eject();

    this->floppy = floppy;
    state = floppy->isProtected()? STATE_CODES::READY_WP : STATE_CODES::READY;
    error = ERROR_CODES::NONE;
    this->floppy->drive = this;

    LOG << "[M35FD] Disk inserted!";
}

void M35FD::eject()
{
    if (this->floppy) {
        this->floppy->drive = NULL;
        this->floppy = std::shared_ptr<M35_Floppy>(); // like = NULL
    }

    LOG << "[M35FD] Disk ejected!";

    if (state == STATE_CODES::BUSY) // Wops!
        error = ERROR_CODES::EJECT;
    else
        error = ERROR_CODES::NONE;

    state = STATE_CODES::NO_MEDIA;
}

// M35_Floppy class ***********************************************************

size_t data_pos (size_t sector, size_t index)
{
    return 4 + sector*SECTOR_SIZE + index*2;
    // We wrok with Words, but file post is in bytes!!
}

M35_Floppy::M35_Floppy(const std::string filename, uint8_t tracks, bool wp) :
                        tracks(tracks), bad_sectors(NULL), wp_flag(wp),
                        last_sector(0), cursor(0), drive(NULL)
{
    assert(tracks == 80 || tracks == 40);

    // Qucik and dirty way to see if file exists
    bool create_header = false;
    std::ifstream f(filename);
    if (!f.good()) {
        create_header = true;
        LOG << "[M35FD] Datafile not exists";
    }
    f.close();

    bad_sectors = new uint8_t[(tracks * SECTORS_PER_TRACK) >> 3];

    if (create_header) {
        datafile.open(filename, std::ios::in | std::ios::out |
                                std::ios::binary | std::ios::trunc);
        datafile.write(&FileHeader[0], 1);
        datafile.write(&FileHeader[1], 1);
        datafile.seekg(1, std::fstream::cur);
        datafile.write((const char*)(&tracks), 1);
    } else {
        datafile.open(filename, std::ios::in | std::ios::out |
                                std::ios::binary);
    }
}

M35_Floppy::~M35_Floppy()
{
    if (datafile.is_open()) {
        datafile.close();
        LOG << "[M35FD] Datafile closed";
    }

    delete[] bad_sectors;
}

bool M35_Floppy::isSectorBad (uint16_t sector) const
{
    return false; // TODO
}

void M35_Floppy::setSectorBad (uint16_t sector, bool state)
{
    return; // TODO
}

ERROR_CODES M35_Floppy::write (uint16_t sector, uint16_t addr,
                                unsigned& cycles)
{
    cycles = setTrack(sector / SECTORS_PER_TRACK);
    cycles += WRITE_CYCLES_PER_SECTOR;

    cursor = addr;
    count = 0;
    reading = false;

    last_sector = sector;
    return ERROR_CODES::NONE;
}

ERROR_CODES M35_Floppy::read (uint16_t sector, uint16_t addr,
                                unsigned& cycles)
{
    cycles = setTrack(sector / SECTORS_PER_TRACK);
    cycles += READ_CYCLES_PER_SECTOR;

    cursor = addr;
    count = 0;
    reading = false;

    last_sector = sector;
    return ERROR_CODES::NONE;
}

void M35_Floppy::tick()
{
    char buff[2];
    if (count < SECTOR_SIZE) {
        datafile.seekp(data_pos (last_sector, count), std::ios::beg);
        // TODO Force endianess
        if (reading) {
            datafile.read (buff, 2);
            drive->cpu->getMem()[cursor + count++] = *((uint16_t*)buff);
        } else {
            buff[0] = drive->cpu->getMem()[cursor + count] >> 8;
            buff[1] = 0xFF & drive->cpu->getMem()[cursor + count++];
            datafile.write (buff, 2);
        }
    }
}

} // END OF NAMESPACE m35fd

} // END OF NAMESPACE cpu

<commit_msg>Changed a log message<commit_after>#include <devices/m35fd.hpp>

#include <cassert>

namespace cpu {

namespace m35fd {

// M35FD class ****************************************************************

M35FD::M35FD() : state(STATE_CODES::NO_MEDIA), error(ERROR_CODES::NONE),
                 busy_cycles(0)
{ }

M35FD::~M35FD()
{
    if (floppy)
        eject();
}

void M35FD::attachTo (DCPU* cpu, size_t index)
{
    this->IHardware::attachTo(cpu, index);
    if (floppy) {
        state = floppy->isProtected() ?
                    STATE_CODES::READY_WP : STATE_CODES::READY;
    } else {
        state = STATE_CODES::NO_MEDIA;
    }

    error = ERROR_CODES::NONE;
}

bool M35FD::checkInterrupt (uint16_t& msg)
{
    if (this->msg != 0 && true) {
        msg = this->msg;
        return true;
    }
    return false;
}

unsigned M35FD::handleInterrupt()
{
    if (cpu == NULL)
        return 0;

    switch (static_cast<COMMANDS>(cpu->getA())) {
    case COMMANDS::POLL :
        cpu->setB(static_cast<uint16_t>(state));
        cpu->setC(static_cast<uint16_t>(error));
        LOG_DEBUG << "[M35FD] polling E:" << static_cast<uint16_t>(state) <<
                                    " R:" << static_cast<uint16_t>(error);
        break;

    case COMMANDS::SET_INTERRUPT :
        msg = cpu->getX();
        break;

    case COMMANDS::READ_SECTOR :
        if (state == STATE_CODES::READY || state == STATE_CODES::READY_WP) {
            if (! floppy) { // This not should happen never, but...
                state = STATE_CODES::NO_MEDIA;
                error = ERROR_CODES::BROKEN;
                cpu->setB(0);
                LOG_ERROR << "[M35FD] Something weird happen trying to Read";
                break;
            }
            floppy->read(cpu->getX(), cpu->getY(), busy_cycles);
            state = STATE_CODES::BUSY;
            error = ERROR_CODES::NONE;
            cpu->setB(1);

        } else {
            if (state == STATE_CODES::NO_MEDIA) {
                error = ERROR_CODES::NO_MEDIA;
            } else if (state == STATE_CODES::BUSY) {
                error = ERROR_CODES::BUSY;
            }

            LOG_DEBUG << "[M35FD] Reading set to Error: "
                        << static_cast<int>(error);
            cpu->setB(0);
        }
        break;

    case COMMANDS::WRITE_SECTOR :
        if (state == STATE_CODES::READY) {
            if (! floppy) { // This not should happen never, but...
                state = STATE_CODES::NO_MEDIA;
                error = ERROR_CODES::BROKEN;
                cpu->setB(0);
                LOG_ERROR << "[M35FD] Something weird happen trying to Write";
                break;
            }
            floppy->write(cpu->getX(), cpu->getY(), busy_cycles);
            state = STATE_CODES::BUSY;
            error = ERROR_CODES::NONE;
            cpu->setB(1);
        } else {
            if (state == STATE_CODES::NO_MEDIA) {
                error = ERROR_CODES::NO_MEDIA;
            } else if (state == STATE_CODES::READY_WP) {
                error = ERROR_CODES::PROTECTED;
            } else if (state == STATE_CODES::BUSY) {
                error = ERROR_CODES::BUSY;
            }

            LOG_DEBUG << "[M35FD] Writing set to Error: "
                        << static_cast<int>(error);
            cpu->setB(0);
        }
        break;

    default:
        break;
    }

    return 0;
}

void M35FD::tick()
{
    if (busy_cycles > 0) {
        busy_cycles--;
        // Read/write 1 word each 3 cycles. A bit more faster that the suposed
        // specs speeds, but more easy to do
        if (floppy && busy_cycles % 3)
            floppy->tick();

    } else if (floppy) {
        state = floppy->isProtected() ?
            STATE_CODES::READY_WP : STATE_CODES::READY;
    }
}

void M35FD::insertFloppy (std::shared_ptr<M35_Floppy> floppy)
{
    if (this->floppy)
        eject();

    this->floppy = floppy;
    state = floppy->isProtected()? STATE_CODES::READY_WP : STATE_CODES::READY;
    error = ERROR_CODES::NONE;
    this->floppy->drive = this;

    LOG << "[M35FD] Disk inserted!";
}

void M35FD::eject()
{
    if (this->floppy) {
        this->floppy->drive = NULL;
        this->floppy = std::shared_ptr<M35_Floppy>(); // like = NULL
    }

    LOG << "[M35FD] Disk ejected!";

    if (state == STATE_CODES::BUSY) // Wops!
        error = ERROR_CODES::EJECT;
    else
        error = ERROR_CODES::NONE;

    state = STATE_CODES::NO_MEDIA;
}

// M35_Floppy class ***********************************************************

size_t data_pos (size_t sector, size_t index)
{
    return 4 + sector*SECTOR_SIZE + index*2;
    // We wrok with Words, but file post is in bytes!!
}

M35_Floppy::M35_Floppy(const std::string filename, uint8_t tracks, bool wp) :
                        tracks(tracks), bad_sectors(NULL), wp_flag(wp),
                        last_sector(0), cursor(0), drive(NULL)
{
    assert(tracks == 80 || tracks == 40);

    // Qucik and dirty way to see if file exists
    bool create_header = false;
    std::ifstream f(filename);
    if (!f.good()) {
        create_header = true;
        LOG << "[M35FD] Disk datafile not exists. Creating it.";
    }
    f.close();

    bad_sectors = new uint8_t[(tracks * SECTORS_PER_TRACK) >> 3];

    if (create_header) {
        datafile.open(filename, std::ios::in | std::ios::out |
                                std::ios::binary | std::ios::trunc);
        datafile.write(&FileHeader[0], 1);
        datafile.write(&FileHeader[1], 1);
        datafile.seekg(1, std::fstream::cur);
        datafile.write((const char*)(&tracks), 1);
    } else {
        datafile.open(filename, std::ios::in | std::ios::out |
                                std::ios::binary);
    }
}

M35_Floppy::~M35_Floppy()
{
    if (datafile.is_open()) {
        datafile.close();
        LOG << "[M35FD] Datafile closed";
    }

    delete[] bad_sectors;
}

bool M35_Floppy::isSectorBad (uint16_t sector) const
{
    return false; // TODO
}

void M35_Floppy::setSectorBad (uint16_t sector, bool state)
{
    return; // TODO
}

ERROR_CODES M35_Floppy::write (uint16_t sector, uint16_t addr,
                                unsigned& cycles)
{
    cycles = setTrack(sector / SECTORS_PER_TRACK);
    cycles += WRITE_CYCLES_PER_SECTOR;

    cursor = addr;
    count = 0;
    reading = false;

    last_sector = sector;
    return ERROR_CODES::NONE;
}

ERROR_CODES M35_Floppy::read (uint16_t sector, uint16_t addr,
                                unsigned& cycles)
{
    cycles = setTrack(sector / SECTORS_PER_TRACK);
    cycles += READ_CYCLES_PER_SECTOR;

    cursor = addr;
    count = 0;
    reading = false;

    last_sector = sector;
    return ERROR_CODES::NONE;
}

void M35_Floppy::tick()
{
    char buff[2];
    if (count < SECTOR_SIZE) {
        datafile.seekp(data_pos (last_sector, count), std::ios::beg);
        // TODO Force endianess
        if (reading) {
            datafile.read (buff, 2);
            drive->cpu->getMem()[cursor + count++] = *((uint16_t*)buff);
        } else {
            buff[0] = drive->cpu->getMem()[cursor + count] >> 8;
            buff[1] = 0xFF & drive->cpu->getMem()[cursor + count++];
            datafile.write (buff, 2);
        }
    }
}

} // END OF NAMESPACE m35fd

} // END OF NAMESPACE cpu

<|endoftext|>


<commit_before><commit_msg>Update `yli::data::Datatype`.<commit_after><|endoftext|>


<commit_before><commit_msg>Added MORPHTARGETS_TEXTURE define<commit_after><|endoftext|>


<commit_before>#ifndef _IZENELIB_AM_SUCCINCT_HP_ARRAY_HPP
#define _IZENELIB_AM_SUCCINCT_HP_ARRAY_HPP

#include <am/succinct/constants.hpp>

#include <vector>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <sys/mman.h>

NS_IZENELIB_AM_BEGIN

namespace succinct
{

#define HUGE_PROTECTION (PROT_READ | PROT_WRITE)
#define HUGE_FLAGS (MAP_HUGETLB | MAP_ANONYMOUS | MAP_PRIVATE)

template <class T>
class HPArray
{
public:
    typedef T value_type;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef value_type* iterator;
    typedef const value_type* const_iterator;
    typedef ptrdiff_t difference_type;
    typedef size_t size_type;

    HPArray() : use_hp_(true), size_(), capacity_(), data_() {}

    HPArray(size_type size)
    {
        resize(size);
    }

    HPArray(const std::vector<value_type>& vec)
    {
        assign(vec);
    }

    ~HPArray()
    {
        clear();
    }

    size_type capacity()
    {
        return capacity_;
    }

    size_type size()
    {
        return size_;
    }

    value_type* data()
    {
        return data_;
    }
    const value_type* data() const
    {
        return data_;
    }

    reference operator[](size_type pos)
    {
        return data_[pos];
    }
    const_reference operator[](size_type pos) const
    {
        return data_[pos];
    }

    void clear()
    {
        if (data_ > 0)
        {
            size_ = 0;
            capacity_ = 0;
            if (use_hp_)
            {
                munmap(data_, sizeof(value_type) * capacity_);
            }
            else
            {
                free(data_);
            }
            data_ = 0;
        }
    }

    void resize(size_type size)
    {
        if (size > capacity_)
        {
            bool new_use_hp = true;
            size_type new_capacity = std::max(size, capacity_ * 2);
            value_type* new_data = (value_type*)mmap(NULL, sizeof(value_type) * new_capacity, HUGE_PROTECTION, HUGE_FLAGS, 0, 0);
            if (new_data == MAP_FAILED)
            {
                std::cout << "mmap was not successful" << std::endl;
                new_use_hp = false;
                new_data = (value_type*)malloc(sizeof(value_type) * new_capacity);
            }
            if (data_)
            {
                memcpy(new_data, data_, sizeof(value_type) * size_);
                if (use_hp_)
                {
                    munmap(data_, sizeof(value_type) * capacity_);
                }
                else
                {
                    free(data_);
                }
            }
            use_hp_ = new_use_hp;
            capacity_ = new_capacity;
            data_ = new_data;
        }
        size_ = size;
    }

    void assign(const std::vector<value_type>& vec)
    {
        if (vec.size() > capacity_)
        {
            bool new_use_hp = true;
            if (data_)
            {
                if (use_hp_)
                {
                    munmap(data_, sizeof(value_type) * capacity_);
                }
                else
                {
                    free(data_);
                }
            }
            capacity_ = std::max(vec.size(), capacity_ * 2);
            data_ = (value_type*)mmap(NULL, sizeof(value_type) * capacity_, HUGE_PROTECTION, HUGE_FLAGS, 0, 0);
            if (data_ == MAP_FAILED)
            {
                std::cout << "mmap was not successful" << std::endl;
                new_use_hp = false;
                data_ = (value_type*)malloc(sizeof(value_type) * capacity_);
            }
            use_hp_ = new_use_hp;
        }
        size_ = vec.size();
        memcpy(data_, &vec[0], sizeof(value_type) * size_);
    }

    void swap(HPArray& other)
    {
        std::swap(use_hp_, other.use_hp_);
        std::swap(size_, other. size_);
        std::swap(capacity_, other.capacity_);
        std::swap(data_, other.data_);
    }

    void save(std::ostream& os) const
    {
        os.write((const char*)&size_, sizeof(size_));
        os.write((const char*)data_, sizeof(value_type) * size_);
    }
    void load(std::istream& is)
    {
        is.read((char*)&size_, sizeof(size_));
        resize(size_);
        is.read((char*)data_, sizeof(value_type) * size_);
    }

private:
    bool use_hp_;
    size_type size_;
    size_type capacity_;
    value_type* data_;
};

}

NS_IZENELIB_AM_END

#endif
<commit_msg>tiny fix<commit_after>#ifndef _IZENELIB_AM_SUCCINCT_HP_ARRAY_HPP
#define _IZENELIB_AM_SUCCINCT_HP_ARRAY_HPP

#include <am/succinct/constants.hpp>

#include <vector>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <sys/mman.h>

NS_IZENELIB_AM_BEGIN

namespace succinct
{

#define HUGE_PROTECTION (PROT_READ | PROT_WRITE)
#define HUGE_FLAGS (MAP_HUGETLB | MAP_ANONYMOUS | MAP_PRIVATE)

template <class T>
class HPArray
{
public:
    typedef T value_type;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef value_type* iterator;
    typedef const value_type* const_iterator;
    typedef ptrdiff_t difference_type;
    typedef size_t size_type;

    HPArray() : use_hp_(true), size_(), capacity_(), data_() {}

    HPArray(size_type size)
    {
        resize(size);
    }

    HPArray(const std::vector<value_type>& vec)
    {
        assign(vec);
    }

    ~HPArray()
    {
        clear();
    }

    size_type capacity()
    {
        return capacity_;
    }

    size_type size()
    {
        return size_;
    }

    value_type* data()
    {
        return data_;
    }
    const value_type* data() const
    {
        return data_;
    }

    reference operator[](size_type pos)
    {
        return data_[pos];
    }
    const_reference operator[](size_type pos) const
    {
        return data_[pos];
    }

    void clear()
    {
        if (data_)
        {
            if (use_hp_)
            {
                munmap(data_, sizeof(value_type) * capacity_);
            }
            else
            {
                free(data_);
            }
            size_ = 0;
            capacity_ = 0;
            data_ = 0;
        }
    }

    void resize(size_type size)
    {
        if (size > capacity_)
        {
            bool new_use_hp = true;
            size_type new_capacity = std::max(size, capacity_ * 2);
            value_type* new_data = (value_type*)mmap(NULL, sizeof(value_type) * new_capacity, HUGE_PROTECTION, HUGE_FLAGS, 0, 0);
            if (new_data == MAP_FAILED)
            {
                std::cout << "mmap was not successful" << std::endl;
                new_use_hp = false;
                new_data = (value_type*)malloc(sizeof(value_type) * new_capacity);
            }
            if (data_)
            {
                memcpy(new_data, data_, sizeof(value_type) * size_);
                if (use_hp_)
                {
                    munmap(data_, sizeof(value_type) * capacity_);
                }
                else
                {
                    free(data_);
                }
            }
            use_hp_ = new_use_hp;
            capacity_ = new_capacity;
            data_ = new_data;
        }
        size_ = size;
    }

    void assign(const std::vector<value_type>& vec)
    {
        if (vec.size() > capacity_)
        {
            bool new_use_hp = true;
            if (data_)
            {
                if (use_hp_)
                {
                    munmap(data_, sizeof(value_type) * capacity_);
                }
                else
                {
                    free(data_);
                }
            }
            capacity_ = std::max(vec.size(), capacity_ * 2);
            data_ = (value_type*)mmap(NULL, sizeof(value_type) * capacity_, HUGE_PROTECTION, HUGE_FLAGS, 0, 0);
            if (data_ == MAP_FAILED)
            {
                std::cout << "mmap was not successful" << std::endl;
                new_use_hp = false;
                data_ = (value_type*)malloc(sizeof(value_type) * capacity_);
            }
            use_hp_ = new_use_hp;
        }
        size_ = vec.size();
        memcpy(data_, &vec[0], sizeof(value_type) * size_);
    }

    void swap(HPArray& other)
    {
        std::swap(use_hp_, other.use_hp_);
        std::swap(size_, other. size_);
        std::swap(capacity_, other.capacity_);
        std::swap(data_, other.data_);
    }

    void save(std::ostream& os) const
    {
        os.write((const char*)&size_, sizeof(size_));
        os.write((const char*)data_, sizeof(value_type) * size_);
    }
    void load(std::istream& is)
    {
        is.read((char*)&size_, sizeof(size_));
        resize(size_);
        is.read((char*)data_, sizeof(value_type) * size_);
    }

private:
    bool use_hp_;
    size_type size_;
    size_type capacity_;
    value_type* data_;
};

}

NS_IZENELIB_AM_END

#endif
<|endoftext|>


<commit_before>#pragma once

#include <functional>
#include <string>

#ifdef __has_include
    #if __has_include(<boost/container/small_vector.hpp>)
        #define BLACKHOLE_HAVE_SMALL_VECTOR
    #endif
#endif

#ifdef BLACKHOLE_HAVE_SMALL_VECTOR
    #include <boost/container/small_vector.hpp>
#else
    #include <vector>
#endif

#include "blackhole/attribute.hpp"

namespace blackhole {

// TODO: Try to encapsulate.
#ifdef BLACKHOLE_HAVE_SMALL_VECTOR
typedef boost::container::small_vector<std::pair<string_view, attribute::value_t>, 16> attributes_t;
typedef boost::container::small_vector<std::pair<std::string, attribute::owned_t>, 16> attributes_w_t;
typedef boost::container::small_vector<std::reference_wrapper<const attributes_t>, 16> range_t;
#else
typedef std::vector<std::pair<string_view, attribute::value_t>> attributes_t;
typedef std::vector<std::pair<std::string, attribute::owned_t>> attributes_w_t;
// TODO: I can use stack allocator with fallback for portability.
typedef std::vector<std::reference_wrapper<const attributes_t>> range_t;
#endif

}  // namespace blackhole
<commit_msg>chore(attributes): add planning note<commit_after>#pragma once

#include <functional>
#include <string>

#ifdef __has_include
    #if __has_include(<boost/container/small_vector.hpp>)
        #define BLACKHOLE_HAVE_SMALL_VECTOR
    #endif
#endif

#ifdef BLACKHOLE_HAVE_SMALL_VECTOR
    #include <boost/container/small_vector.hpp>
#else
    #include <vector>
#endif

#include "blackhole/attribute.hpp"

namespace blackhole {

// TODO: Try to encapsulate.
#ifdef BLACKHOLE_HAVE_SMALL_VECTOR
// TODO: Use initializer_list instead?
typedef boost::container::small_vector<std::pair<string_view, attribute::value_t>, 16> attributes_t;
typedef boost::container::small_vector<std::pair<std::string, attribute::owned_t>, 16> attributes_w_t;
typedef boost::container::small_vector<std::reference_wrapper<const attributes_t>, 16> range_t;
#else
typedef std::vector<std::pair<string_view, attribute::value_t>> attributes_t;
typedef std::vector<std::pair<std::string, attribute::owned_t>> attributes_w_t;
// TODO: I can use stack allocator with fallback for portability.
typedef std::vector<std::reference_wrapper<const attributes_t>> range_t;
#endif

}  // namespace blackhole
<|endoftext|>


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

#ifndef ESTD_CONTIGUOUSRANGE_HPP_
#define ESTD_CONTIGUOUSRANGE_HPP_

#include <iterator>

namespace estd
{

/**
 * \brief ContiguousRange template class is a pair of iterators to contiguous sequence of elements in memory
 *
 * \tparam T is the type of data in the range
 */

template<typename T>
class ContiguousRange
{
public:

	/// value_type type
	using value_type = T;

	/// pointer type
	using pointer = value_type*;

	/// const_pointer type
	using const_pointer = const value_type*;

	/// reference type
	using reference = value_type&;

	/// const_reference type
	using const_reference = const value_type&;

	/// iterator type
	using iterator = value_type*;

	/// const_iterator type
	using const_iterator = const value_type*;

	/// size_type type
	using size_type = std::size_t;

	/// difference_type type
	using difference_type = std::ptrdiff_t;

	/// reverse_iterator type
	using reverse_iterator = std::reverse_iterator<iterator>;

	/// const_reverse_iterator type
	using const_reverse_iterator = std::reverse_iterator<const_iterator>;

	/**
	 * \brief ContiguousRange's constructor.
	 *
	 * \param [in] beginn is an iterator to first element in the range
	 * \param [in] endd is an iterator to "one past the last" element in the range
	 */

	constexpr ContiguousRange(const iterator beginn, const iterator endd) noexcept :
			begin_{beginn},
			end_{endd}
	{

	}

	/**
	 * \brief Empty ContiguousRange's constructor.
	 */

	constexpr explicit ContiguousRange() noexcept :
			ContiguousRange{nullptr, nullptr}
	{

	}

	/**
	 * \brief ContiguousRange's constructor using C-style array.
	 *
	 * \tparam N is the number of elements in the array
	 *
	 * \param [in] array is the array used to initialize the range
	 */

	template<size_t N>
	constexpr explicit ContiguousRange(T (& array)[N]) noexcept :
			ContiguousRange{array, array + N}
	{

	}

	/**
	 * \brief ContiguousRange's constructor using single value
	 *
	 * \param [in] value is a reference to variable used to initialize the range
	 */

	constexpr explicit ContiguousRange(T& value) noexcept :
			ContiguousRange{&value, &value + 1}
	{

	}

	/**
	 * \return iterator to first element in the range
	 */

	constexpr iterator begin() const noexcept
	{
		return begin_;
	}

	/**
	 * \return iterator to "one past the last" element in the range
	 */

	constexpr iterator end() const noexcept
	{
		return end_;
	}

	/**
	 * \return number of elements in the range
	 */

	constexpr size_type size() const noexcept
	{
		return end_ - begin_;
	}

	/**
	 * \param [in] i is the index of element that will be accessed
	 *
	 * \return reference to element at given index
	 */

	reference operator[](const size_type i) const noexcept
	{
		return begin_[i];
	}

private:

	/// iterator to first element in the range
	iterator begin_;

	/// iterator to "one past the last" element in the range
	iterator end_;
};

}	// namespace estd

#endif	// ESTD_CONTIGUOUSRANGE_HPP_
<commit_msg>Add support for std::array to ContiguousRange<commit_after>/**
 * \file
 * \brief ContiguousRange template class header.
 *
 * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef ESTD_CONTIGUOUSRANGE_HPP_
#define ESTD_CONTIGUOUSRANGE_HPP_

#include <array>

namespace estd
{

/**
 * \brief ContiguousRange template class is a pair of iterators to contiguous sequence of elements in memory
 *
 * \tparam T is the type of data in the range
 */

template<typename T>
class ContiguousRange
{
public:

	/// value_type type
	using value_type = T;

	/// pointer type
	using pointer = value_type*;

	/// const_pointer type
	using const_pointer = const value_type*;

	/// reference type
	using reference = value_type&;

	/// const_reference type
	using const_reference = const value_type&;

	/// iterator type
	using iterator = value_type*;

	/// const_iterator type
	using const_iterator = const value_type*;

	/// size_type type
	using size_type = std::size_t;

	/// difference_type type
	using difference_type = std::ptrdiff_t;

	/// reverse_iterator type
	using reverse_iterator = std::reverse_iterator<iterator>;

	/// const_reverse_iterator type
	using const_reverse_iterator = std::reverse_iterator<const_iterator>;

	/**
	 * \brief ContiguousRange's constructor.
	 *
	 * \param [in] beginn is an iterator to first element in the range
	 * \param [in] endd is an iterator to "one past the last" element in the range
	 */

	constexpr ContiguousRange(const iterator beginn, const iterator endd) noexcept :
			begin_{beginn},
			end_{endd}
	{

	}

	/**
	 * \brief Empty ContiguousRange's constructor.
	 */

	constexpr explicit ContiguousRange() noexcept :
			ContiguousRange{nullptr, nullptr}
	{

	}

	/**
	 * \brief ContiguousRange's constructor using C-style array.
	 *
	 * \tparam N is the number of elements in the array
	 *
	 * \param [in] array is the array used to initialize the range
	 */

	template<size_t N>
	constexpr explicit ContiguousRange(T (& array)[N]) noexcept :
			ContiguousRange{array, array + N}
	{

	}

	/**
	 * \brief ContiguousRange's constructor using std::array.
	 *
	 * \tparam N is the number of elements in the array
	 *
	 * \param [in] array is the array used to initialize the range
	 */

	template<size_t N>
	constexpr explicit ContiguousRange(std::array<T, N>& array) noexcept :
			ContiguousRange{array.begin(), array.end()}
	{

	}

	/**
	 * \brief ContiguousRange's constructor using const std::array.
	 *
	 * \tparam N is the number of elements in the array
	 *
	 * \param [in] array is the const array used to initialize the range
	 */

	template<size_t N>
	constexpr explicit ContiguousRange(const std::array<typename std::remove_const<T>::type, N>& array) noexcept :
			ContiguousRange{array.begin(), array.end()}
	{

	}

	/**
	 * \brief ContiguousRange's constructor using single value
	 *
	 * \param [in] value is a reference to variable used to initialize the range
	 */

	constexpr explicit ContiguousRange(T& value) noexcept :
			ContiguousRange{&value, &value + 1}
	{

	}

	/**
	 * \return iterator to first element in the range
	 */

	constexpr iterator begin() const noexcept
	{
		return begin_;
	}

	/**
	 * \return iterator to "one past the last" element in the range
	 */

	constexpr iterator end() const noexcept
	{
		return end_;
	}

	/**
	 * \return number of elements in the range
	 */

	constexpr size_type size() const noexcept
	{
		return end_ - begin_;
	}

	/**
	 * \param [in] i is the index of element that will be accessed
	 *
	 * \return reference to element at given index
	 */

	reference operator[](const size_type i) const noexcept
	{
		return begin_[i];
	}

private:

	/// iterator to first element in the range
	iterator begin_;

	/// iterator to "one past the last" element in the range
	iterator end_;
};

}	// namespace estd

#endif	// ESTD_CONTIGUOUSRANGE_HPP_
<|endoftext|>


<commit_before>#pragma once

#include <cstddef> // size_t, uint8_t
#include <functional> // hash

namespace nlohmann
{
namespace detail
{

// boost::hash_combine
std::size_t combine(std::size_t seed, std::size_t h) noexcept
{
    seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
    return seed;
}

/*!
@brief hash a JSON value

The hash function tries to rely on std::hash where possible. Furthermore, the
type of the JSON value is taken into account to have different hash values for
null, 0, 0U, and false, etc.

@tparam BasicJsonType basic_json specialization
@param j JSON value to hash
@return hash value of j
*/
template<typename BasicJsonType>
std::size_t hash(const BasicJsonType& j)
{
    using string_t = typename BasicJsonType::string_t;
    using number_integer_t = typename BasicJsonType::number_integer_t;
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
    using number_float_t = typename BasicJsonType::number_float_t;

    const auto type = static_cast<std::size_t>(j.type());
    switch (j.type())
    {
        case BasicJsonType::value_t::null:
        case BasicJsonType::value_t::discarded:
        {
            return combine(type, 0);
        }

        case BasicJsonType::value_t::object:
        {
            auto seed = combine(type, j.size());
            for (const auto& element : j.items())
            {
                const auto h = std::hash<string_t> {}(element.key());
                seed = combine(seed, h);
                seed = combine(seed, hash(element.value()));
            }
            return seed;
        }

        case BasicJsonType::value_t::array:
        {
            auto seed = combine(type, j.size());
            for (const auto& element : j)
            {
                seed = combine(seed, hash(element));
            }
            return seed;
        }

        case BasicJsonType::value_t::string:
        {
            const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
            return combine(type, h);
        }

        case BasicJsonType::value_t::boolean:
        {
            const auto h = std::hash<bool> {}(j.template get<bool>());
            return combine(type, h);
        }

        case BasicJsonType::value_t::number_integer:
        {
            const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
            return combine(type, h);
        }

        case nlohmann::detail::value_t::number_unsigned:
        {
            const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
            return combine(type, h);
        }

        case nlohmann::detail::value_t::number_float:
        {
            const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
            return combine(type, h);
        }

        case nlohmann::detail::value_t::binary:
        {
            auto seed = combine(type, j.get_binary().size());
            const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
            seed = combine(seed, h);
            seed = combine(seed, j.get_binary().subtype());
            for (const auto byte : j.get_binary())
            {
                seed = combine(seed, std::hash<std::uint8_t> {}(byte));
            }
            return seed;
        }

        default: // LCOV_EXCL_LINE
            JSON_ASSERT(false); // LCOV_EXCL_LINE
    }
}

}  // namespace detail
}  // namespace nlohmann
<commit_msg>add inline specifier for detail::combine<commit_after>#pragma once

#include <cstddef> // size_t, uint8_t
#include <functional> // hash

namespace nlohmann
{
namespace detail
{

// boost::hash_combine
inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
{
    seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
    return seed;
}

/*!
@brief hash a JSON value

The hash function tries to rely on std::hash where possible. Furthermore, the
type of the JSON value is taken into account to have different hash values for
null, 0, 0U, and false, etc.

@tparam BasicJsonType basic_json specialization
@param j JSON value to hash
@return hash value of j
*/
template<typename BasicJsonType>
std::size_t hash(const BasicJsonType& j)
{
    using string_t = typename BasicJsonType::string_t;
    using number_integer_t = typename BasicJsonType::number_integer_t;
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
    using number_float_t = typename BasicJsonType::number_float_t;

    const auto type = static_cast<std::size_t>(j.type());
    switch (j.type())
    {
        case BasicJsonType::value_t::null:
        case BasicJsonType::value_t::discarded:
        {
            return combine(type, 0);
        }

        case BasicJsonType::value_t::object:
        {
            auto seed = combine(type, j.size());
            for (const auto& element : j.items())
            {
                const auto h = std::hash<string_t> {}(element.key());
                seed = combine(seed, h);
                seed = combine(seed, hash(element.value()));
            }
            return seed;
        }

        case BasicJsonType::value_t::array:
        {
            auto seed = combine(type, j.size());
            for (const auto& element : j)
            {
                seed = combine(seed, hash(element));
            }
            return seed;
        }

        case BasicJsonType::value_t::string:
        {
            const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
            return combine(type, h);
        }

        case BasicJsonType::value_t::boolean:
        {
            const auto h = std::hash<bool> {}(j.template get<bool>());
            return combine(type, h);
        }

        case BasicJsonType::value_t::number_integer:
        {
            const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
            return combine(type, h);
        }

        case nlohmann::detail::value_t::number_unsigned:
        {
            const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
            return combine(type, h);
        }

        case nlohmann::detail::value_t::number_float:
        {
            const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
            return combine(type, h);
        }

        case nlohmann::detail::value_t::binary:
        {
            auto seed = combine(type, j.get_binary().size());
            const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
            seed = combine(seed, h);
            seed = combine(seed, j.get_binary().subtype());
            for (const auto byte : j.get_binary())
            {
                seed = combine(seed, std::hash<std::uint8_t> {}(byte));
            }
            return seed;
        }

        default: // LCOV_EXCL_LINE
            JSON_ASSERT(false); // LCOV_EXCL_LINE
    }
}

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


<commit_before>// Nonius - C++ benchmarking tool
//
// Written in 2014 by Martinho Fernandes <martinho.fernandes@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all copyright and related
// and neighboring rights to this software to the public domain worldwide. This software is
// distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>

// Exception to be thrown when a process takes too long to run

#ifndef NONIUS_TIMEOUT_ERROR_HPP
#define NONIUS_TIMEOUT_ERROR_HPP

#include <nonius/timeout_error.h++>
#include <nonius/detail/noexcept.h++>

#include <sstream>
#include <string>
#include <exception>

namespace nonius {
    struct timeout_error : virtual std::exception {
    public:
        timeout_error(int seed, int iters) {
            std::ostringstream ss;
            ss << "took too long to run; seed: " << seed << ", iters: " << iters;
            message = ss.str();
        }

        char const* what() const NONIUS_NOEXCEPT override {
            return message.c_str();
        }

    private:
        std::string message;
    };
} // namespace nonius

#endif // NONIUS_TIMEOUT_ERROR_HPP
<commit_msg>Makes timeout_error.h++ not include itself<commit_after>// Nonius - C++ benchmarking tool
//
// Written in 2014 by Martinho Fernandes <martinho.fernandes@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all copyright and related
// and neighboring rights to this software to the public domain worldwide. This software is
// distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>

// Exception to be thrown when a process takes too long to run

#ifndef NONIUS_TIMEOUT_ERROR_HPP
#define NONIUS_TIMEOUT_ERROR_HPP

#include <nonius/detail/noexcept.h++>

#include <sstream>
#include <string>
#include <exception>

namespace nonius {
    struct timeout_error : virtual std::exception {
    public:
        timeout_error(int seed, int iters) {
            std::ostringstream ss;
            ss << "took too long to run; seed: " << seed << ", iters: " << iters;
            message = ss.str();
        }

        char const* what() const NONIUS_NOEXCEPT override {
            return message.c_str();
        }

    private:
        std::string message;
    };
} // namespace nonius

#endif // NONIUS_TIMEOUT_ERROR_HPP
<|endoftext|>


<commit_before>#ifndef __PARAMETERS_INTERFACE_H__
#define __PARAMETERS_INTERFACE_H__

#include <unordered_map>
#include <type_traits>
#include <string>
#include <cstdio>

#define METHOD(x)\
	const RequestMethod &request_method() const {\
		static const RequestMethod _request_method = x;\
		return _request_method;\
	}

#define URL(x)\
	const std::string &request_url() const {\
		static const std::string _url = x;\
		return _url;\
	}

#if WIN32
#define POSITIONAL_SPRINTF(buffer, size, format, ...) _sprintf_p(buffer, size, format, __VA_ARGS__)
#else
#define POSITIONAL_SPRINTF(buffer, size, format, ...) sprintf(buffer, format, __VA_ARGS__)
#endif

#define URL_FORMAT(gen)\
private:\
	mutable std::string _url;\
public:\
	const std::string &request_url() const override {\
		if (_url.length() == 0) {\
			std::ostringstream os;\
			os << gen;\
			_url.assign(os.str());\
		}\
		return _url;\
	}

template<typename param_type>
using param_arg_type = typename std::conditional<std::is_arithmetic<param_type>::value, param_type, typename std::add_lvalue_reference<typename std::add_const<param_type>::type>::type>::type;

template<typename param_type>
using param_return_type = typename std::conditional<std::is_arithmetic<param_type>::value, param_type, typename std::add_lvalue_reference<typename std::add_const<param_type>::type>::type>::type;

template<typename ret>
param_return_type<ret> from_string(const std::string &val);

template<>
inline double from_string<double>(const std::string &val) {
	return std::stod(val);
}

template<>
inline bool from_string<bool>(const std::string &val) {
	return val.compare("true") == 0;
}

template<>
inline uint64_t from_string<uint64_t>(const std::string &val) {
	return std::stoull(val);
}

template<>
inline const std::string &from_string<std::string>(const std::string &val) {
	return val;
}

namespace std
{
	inline std::string to_string(bool value) {
		static const std::string t("true"), f("false");
		return value ? t : f;
	}

	inline std::string to_string(const std::string &val)
	{
		return val;
	}
}

#define INIT(param_type_name)\
	using this_ref_type = param_type_name&;\
	virtual ~##param_type_name() {}

#define PARAMETER(param_type, param_name)\
  PARAMETER_ALIAS(param_type, param_name, param_name)

#define PARAMETER_ALIAS(param_type, param_name, param_alias)\
	this_ref_type param_name(param_arg_type<param_type> _##param_name) {\
		parameters[#param_alias] = std::move(std::to_string(_##param_name));\
		return *this;\
	}\
	bool is_set_##param_name() const {\
		return parameters.find(#param_alias) != parameters.end();\
	}\
	param_return_type<param_type> param_name() const {\
		return from_string<param_type>(parameters.at(#param_alias)); \
	}

namespace azha {
	namespace parameters {
		typedef std::unordered_map<std::string, std::string> RequestParams;

		enum class RequestMethod {
			GET,
			POST
		};

		class ITwitterParameters {
		public:
			virtual ~ITwitterParameters() {}
			virtual const RequestMethod &request_method() const = 0;
			virtual const std::string &request_url() const = 0;

			RequestParams parameters;
		};
	}
}

#endif // __PARAMETERS_INTERFACE_H__
<commit_msg>fix desctructor macro error<commit_after>#ifndef __PARAMETERS_INTERFACE_H__
#define __PARAMETERS_INTERFACE_H__

#include <unordered_map>
#include <type_traits>
#include <string>
#include <cstdio>

#define METHOD(x)\
	const RequestMethod &request_method() const {\
		static const RequestMethod _request_method = x;\
		return _request_method;\
	}

#define URL(x)\
	const std::string &request_url() const {\
		static const std::string _url = x;\
		return _url;\
	}

#if WIN32
#define POSITIONAL_SPRINTF(buffer, size, format, ...) _sprintf_p(buffer, size, format, __VA_ARGS__)
#else
#define POSITIONAL_SPRINTF(buffer, size, format, ...) sprintf(buffer, format, __VA_ARGS__)
#endif

#define URL_FORMAT(gen)\
private:\
	mutable std::string _url;\
public:\
	const std::string &request_url() const override {\
		if (_url.length() == 0) {\
			std::ostringstream os;\
			os << gen;\
			_url.assign(os.str());\
		}\
		return _url;\
	}

template<typename param_type>
using param_arg_type = typename std::conditional<std::is_arithmetic<param_type>::value, param_type, typename std::add_lvalue_reference<typename std::add_const<param_type>::type>::type>::type;

template<typename param_type>
using param_return_type = typename std::conditional<std::is_arithmetic<param_type>::value, param_type, typename std::add_lvalue_reference<typename std::add_const<param_type>::type>::type>::type;

template<typename ret>
param_return_type<ret> from_string(const std::string &val);

template<>
inline double from_string<double>(const std::string &val) {
	return std::stod(val);
}

template<>
inline bool from_string<bool>(const std::string &val) {
	return val.compare("true") == 0;
}

template<>
inline uint64_t from_string<uint64_t>(const std::string &val) {
	return std::stoull(val);
}

template<>
inline const std::string &from_string<std::string>(const std::string &val) {
	return val;
}

namespace std
{
	inline std::string to_string(bool value) {
		static const std::string t("true"), f("false");
		return value ? t : f;
	}

	inline std::string to_string(const std::string &val)
	{
		return val;
	}
}

#define INIT(param_type_name)\
	using this_ref_type = param_type_name&;\
	virtual ~param_type_name() {}

#define PARAMETER(param_type, param_name)\
  PARAMETER_ALIAS(param_type, param_name, param_name)

#define PARAMETER_ALIAS(param_type, param_name, param_alias)\
	this_ref_type param_name(param_arg_type<param_type> _##param_name) {\
		parameters[#param_alias] = std::move(std::to_string(_##param_name));\
		return *this;\
	}\
	bool is_set_##param_name() const {\
		return parameters.find(#param_alias) != parameters.end();\
	}\
	param_return_type<param_type> param_name() const {\
		return from_string<param_type>(parameters.at(#param_alias)); \
	}

namespace azha {
	namespace parameters {
		typedef std::unordered_map<std::string, std::string> RequestParams;

		enum class RequestMethod {
			GET,
			POST
		};

		class ITwitterParameters {
		public:
			virtual ~ITwitterParameters() {}
			virtual const RequestMethod &request_method() const = 0;
			virtual const std::string &request_url() const = 0;

			RequestParams parameters;
		};
	}
}

#endif // __PARAMETERS_INTERFACE_H__
<|endoftext|>