<commit_before>//
//  ofxAvAudioPlayer.cpp
//  emptyExample
//
//  Created by Hansi on 13.07.15.
//
// a huge chunk of this file is based on the
// blog entry https://blinkingblip.wordpress.com/2011/10/08/decoding-and-playing-an-audio-stream-using-libavcodec-libavformat-and-libao/
// (had to make some adjustments for changes in ffmpeg
// and libavcodecs examples
// https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/decoding_encoding.c

#include "ofxAvAudioPlayer.h"
#include "ofMain.h"

using namespace std;

#define die(msg) { unloadSound(); cerr << msg << endl; return false; }

ofxAvAudioPlayer::ofxAvAudioPlayer(){
	// default audio settings
	output_channel_layout = av_get_default_channel_layout(2);
	output_sample_rate = 44100;
	output_num_channels = 2;
	output_config_changed = false;
	volume = 1;

	forceNativeFormat = false;

	isLooping = false;
	container = NULL;
	decoded_frame = NULL;
	codec_context = NULL;
	buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
	swr_context = NULL;
	av_register_all();
	av_init_packet(&packet);
	unloadSound();

}

ofxAvAudioPlayer::~ofxAvAudioPlayer(){
	unloadSound();
}

bool ofxAvAudioPlayer::loadSound(string fileName, bool stream){
	unloadSound();

	string fileNameAbs = ofToDataPath(fileName,true);
	const char * input_filename = fileNameAbs.c_str();
	// the first finds the right codec, following  https://blinkingblip.wordpress.com/2011/10/08/decoding-and-playing-an-audio-stream-using-libavcodec-libavformat-and-libao/
	container = 0;
	if (avformat_open_input(&container, input_filename, NULL, NULL) < 0) {
		die("Could not open file");
	}

	if (avformat_find_stream_info(container,NULL) < 0) {
		die("Could not find file info");
	}

	audio_stream_id = -1;

	// To find the first audio stream. This process may not be necessary
	// if you can gurarantee that the container contains only the desired
	// audio stream
	int i;
	for (i = 0; i < container->nb_streams; i++) {
		if (container->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
			audio_stream_id = i;
			break;
		}
	}

	if (audio_stream_id == -1) {
		die("Could not find an audio stream");
	}

	// Find the apropriate codec and open it
	codec_context = container->streams[audio_stream_id]->codec;
	if( forceNativeFormat ){
		output_sample_rate = codec_context->sample_rate;
		output_channel_layout = codec_context->channel_layout;
		if( output_channel_layout == 0 ){
			output_num_channels = codec_context->channels;
			output_channel_layout = av_get_default_channel_layout(output_num_channels);
		}
		else{
			output_num_channels = av_get_channel_layout_nb_channels( output_channel_layout );
		}
		cout << "native audio thing: " << output_sample_rate << "Hz / " << output_num_channels << " channels" << endl;
	}

	AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
	if (avcodec_open2(codec_context, codec,NULL)) {
		die("Could not find open the needed codec");
	}

	// from here on it's mostly following
	// https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/decoding_encoding.c
	//packet.data = inbuf;
	//packet.size = fread(inbuf, 1, AVCODEC_AUDIO_INBUF_SIZE, f);
	av_init_packet(&packet);
	packet.data = NULL;
	packet.size = 0;

	swr_context = NULL;
	isLoaded = true;
	isPlaying = true;

	// we continue here:
	decode_next_frame();
	duration = av_time_to_millis(container->streams[audio_stream_id]->duration);

	return true;
}

bool ofxAvAudioPlayer::setupAudioOut( int numChannels, int sampleRate ){
	if( numChannels != output_num_channels || sampleRate != output_sample_rate ){
		output_channel_layout = av_get_default_channel_layout(numChannels);
		output_sample_rate = sampleRate;
		output_num_channels = numChannels;

		if( swr_context != NULL ){
			output_config_changed = true;
		}
	}

	return true;
}

void ofxAvAudioPlayer::unloadSound(){
	len = 0;
	isLoaded = false;
	isPlaying = false;
	packet_data_size = 0;
	decoded_buffer_pos = 0;
	decoded_buffer_len = 0;
	next_seekTarget = -1;

	av_free_packet(&packet);

	if( decoded_frame ){
		av_frame_unref(decoded_frame);
		av_frame_free(&decoded_frame);
		decoded_frame = NULL;
	}

	if( container ){
		avcodec_close(codec_context);
		avformat_close_input(&container);
		avformat_free_context(container);
		av_free(container);
		container = NULL;
		codec_context = NULL;
	}

	if( swr_context ){
		swr_close(swr_context);
		swr_free(&swr_context);
		swr_context = NULL;
	}
}

int ofxAvAudioPlayer::audioOut(float *output, int bufferSize, int nChannels){
	if( !isLoaded ){ return 0; }

	if( next_seekTarget >= 0 ){
		//av_seek_frame(container,-1,next_seekTarget,AVSEEK_FLAG_ANY);
		avformat_seek_file(container,audio_stream_id,0,next_seekTarget,next_seekTarget,AVSEEK_FLAG_ANY);
		next_seekTarget = -1;
		avcodec_flush_buffers(codec_context);
		decode_next_frame();
	}

	if( !isPlaying ){ return 0; }

	int max_read_packets = 4;
	if( decoded_frame && decoded_frame);
	// number of samples read per channel (up to bufferSize)
	int num_samples_read = 0;

	if( decoded_frame == NULL ){
		decode_next_frame();
	}

	while( decoded_frame != NULL && max_read_packets > 0 ){
		max_read_packets --;

		int missing_samples = bufferSize*nChannels - num_samples_read;
		int available_samples = decoded_buffer_len - decoded_buffer_pos;
		if( missing_samples > 0 && available_samples > 0 ){
			int samples = min( missing_samples, available_samples );

			if( volume != 0 ){
				memcpy(output+num_samples_read, decoded_buffer+decoded_buffer_pos, samples*sizeof(float) );
			}

			if( volume != 1 && volume != 0 ){
				for( int i = 0; i < samples; i++ ){
					output[i+num_samples_read] *= volume;
				}
			}

			decoded_buffer_pos += samples;
			num_samples_read += samples;
		}

		if( num_samples_read >= bufferSize*nChannels ){
			return bufferSize;
		}
		else{
			decode_next_frame();
		}
	}

	return num_samples_read/nChannels;
}

bool ofxAvAudioPlayer::decode_next_frame(){
	av_free_packet(&packet);
	int res = av_read_frame(container, &packet);
	bool didRead = res >= 0;

	if( didRead ){
		int got_frame = 0;
		if (!decoded_frame) {
			if (!(decoded_frame = av_frame_alloc())) {
				fprintf(stderr, "Could not allocate audio frame\n");
				return false;
			}
		}
		else{
			av_frame_unref(decoded_frame);
		}

		len = avcodec_decode_audio4(codec_context, decoded_frame, &got_frame, &packet);
		if (len < 0) {
			// no data
			return false;
		}

		if (got_frame) {

			if( swr_context != NULL && output_config_changed ){
				output_config_changed = false;
				if( swr_context ){
					swr_close(swr_context);
					swr_free(&swr_context);
					swr_context = NULL;
				}
			}

			if( swr_context == NULL ){
				int input_channel_layout = decoded_frame->channel_layout;
				if( input_channel_layout == 0 ){
					input_channel_layout = av_get_default_channel_layout( codec_context->channels );
				}
				swr_context = swr_alloc_set_opts(NULL,
												 output_channel_layout, AV_SAMPLE_FMT_FLT, output_sample_rate,
												 input_channel_layout, (AVSampleFormat)decoded_frame->format, decoded_frame->sample_rate,
												 0, NULL);
				swr_init(swr_context);

				if (!swr_context){
					fprintf(stderr, "Could not allocate resampler context\n");
					return false;
				}
			}

			/* if a frame has been decoded, resample to desired rate */
			int samples_per_channel = AVCODEC_MAX_AUDIO_FRAME_SIZE/output_num_channels;
			//samples_per_channel = 512;
			uint8_t * out = (uint8_t*)decoded_buffer;
			int samples_converted = swr_convert(swr_context,
												(uint8_t**)&out, samples_per_channel,
												(const uint8_t**)decoded_frame->extended_data, decoded_frame->nb_samples);
			decoded_buffer_len = samples_converted*output_num_channels;
			decoded_buffer_pos = 0;
		}

		packet.size -= len;
		packet.data += len;
//		packet->dts =
//		packet->pts = AV_NOPTS_VALUE;

		return true;
	}
	else{
		// no data read...
		packet_data_size = 0;
		decoded_buffer_len = 0;
		decoded_buffer_pos = 0;
		if( isLooping ){
			avformat_seek_file(container,audio_stream_id,0,0,0,AVSEEK_FLAG_ANY);
			avcodec_flush_buffers(codec_context);
			decode_next_frame();
		}
		else{
			isPlaying = false;
		}

		return false;
	}
}

unsigned long long ofxAvAudioPlayer::av_time_to_millis( int64_t av_time ){
	return av_rescale(1000*av_time,(uint64_t)container->streams[audio_stream_id]->time_base.num,container->streams[audio_stream_id]->time_base.den);
	//alternative:
	//return av_time*1000*av_q2d(container->streams[audio_stream_id]->time_base);
}

int64_t ofxAvAudioPlayer::millis_to_av_time( unsigned long long ms ){
	//TODO: fix conversion
/*	int64_t timeBase = (int64_t(codec_context->time_base.num) * AV_TIME_BASE) / int64_t(codec_context->time_base.den);
	int64_t seekTarget = int64_t(ms) / timeBase;*/
	return av_rescale(ms,container->streams[audio_stream_id]->time_base.den,(uint64_t)container->streams[audio_stream_id]->time_base.num)/1000;
}

void ofxAvAudioPlayer::setPositionMS(int ms){
	next_seekTarget = millis_to_av_time(ms);
}

int ofxAvAudioPlayer::getPositionMS(){
	if( !isLoaded ) return 0;
	int64_t ts = packet.pts;
	return av_time_to_millis( ts );
}

float ofxAvAudioPlayer::getPosition(){
	return duration == 0? 0 : (getPositionMS()/(float)duration);
}

void ofxAvAudioPlayer::setPosition(float percent){
	if(duration>0) setPositionMS(percent*duration);
}

void ofxAvAudioPlayer::stop(){
	isPlaying =false;
}

void ofxAvAudioPlayer::play(){
	if( isLoaded ){
		isPlaying = true;
	}
}

void ofxAvAudioPlayer::setLoop(bool loop){
	isLooping = loop;
}

void ofxAvAudioPlayer::setVolume(float vol){
	this->volume = vol;
}

string ofxAvAudioPlayer::getMetadata( string key ){
	if( container != NULL ){
		AVDictionaryEntry * entry = av_dict_get(container->metadata, key.c_str(), NULL, 0);
		if( entry == NULL ) return "";
		else return string(entry->value);
	}
	else{
		return "";
	}
}

map<string,string> ofxAvAudioPlayer::getMetadata(){
	map<string,string> meta;
	AVDictionary * d = container->metadata;
	AVDictionaryEntry *t = NULL;
	while ((t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX))!=0){
		meta[string(t->key)] = string(t->value);
	}

	return meta;
}

<commit_msg>skip packets from the wrong streams. this fixes random crashes when extracting the audio from video files<commit_after>//
//  ofxAvAudioPlayer.cpp
//  emptyExample
//
//  Created by Hansi on 13.07.15.
//
// a huge chunk of this file is based on the
// blog entry https://blinkingblip.wordpress.com/2011/10/08/decoding-and-playing-an-audio-stream-using-libavcodec-libavformat-and-libao/
// (had to make some adjustments for changes in ffmpeg
// and libavcodecs examples
// https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/decoding_encoding.c

#include "ofxAvAudioPlayer.h"
#include "ofMain.h"

using namespace std;

#define die(msg) { unloadSound(); cerr << msg << endl; return false; }

ofxAvAudioPlayer::ofxAvAudioPlayer(){
	// default audio settings
	output_channel_layout = av_get_default_channel_layout(2);
	output_sample_rate = 44100;
	output_num_channels = 2;
	output_config_changed = false;
	volume = 1;

	forceNativeFormat = false;

	isLooping = false;
	container = NULL;
	decoded_frame = NULL;
	codec_context = NULL;
	buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
	swr_context = NULL;
	av_register_all();
	av_init_packet(&packet);
	unloadSound();

}

ofxAvAudioPlayer::~ofxAvAudioPlayer(){
	unloadSound();
}

bool ofxAvAudioPlayer::loadSound(string fileName, bool stream){
	unloadSound();

	string fileNameAbs = ofToDataPath(fileName,true);
	const char * input_filename = fileNameAbs.c_str();
	// the first finds the right codec, following  https://blinkingblip.wordpress.com/2011/10/08/decoding-and-playing-an-audio-stream-using-libavcodec-libavformat-and-libao/
	container = 0;
	if (avformat_open_input(&container, input_filename, NULL, NULL) < 0) {
		die("Could not open file");
	}

	if (avformat_find_stream_info(container,NULL) < 0) {
		die("Could not find file info");
	}

	audio_stream_id = -1;

	// To find the first audio stream. This process may not be necessary
	// if you can gurarantee that the container contains only the desired
	// audio stream
	int i;
	for (i = 0; i < container->nb_streams; i++) {
		if (container->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
			audio_stream_id = i;
			break;
		}
	}

	if (audio_stream_id == -1) {
		die("Could not find an audio stream");
	}

	// Find the apropriate codec and open it
	codec_context = container->streams[audio_stream_id]->codec;
	if( forceNativeFormat ){
		output_sample_rate = codec_context->sample_rate;
		output_channel_layout = codec_context->channel_layout;
		if( output_channel_layout == 0 ){
			output_num_channels = codec_context->channels;
			output_channel_layout = av_get_default_channel_layout(output_num_channels);
		}
		else{
			output_num_channels = av_get_channel_layout_nb_channels( output_channel_layout );
		}
		cout << "native audio thing: " << output_sample_rate << "Hz / " << output_num_channels << " channels" << endl;
	}

	AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
	if (avcodec_open2(codec_context, codec,NULL)) {
		die("Could not find open the needed codec");
	}

	// from here on it's mostly following
	// https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/decoding_encoding.c
	//packet.data = inbuf;
	//packet.size = fread(inbuf, 1, AVCODEC_AUDIO_INBUF_SIZE, f);
	av_init_packet(&packet);
	packet.data = NULL;
	packet.size = 0;

	swr_context = NULL;
	isLoaded = true;
	isPlaying = true;

	// we continue here:
	decode_next_frame();
	duration = av_time_to_millis(container->streams[audio_stream_id]->duration);

	return true;
}

bool ofxAvAudioPlayer::setupAudioOut( int numChannels, int sampleRate ){
	if( numChannels != output_num_channels || sampleRate != output_sample_rate ){
		output_channel_layout = av_get_default_channel_layout(numChannels);
		output_sample_rate = sampleRate;
		output_num_channels = numChannels;

		if( swr_context != NULL ){
			output_config_changed = true;
		}
	}

	return true;
}

void ofxAvAudioPlayer::unloadSound(){
	len = 0;
	isLoaded = false;
	isPlaying = false;
	packet_data_size = 0;
	decoded_buffer_pos = 0;
	decoded_buffer_len = 0;
	next_seekTarget = -1;

	av_free_packet(&packet);

	if( decoded_frame ){
		av_frame_unref(decoded_frame);
		av_frame_free(&decoded_frame);
		decoded_frame = NULL;
	}

	if( container ){
		avcodec_close(codec_context);
		avformat_close_input(&container);
		avformat_free_context(container);
		av_free(container);
		container = NULL;
		codec_context = NULL;
	}

	if( swr_context ){
		swr_close(swr_context);
		swr_free(&swr_context);
		swr_context = NULL;
	}
}

int ofxAvAudioPlayer::audioOut(float *output, int bufferSize, int nChannels){
	if( !isLoaded ){ return 0; }

	if( next_seekTarget >= 0 ){
		//av_seek_frame(container,-1,next_seekTarget,AVSEEK_FLAG_ANY);
		avformat_seek_file(container,audio_stream_id,0,next_seekTarget,next_seekTarget,AVSEEK_FLAG_ANY);
		next_seekTarget = -1;
		avcodec_flush_buffers(codec_context);
		decode_next_frame();
	}

	if( !isPlaying ){ return 0; }

	int max_read_packets = 4;
	if( decoded_frame && decoded_frame);
	// number of samples read per channel (up to bufferSize)
	int num_samples_read = 0;

	if( decoded_frame == NULL ){
		decode_next_frame();
	}

	while( decoded_frame != NULL && max_read_packets > 0 ){
		max_read_packets --;

		int missing_samples = bufferSize*nChannels - num_samples_read;
		int available_samples = decoded_buffer_len - decoded_buffer_pos;
		if( missing_samples > 0 && available_samples > 0 ){
			int samples = min( missing_samples, available_samples );

			if( volume != 0 ){
				memcpy(output+num_samples_read, decoded_buffer+decoded_buffer_pos, samples*sizeof(float) );
			}

			if( volume != 1 && volume != 0 ){
				for( int i = 0; i < samples; i++ ){
					output[i+num_samples_read] *= volume;
				}
			}

			decoded_buffer_pos += samples;
			num_samples_read += samples;
		}

		if( num_samples_read >= bufferSize*nChannels ){
			return bufferSize;
		}
		else{
			decode_next_frame();
		}
	}

	return num_samples_read/nChannels;
}

bool ofxAvAudioPlayer::decode_next_frame(){
	av_free_packet(&packet);
	int res = av_read_frame(container, &packet);
	bool didRead = res >= 0;

	if( didRead ){
		int got_frame = 0;
		if (!decoded_frame) {
			if (!(decoded_frame = av_frame_alloc())) {
				fprintf(stderr, "Could not allocate audio frame\n");
				return false;
			}
		}
		else{
			av_frame_unref(decoded_frame);
		}

		len = avcodec_decode_audio4(codec_context, decoded_frame, &got_frame, &packet);
		if (len < 0) {
			// no data
			return false;
		}

		if( packet.stream_index != audio_stream_id ){
			return false;
		}

		if (got_frame) {

			if( swr_context != NULL && output_config_changed ){
				output_config_changed = false;
				if( swr_context ){
					swr_close(swr_context);
					swr_free(&swr_context);
					swr_context = NULL;
				}
			}

			if( swr_context == NULL ){
				int input_channel_layout = decoded_frame->channel_layout;
				if( input_channel_layout == 0 ){
					input_channel_layout = av_get_default_channel_layout( codec_context->channels );
				}
				swr_context = swr_alloc_set_opts(NULL,
												 output_channel_layout, AV_SAMPLE_FMT_FLT, output_sample_rate,
												 input_channel_layout, (AVSampleFormat)decoded_frame->format, decoded_frame->sample_rate,
												 0, NULL);
				swr_init(swr_context);

				if (!swr_context){
					fprintf(stderr, "Could not allocate resampler context\n");
					return false;
				}
			}

			/* if a frame has been decoded, resample to desired rate */
			int samples_per_channel = AVCODEC_MAX_AUDIO_FRAME_SIZE/output_num_channels;
			//samples_per_channel = 512;
			uint8_t * out = (uint8_t*)decoded_buffer;
			int samples_converted = swr_convert(swr_context,
												(uint8_t**)&out, samples_per_channel,
												(const uint8_t**)decoded_frame->extended_data, decoded_frame->nb_samples);
			decoded_buffer_len = samples_converted*output_num_channels;
			decoded_buffer_pos = 0;
		}

		packet.size -= len;
		packet.data += len;
//		packet->dts =
//		packet->pts = AV_NOPTS_VALUE;

		return true;
	}
	else{
		// no data read...
		packet_data_size = 0;
		decoded_buffer_len = 0;
		decoded_buffer_pos = 0;
		if( isLooping ){
			avformat_seek_file(container,audio_stream_id,0,0,0,AVSEEK_FLAG_ANY);
			avcodec_flush_buffers(codec_context);
			decode_next_frame();
		}
		else{
			isPlaying = false;
		}

		return false;
	}
}

unsigned long long ofxAvAudioPlayer::av_time_to_millis( int64_t av_time ){
	return av_rescale(1000*av_time,(uint64_t)container->streams[audio_stream_id]->time_base.num,container->streams[audio_stream_id]->time_base.den);
	//alternative:
	//return av_time*1000*av_q2d(container->streams[audio_stream_id]->time_base);
}

int64_t ofxAvAudioPlayer::millis_to_av_time( unsigned long long ms ){
	//TODO: fix conversion
/*	int64_t timeBase = (int64_t(codec_context->time_base.num) * AV_TIME_BASE) / int64_t(codec_context->time_base.den);
	int64_t seekTarget = int64_t(ms) / timeBase;*/
	return av_rescale(ms,container->streams[audio_stream_id]->time_base.den,(uint64_t)container->streams[audio_stream_id]->time_base.num)/1000;
}

void ofxAvAudioPlayer::setPositionMS(int ms){
	next_seekTarget = millis_to_av_time(ms);
}

int ofxAvAudioPlayer::getPositionMS(){
	if( !isLoaded ) return 0;
	int64_t ts = packet.pts;
	return av_time_to_millis( ts );
}

float ofxAvAudioPlayer::getPosition(){
	return duration == 0? 0 : (getPositionMS()/(float)duration);
}

void ofxAvAudioPlayer::setPosition(float percent){
	if(duration>0) setPositionMS(percent*duration);
}

void ofxAvAudioPlayer::stop(){
	isPlaying =false;
}

void ofxAvAudioPlayer::play(){
	if( isLoaded ){
		isPlaying = true;
	}
}

void ofxAvAudioPlayer::setLoop(bool loop){
	isLooping = loop;
}

void ofxAvAudioPlayer::setVolume(float vol){
	this->volume = vol;
}

string ofxAvAudioPlayer::getMetadata( string key ){
	if( container != NULL ){
		AVDictionaryEntry * entry = av_dict_get(container->metadata, key.c_str(), NULL, 0);
		if( entry == NULL ) return "";
		else return string(entry->value);
	}
	else{
		return "";
	}
}

map<string,string> ofxAvAudioPlayer::getMetadata(){
	map<string,string> meta;
	AVDictionary * d = container->metadata;
	AVDictionaryEntry *t = NULL;
	while ((t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX))!=0){
		meta[string(t->key)] = string(t->value);
	}

	return meta;
}

<|endoftext|>


<commit_before>/*
 *  glContext.cpp
 *  MonkVG-OpenGL
 *
 *  Created by Micah Pearlman on 8/6/10.
 *  Copyright 2010 MP Engineering. All rights reserved.
 *
 */

#include "glContext.h"
#include "glPath.h"
#include "glPaint.h"
#include "mkCommon.h"

namespace MonkVG {

	OpenGLContext::OpenGLContext()
		:	IContext()
	{
	}

	void OpenGLContext::checkGLError() {

		int err = glGetError();

		const char* RVAL = "GL_UNKNOWN_ERROR";

		switch( err )
		{
			case GL_NO_ERROR:
				RVAL =  "GL_NO_ERROR";
				break;
			case GL_INVALID_ENUM:
				RVAL =  "GL_INVALID_ENUM";
				break;
			case GL_INVALID_VALUE:
				RVAL =  "GL_INVALID_VALUE";
				break;
			case GL_INVALID_OPERATION:
				RVAL = "GL_INVALID_OPERATION";
				break;
			case GL_STACK_OVERFLOW:
				RVAL =  "GL_STACK_OVERFLOW";
				break;
			case GL_STACK_UNDERFLOW:
				RVAL =  "GL_STACK_UNDERFLOW";
				break;
			case GL_OUT_OF_MEMORY:
				RVAL =  "GL_OUT_OF_MEMORY";
				break;
			default:
				break;
		}

		if( err != GL_NO_ERROR ) {
			printf("GL_ERROR: %s\n", RVAL );
			MK_ASSERT(0);
		}
	}

	bool OpenGLContext::Initialize() {

//		/* setup GL projection */
//		glViewport(0,0, _width, _height);
//
//		glMatrixMode(GL_PROJECTION);
//		glLoadIdentity();
//		glOrthof(0, _width, _height, 0, -1, 1);
//		glMatrixMode(GL_MODELVIEW);
//		glLoadIdentity();

		return true;
	}

	bool OpenGLContext::Terminate() {
		return true;
	}

	void OpenGLContext::beginRender() {

		CHECK_GL_ERROR;

		// get viewport to restore back when we are done
		glGetIntegerv( GL_VIEWPORT, _viewport );
		glGetFloatv( GL_PROJECTION_MATRIX, _projection );
		glGetFloatv( GL_MODELVIEW_MATRIX, _modelview );

		// get the color to back up when we are done
		glGetFloatv( GL_CURRENT_COLOR, _color );

		// setup GL projection
		glViewport(0,0, _width, _height);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrthof(0, _width, _height, 0, -1, 1);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		glDisable( GL_CULL_FACE );

		// turn on blending
		glEnable(GL_BLEND);
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		CHECK_GL_ERROR;

	}
	void OpenGLContext::endRender() {

		CHECK_GL_ERROR;

		// todo: restore state to be nice to other apps
		// restore the old viewport
		glMatrixMode( GL_PROJECTION );
		glLoadMatrixf( _projection );
		glViewport( _viewport[0], _viewport[1], _viewport[2], _viewport[3] );
		glMatrixMode( GL_MODELVIEW );
		glLoadMatrixf( _modelview );

		// restore color
		glColor4f( _color[0], _color[1], _color[2], _color[3] );

		CHECK_GL_ERROR;
	}

	IPath* OpenGLContext::createPath( VGint pathFormat, VGPathDatatype datatype, VGfloat scale, VGfloat bias, VGint segmentCapacityHint, VGint coordCapacityHint, VGbitfield capabilities ) {

		OpenGLPath *path = new OpenGLPath(pathFormat, datatype, scale, bias, segmentCapacityHint, coordCapacityHint, capabilities  &= VG_PATH_CAPABILITY_ALL);
		if( path == 0 )
			setError( VG_OUT_OF_MEMORY_ERROR );

		return (IPath*)path;
	}

	void OpenGLContext::destroyPath( IPath* path ) {
		delete (OpenGLPath*)path;
	}

	void OpenGLContext::destroyPaint( IPaint* paint ) {
		delete (OpenGLPaint*)paint;
	}

	IPaint* OpenGLContext::createPaint() {
		OpenGLPaint *paint = new OpenGLPaint();
		if( paint == 0 )
			setError( VG_OUT_OF_MEMORY_ERROR );
		return (IPaint*)paint;
	}

	void OpenGLContext::stroke() {
		if ( _stroke_paint ) {
			const VGfloat* c = _stroke_paint->getPaintColor();
			glColor4f(c[0], c[1], c[2], c[3] );
		}
	}

	void OpenGLContext::fill() {
		if ( _fill_paint ) {
			const VGfloat* c = _fill_paint->getPaintColor();
			glColor4f(c[0], c[1], c[2], c[3] );
		}

	}

	void OpenGLContext::clear(VGint x, VGint y, VGint width, VGint height) {
	}

	void OpenGLContext::setIdentity() {
		Matrix33* active = getActiveMatrix();
		active->setIdentity();
	}

	void OpenGLContext::transform( VGfloat* t ) {
		// a	b	0
		// c	d	0
		// tx	ty	1
		Matrix33* active = getActiveMatrix();
		for ( int x = 0; x < 3; x++ ) {
			for ( int y = 0; y < 3; y++ ) {
				t[(y*3)+x] = active->get( y, x );
			}
		}
	}

	void OpenGLContext::setTransform( const VGfloat* t )  {
		//	OpenVG:
		//	sh	shx	tx
		//	shy	sy	ty
		//	0	0	1
		//
		// OpenGL
		// a	b	0
		// c	d	0
		// tx	ty	1

		Matrix33* active = getActiveMatrix();
		// transpose:  see above
		for ( int x = 0; x < 3; x++ ) {
			for ( int y = 0; y < 3; y++ ) {
				active->set( y, x, t[(y*3)+x] );
			}
		}
	}

	void OpenGLContext::multiply( const VGfloat* t ) {
		Matrix33 m;
		for ( int x = 0; x < 3; x++ ) {
			for ( int y = 0; y < 3; y++ ) {
				m.set( y, x, t[(y*3)+x] );
			}
		}
		Matrix33* active = getActiveMatrix();
		//m.multiply( *active );
		//active->copy( m );
		//active->multiply( m );
		active->postMultiply( m );
	}

	void OpenGLContext::scale( VGfloat sx, VGfloat sy ) {
		Matrix33* active = getActiveMatrix();
		Matrix33 scale;
		scale.setIdentity();
		scale.setScale( sx, sy );
		active->preMultiply( scale );
	}
	void OpenGLContext::translate( VGfloat x, VGfloat y ) {

		Matrix33* active = getActiveMatrix();
		Matrix33 translate;
		translate.setTranslate( x, y );
		Matrix33 tmp;
		tmp.setIdentity();
		Matrix33::multiply( tmp, *active, translate );
		active->copy( tmp );
	}
	void OpenGLContext::rotate( VGfloat angle ) {
		Matrix33* active = getActiveMatrix();
		Matrix33 rotate;
		rotate.setRotate( radians( -angle ) );
		Matrix33 tmp;
		tmp.setIdentity();
		Matrix33::multiply( tmp, *active, rotate );
		active->copy( tmp );
	}

	//// singleton implementation ////
	static OpenGLContext g_context;
	IContext& IContext::instance()
	{
		return g_context;
	}

}<commit_msg>set matrix operations to be more intuitive, though opposite of opengl.<commit_after>/*
 *  glContext.cpp
 *  MonkVG-OpenGL
 *
 *  Created by Micah Pearlman on 8/6/10.
 *  Copyright 2010 MP Engineering. All rights reserved.
 *
 */

#include "glContext.h"
#include "glPath.h"
#include "glPaint.h"
#include "mkCommon.h"

namespace MonkVG {

	OpenGLContext::OpenGLContext()
		:	IContext()
	{
	}

	void OpenGLContext::checkGLError() {

		int err = glGetError();

		const char* RVAL = "GL_UNKNOWN_ERROR";

		switch( err )
		{
			case GL_NO_ERROR:
				RVAL =  "GL_NO_ERROR";
				break;
			case GL_INVALID_ENUM:
				RVAL =  "GL_INVALID_ENUM";
				break;
			case GL_INVALID_VALUE:
				RVAL =  "GL_INVALID_VALUE";
				break;
			case GL_INVALID_OPERATION:
				RVAL = "GL_INVALID_OPERATION";
				break;
			case GL_STACK_OVERFLOW:
				RVAL =  "GL_STACK_OVERFLOW";
				break;
			case GL_STACK_UNDERFLOW:
				RVAL =  "GL_STACK_UNDERFLOW";
				break;
			case GL_OUT_OF_MEMORY:
				RVAL =  "GL_OUT_OF_MEMORY";
				break;
			default:
				break;
		}

		if( err != GL_NO_ERROR ) {
			printf("GL_ERROR: %s\n", RVAL );
			MK_ASSERT(0);
		}
	}

	bool OpenGLContext::Initialize() {

//		/* setup GL projection */
//		glViewport(0,0, _width, _height);
//
//		glMatrixMode(GL_PROJECTION);
//		glLoadIdentity();
//		glOrthof(0, _width, _height, 0, -1, 1);
//		glMatrixMode(GL_MODELVIEW);
//		glLoadIdentity();

		return true;
	}

	bool OpenGLContext::Terminate() {
		return true;
	}

	void OpenGLContext::beginRender() {

		CHECK_GL_ERROR;

		// get viewport to restore back when we are done
		glGetIntegerv( GL_VIEWPORT, _viewport );
		glGetFloatv( GL_PROJECTION_MATRIX, _projection );
		glGetFloatv( GL_MODELVIEW_MATRIX, _modelview );

		// get the color to back up when we are done
		glGetFloatv( GL_CURRENT_COLOR, _color );

		// setup GL projection
		glViewport(0,0, _width, _height);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrthof(0, _width, _height, 0, -1, 1);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		glDisable( GL_CULL_FACE );

		// turn on blending
		glEnable(GL_BLEND);
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		CHECK_GL_ERROR;

	}
	void OpenGLContext::endRender() {

		CHECK_GL_ERROR;

		// todo: restore state to be nice to other apps
		// restore the old viewport
		glMatrixMode( GL_PROJECTION );
		glLoadMatrixf( _projection );
		glViewport( _viewport[0], _viewport[1], _viewport[2], _viewport[3] );
		glMatrixMode( GL_MODELVIEW );
		glLoadMatrixf( _modelview );

		// restore color
		glColor4f( _color[0], _color[1], _color[2], _color[3] );

		CHECK_GL_ERROR;
	}

	IPath* OpenGLContext::createPath( VGint pathFormat, VGPathDatatype datatype, VGfloat scale, VGfloat bias, VGint segmentCapacityHint, VGint coordCapacityHint, VGbitfield capabilities ) {

		OpenGLPath *path = new OpenGLPath(pathFormat, datatype, scale, bias, segmentCapacityHint, coordCapacityHint, capabilities  &= VG_PATH_CAPABILITY_ALL);
		if( path == 0 )
			setError( VG_OUT_OF_MEMORY_ERROR );

		return (IPath*)path;
	}

	void OpenGLContext::destroyPath( IPath* path ) {
		delete (OpenGLPath*)path;
	}

	void OpenGLContext::destroyPaint( IPaint* paint ) {
		delete (OpenGLPaint*)paint;
	}

	IPaint* OpenGLContext::createPaint() {
		OpenGLPaint *paint = new OpenGLPaint();
		if( paint == 0 )
			setError( VG_OUT_OF_MEMORY_ERROR );
		return (IPaint*)paint;
	}

	void OpenGLContext::stroke() {
		if ( _stroke_paint ) {
			const VGfloat* c = _stroke_paint->getPaintColor();
			glColor4f(c[0], c[1], c[2], c[3] );
		}
	}

	void OpenGLContext::fill() {
		if ( _fill_paint ) {
			const VGfloat* c = _fill_paint->getPaintColor();
			glColor4f(c[0], c[1], c[2], c[3] );
		}

	}

	void OpenGLContext::clear(VGint x, VGint y, VGint width, VGint height) {
	}

	void OpenGLContext::setIdentity() {
		Matrix33* active = getActiveMatrix();
		active->setIdentity();
	}

	void OpenGLContext::transform( VGfloat* t ) {
		// a	b	0
		// c	d	0
		// tx	ty	1
		Matrix33* active = getActiveMatrix();
		for ( int x = 0; x < 3; x++ ) {
			for ( int y = 0; y < 3; y++ ) {
				t[(y*3)+x] = active->get( y, x );
			}
		}
	}

	void OpenGLContext::setTransform( const VGfloat* t )  {
		//	OpenVG:
		//	sh	shx	tx
		//	shy	sy	ty
		//	0	0	1
		//
		// OpenGL
		// a	b	0
		// c	d	0
		// tx	ty	1

		Matrix33* active = getActiveMatrix();
		// transpose:  see above
		for ( int x = 0; x < 3; x++ ) {
			for ( int y = 0; y < 3; y++ ) {
				active->set( y, x, t[(y*3)+x] );
			}
		}
	}

	void OpenGLContext::multiply( const VGfloat* t ) {
		Matrix33 m;
		for ( int x = 0; x < 3; x++ ) {
			for ( int y = 0; y < 3; y++ ) {
				m.set( y, x, t[(y*3)+x] );
			}
		}
		Matrix33* active = getActiveMatrix();
		//m.multiply( *active );
		//active->copy( m );
		//active->multiply( m );
		active->postMultiply( m );
	}

	void OpenGLContext::scale( VGfloat sx, VGfloat sy ) {
		Matrix33* active = getActiveMatrix();
		Matrix33 scale;
		scale.setIdentity();
		scale.setScale( sx, sy );
		active->preMultiply( scale );
	}
	void OpenGLContext::translate( VGfloat x, VGfloat y ) {

		Matrix33* active = getActiveMatrix();
		Matrix33 translate;
		translate.setTranslate( x, y );
		Matrix33 tmp;
		tmp.setIdentity();
		//Matrix33::multiply( tmp, *active, translate );
		Matrix33::multiply( tmp, translate, *active );
		active->copy( tmp );
	}
	void OpenGLContext::rotate( VGfloat angle ) {
		Matrix33* active = getActiveMatrix();
		Matrix33 rotate;
		rotate.setRotate( radians( -angle ) );
		Matrix33 tmp;
		tmp.setIdentity();
		Matrix33::multiply( tmp, rotate, *active );
		active->copy( tmp );
	}

	//// singleton implementation ////
	static OpenGLContext g_context;
	IContext& IContext::instance()
	{
		return g_context;
	}

}<|endoftext|>


<commit_before>#include <osg/DOFTransform>

#include <osgUtil/CullVisitor>
#include <osgUtil/AppVisitor>

using namespace osg;

struct DOFCullCallback : public Transform::ComputeTransformCallback
{
    /**/
    virtual const bool computeLocalToWorldMatrix(Matrix& matrix, const Transform* trans, NodeVisitor* nv) const
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if(cv)
        {
            const DOFTransform* dof = dynamic_cast<const DOFTransform*>(trans);
            if(dof)
            {
                //here we are:
                //put the PUT matrix first:
                Matrix l2w(dof->getPutMatrix());

                //now the current matrix:
                Matrix current;
                current.makeTranslate(dof->getCurrentTranslate());

                //now create the local rotation:
                current.preMult(Matrix::rotate(dof->getCurrentHPR()[1], 1.0, 0.0, 0.0));//pitch
                current.preMult(Matrix::rotate(dof->getCurrentHPR()[2], 0.0, 1.0, 0.0));//roll
                current.preMult(Matrix::rotate(dof->getCurrentHPR()[0], 0.0, 0.0, 1.0));//heading

                //and scale:
                current.preMult(Matrix::scale(dof->getCurrentScale()));

                l2w.postMult(current);

                //and impose inverse put:
                l2w.postMult(dof->getInversePutMatrix());

                //finally:
                matrix.preMult(l2w);
            }
        }

        return true;
    }

    /**/
    virtual const bool computeWorldToLocalMatrix(Matrix& matrix, const Transform* trans, NodeVisitor* nv) const
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if(cv)
        {
            const DOFTransform* dof = dynamic_cast<const DOFTransform*>(trans);
            if(dof)
            {
                //here we are:
                //put the PUT matrix first:
                Matrix w2l(dof->getInversePutMatrix());

                //now the current matrix:
                Matrix current;
                current.makeTranslate(-dof->getCurrentTranslate());

                //now create the local rotation:

                current.postMult(Matrix::rotate(-dof->getCurrentHPR()[0], 0.0, 0.0, 1.0));//heading
                current.postMult(Matrix::rotate(-dof->getCurrentHPR()[2], 0.0, 1.0, 0.0));//roll
                current.postMult(Matrix::rotate(-dof->getCurrentHPR()[1], 1.0, 0.0, 0.0));//pitch

                //and scale:
                current.postMult(Matrix::scale(1./dof->getCurrentScale()[0], 1./dof->getCurrentScale()[1], 1./dof->getCurrentScale()[2]));

                w2l.postMult(current);

                //and impose inverse put:
                w2l.postMult(dof->getPutMatrix());

                //finally:
                matrix.postMult(w2l);
            }
        }

        return true;
    }
};

class DOFAnimationAppCallback : public osg::NodeCallback
{
    /** Callback method call by the NodeVisitor when visiting a node.*/
    virtual void operator()(Node* node, NodeVisitor* nv)
    {
        //this is aspp visitor, see if we have DOFTransform:
        DOFTransform* dof = dynamic_cast<DOFTransform*>(node);
        if(dof)
        {
            //see if it is ina animation mode:
            dof->animate();
        }

        // note, callback is repsonsible for scenegraph traversal so
        // should always include call the traverse(node,nv) to ensure
        // that the rest of cullbacks and the scene graph are traversed.
        traverse(node,nv);
    }
};

DOFTransform::DOFTransform():
    _limitationFlags(0),
    _animationOn(false),
    _increasingFlags(0xffffff)
{
    //default zero-ed Vec3-s are fine for all
    //default idenetiy inverse matrix is fine:

    _computeTransformCallback = new DOFCullCallback;

    DOFAnimationAppCallback* dof_animation = new DOFAnimationAppCallback;

    setAppCallback(dof_animation);
}

void DOFTransform::setCurrentHPR(const Vec3& hpr)
{
    //if there is no constrain on animation
    if(!(_limitationFlags & ((unsigned long)1<<26)))
    {
        //if we have min == max, it is efective constrain, so don't change
        if(_minHPR[2] != _maxHPR[2])
        {
            _currentHPR[2] = hpr[2];
            unsigned short this_flag = (unsigned short)1<<4;//roll

            if(_currentHPR[2] < _minHPR[2])
            {
                _currentHPR[2] = _minHPR[2];
                //force increasing flag to 1
                _increasingFlags |= this_flag;
            }
            else if(_currentHPR[2] > _maxHPR[2])
            {
                _currentHPR[2] = _maxHPR[2];
                //force increasing flag to 0
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & ((unsigned long)1<<27)))
    {
        if(_minHPR[1] != _maxHPR[1])
        {
            _currentHPR[1] = hpr[1];
            unsigned short this_flag = (unsigned short)1<<3;//pitch

            if(_currentHPR[1] < _minHPR[1])
            {
                _currentHPR[1] = _minHPR[1];
                _increasingFlags |= this_flag;
            }
            else if(_currentHPR[1] > _maxHPR[1])
            {
                _currentHPR[1] = _maxHPR[1];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & ((unsigned long)1<<28)))
    {
        if(_minHPR[0] != _maxHPR[0])
        {
            _currentHPR[0] = hpr[0];

            unsigned short this_flag = (unsigned short)1<<5;//heading

            if(_currentHPR[0] < _minHPR[0])
            {
                _currentHPR[0] = _minHPR[0];
                _increasingFlags |= this_flag;
            }
            else if(_currentHPR[0] > _maxHPR[0])
            {
                _currentHPR[0] = _maxHPR[0];
                _increasingFlags &= ~this_flag;
            }
        }
    }
}

void DOFTransform::setCurrentTranslate(const Vec3& translate)
{
    if(!(_limitationFlags & (unsigned long)1<<29))
    {
        if(_minTranslate[2] != _maxTranslate[2])
        {
            _currentTranslate[2] = translate[2];
            unsigned short this_flag = (unsigned short)1<<2;

            if(_currentTranslate[2] < _minTranslate[2])
            {
                _currentTranslate[2] = _minTranslate[2];
                _increasingFlags |= this_flag;
            }
            else if(_currentTranslate[2] > _maxTranslate[2])
            {
                _currentTranslate[2] = _maxTranslate[2];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & (unsigned long)1<<30))
    {
        if(_minTranslate[1] != _maxTranslate[1])
        {
            _currentTranslate[1] = translate[1];
            unsigned short this_flag = (unsigned short)1<<1;

            if(_currentTranslate[1] < _minTranslate[1])
            {
                _currentTranslate[1] = _minTranslate[1];
                _increasingFlags |= this_flag;
            }
            else if(_currentTranslate[1] > _maxTranslate[1])
            {
                _currentTranslate[1] = _maxTranslate[1];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & (unsigned long)1<<31))
    {
        if(_minTranslate[0] != _maxTranslate[0])
        {
            _currentTranslate[0] = translate[0];
            unsigned short this_flag = (unsigned short)1;

            if(_currentTranslate[0] < _minTranslate[0])
            {
                _currentTranslate[0] = _minTranslate[0];
                _increasingFlags |= this_flag;
            }
            else if(_currentTranslate[0] > _maxTranslate[0])
            {
                _currentTranslate[0] = _maxTranslate[0];
                _increasingFlags &= ~this_flag;
            }
        }
    }
}

void DOFTransform::setCurrentScale(const Vec3& scale)
{

    if(!(_limitationFlags & ((unsigned long)1<<23)))
    {
        if(_minScale[2] != _maxScale[2])
        {
            _currentScale[2] = scale[2];
            unsigned short this_flag = (unsigned short)1<<8;

            if(_currentScale[2] < _minScale[2])
            {
                _currentScale[2] = _minScale[2];
                _increasingFlags |= this_flag;
            }
            else if(_currentScale[2] > _maxScale[2])
            {
                _currentScale[2] = _maxScale[2];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & ((unsigned long)1<<24)))
    {
        if(_minScale[1] != _maxScale[1])
        {
            _currentScale[1] = scale[1];
            unsigned short this_flag = (unsigned short)1<<7;

            if(_currentScale[1] < _minScale[1])
            {
                _currentScale[1] = _minScale[1];
                _increasingFlags |= this_flag;
            }
            else if(_currentScale[1] > _maxScale[1])
            {
                _currentScale[1] = _maxScale[1];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & ((unsigned long)1<<25)))
    {
        if(_minScale[0] != _maxScale[0])
        {
            _currentScale[0] = scale[0];
            unsigned short this_flag = (unsigned short)1<<6;

            if(_currentScale[0] < _minScale[0])
            {
                _currentScale[0] = _minScale[0];
                _increasingFlags |= this_flag;
            }
            else if(_currentScale[0] > _maxScale[0])
            {
                _currentScale[0] = _maxScale[0];
                _increasingFlags &= ~this_flag;
            }
        }
    }
}

void DOFTransform::animate()
{
    if(!_animationOn) return;
    //this will increment or decrement all allowed values

    Vec3 new_value = _currentTranslate;

    if(_increasingFlags & 1)
        new_value[0] += _incrementTranslate[0];
    else
        new_value[0] -= _incrementTranslate[0];

    if(_increasingFlags & 1<<1)
        new_value[1] += _incrementTranslate[1];
    else
        new_value[1] -= _incrementTranslate[1];

    if(_increasingFlags & 1<<2)
        new_value[2] += _incrementTranslate[2];
    else
        new_value[2] -= _incrementTranslate[2];

    setCurrentTranslate(new_value);

    new_value = _currentHPR;

    if(_increasingFlags & ((unsigned short)1<<3))
        new_value[1] += _incrementHPR[1];
    else
        new_value[1] -= _incrementHPR[1];

    if(_increasingFlags & ((unsigned short)1<<4))
        new_value[2] += _incrementHPR[2];
    else
        new_value[2] -= _incrementHPR[2];

    if(_increasingFlags & ((unsigned short)1<<5))
        new_value[0] += _incrementHPR[0];
    else
        new_value[0] -= _incrementHPR[0];

    setCurrentHPR(new_value);

    new_value = _currentScale;

    if(_increasingFlags & 1<<6)
        new_value[0] += _incrementScale[0];
    else
        new_value[0] -= _incrementScale[0];

    if(_increasingFlags & 1<<7)
        new_value[1] += _incrementScale[1];
    else
        new_value[1] -= _incrementScale[1];

    if(_increasingFlags & 1<<8)
        new_value[2] += _incrementScale[2];
    else
        new_value[2] -= _incrementScale[2];

    setCurrentScale(new_value);
}
<commit_msg>Changed the default value of _animationOn to true.<commit_after>#include <osg/DOFTransform>

#include <osgUtil/CullVisitor>
#include <osgUtil/AppVisitor>

using namespace osg;

struct DOFCullCallback : public Transform::ComputeTransformCallback
{
    /**/
    virtual const bool computeLocalToWorldMatrix(Matrix& matrix, const Transform* trans, NodeVisitor* nv) const
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if(cv)
        {
            const DOFTransform* dof = dynamic_cast<const DOFTransform*>(trans);
            if(dof)
            {
                //here we are:
                //put the PUT matrix first:
                Matrix l2w(dof->getPutMatrix());

                //now the current matrix:
                Matrix current;
                current.makeTranslate(dof->getCurrentTranslate());

                //now create the local rotation:
                current.preMult(Matrix::rotate(dof->getCurrentHPR()[1], 1.0, 0.0, 0.0));//pitch
                current.preMult(Matrix::rotate(dof->getCurrentHPR()[2], 0.0, 1.0, 0.0));//roll
                current.preMult(Matrix::rotate(dof->getCurrentHPR()[0], 0.0, 0.0, 1.0));//heading

                //and scale:
                current.preMult(Matrix::scale(dof->getCurrentScale()));

                l2w.postMult(current);

                //and impose inverse put:
                l2w.postMult(dof->getInversePutMatrix());

                //finally:
                matrix.preMult(l2w);
            }
        }

        return true;
    }

    /**/
    virtual const bool computeWorldToLocalMatrix(Matrix& matrix, const Transform* trans, NodeVisitor* nv) const
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if(cv)
        {
            const DOFTransform* dof = dynamic_cast<const DOFTransform*>(trans);
            if(dof)
            {
                //here we are:
                //put the PUT matrix first:
                Matrix w2l(dof->getInversePutMatrix());

                //now the current matrix:
                Matrix current;
                current.makeTranslate(-dof->getCurrentTranslate());

                //now create the local rotation:

                current.postMult(Matrix::rotate(-dof->getCurrentHPR()[0], 0.0, 0.0, 1.0));//heading
                current.postMult(Matrix::rotate(-dof->getCurrentHPR()[2], 0.0, 1.0, 0.0));//roll
                current.postMult(Matrix::rotate(-dof->getCurrentHPR()[1], 1.0, 0.0, 0.0));//pitch

                //and scale:
                current.postMult(Matrix::scale(1./dof->getCurrentScale()[0], 1./dof->getCurrentScale()[1], 1./dof->getCurrentScale()[2]));

                w2l.postMult(current);

                //and impose inverse put:
                w2l.postMult(dof->getPutMatrix());

                //finally:
                matrix.postMult(w2l);
            }
        }

        return true;
    }
};

class DOFAnimationAppCallback : public osg::NodeCallback
{
    /** Callback method call by the NodeVisitor when visiting a node.*/
    virtual void operator()(Node* node, NodeVisitor* nv)
    {
        //this is aspp visitor, see if we have DOFTransform:
        DOFTransform* dof = dynamic_cast<DOFTransform*>(node);
        if(dof)
        {
            //see if it is ina animation mode:
            dof->animate();
        }

        // note, callback is repsonsible for scenegraph traversal so
        // should always include call the traverse(node,nv) to ensure
        // that the rest of cullbacks and the scene graph are traversed.
        traverse(node,nv);
    }
};

DOFTransform::DOFTransform():
    _limitationFlags(0),
    _animationOn(true),
    _increasingFlags(0xffffff)
{
    //default zero-ed Vec3-s are fine for all
    //default idenetiy inverse matrix is fine:

    _computeTransformCallback = new DOFCullCallback;

    DOFAnimationAppCallback* dof_animation = new DOFAnimationAppCallback;

    setAppCallback(dof_animation);
}

void DOFTransform::setCurrentHPR(const Vec3& hpr)
{
    //if there is no constrain on animation
    if(!(_limitationFlags & ((unsigned long)1<<26)))
    {
        //if we have min == max, it is efective constrain, so don't change
        if(_minHPR[2] != _maxHPR[2])
        {
            _currentHPR[2] = hpr[2];
            unsigned short this_flag = (unsigned short)1<<4;//roll

            if(_currentHPR[2] < _minHPR[2])
            {
                _currentHPR[2] = _minHPR[2];
                //force increasing flag to 1
                _increasingFlags |= this_flag;
            }
            else if(_currentHPR[2] > _maxHPR[2])
            {
                _currentHPR[2] = _maxHPR[2];
                //force increasing flag to 0
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & ((unsigned long)1<<27)))
    {
        if(_minHPR[1] != _maxHPR[1])
        {
            _currentHPR[1] = hpr[1];
            unsigned short this_flag = (unsigned short)1<<3;//pitch

            if(_currentHPR[1] < _minHPR[1])
            {
                _currentHPR[1] = _minHPR[1];
                _increasingFlags |= this_flag;
            }
            else if(_currentHPR[1] > _maxHPR[1])
            {
                _currentHPR[1] = _maxHPR[1];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & ((unsigned long)1<<28)))
    {
        if(_minHPR[0] != _maxHPR[0])
        {
            _currentHPR[0] = hpr[0];

            unsigned short this_flag = (unsigned short)1<<5;//heading

            if(_currentHPR[0] < _minHPR[0])
            {
                _currentHPR[0] = _minHPR[0];
                _increasingFlags |= this_flag;
            }
            else if(_currentHPR[0] > _maxHPR[0])
            {
                _currentHPR[0] = _maxHPR[0];
                _increasingFlags &= ~this_flag;
            }
        }
    }
}

void DOFTransform::setCurrentTranslate(const Vec3& translate)
{
    if(!(_limitationFlags & (unsigned long)1<<29))
    {
        if(_minTranslate[2] != _maxTranslate[2])
        {
            _currentTranslate[2] = translate[2];
            unsigned short this_flag = (unsigned short)1<<2;

            if(_currentTranslate[2] < _minTranslate[2])
            {
                _currentTranslate[2] = _minTranslate[2];
                _increasingFlags |= this_flag;
            }
            else if(_currentTranslate[2] > _maxTranslate[2])
            {
                _currentTranslate[2] = _maxTranslate[2];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & (unsigned long)1<<30))
    {
        if(_minTranslate[1] != _maxTranslate[1])
        {
            _currentTranslate[1] = translate[1];
            unsigned short this_flag = (unsigned short)1<<1;

            if(_currentTranslate[1] < _minTranslate[1])
            {
                _currentTranslate[1] = _minTranslate[1];
                _increasingFlags |= this_flag;
            }
            else if(_currentTranslate[1] > _maxTranslate[1])
            {
                _currentTranslate[1] = _maxTranslate[1];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & (unsigned long)1<<31))
    {
        if(_minTranslate[0] != _maxTranslate[0])
        {
            _currentTranslate[0] = translate[0];
            unsigned short this_flag = (unsigned short)1;

            if(_currentTranslate[0] < _minTranslate[0])
            {
                _currentTranslate[0] = _minTranslate[0];
                _increasingFlags |= this_flag;
            }
            else if(_currentTranslate[0] > _maxTranslate[0])
            {
                _currentTranslate[0] = _maxTranslate[0];
                _increasingFlags &= ~this_flag;
            }
        }
    }
}

void DOFTransform::setCurrentScale(const Vec3& scale)
{

    if(!(_limitationFlags & ((unsigned long)1<<23)))
    {
        if(_minScale[2] != _maxScale[2])
        {
            _currentScale[2] = scale[2];
            unsigned short this_flag = (unsigned short)1<<8;

            if(_currentScale[2] < _minScale[2])
            {
                _currentScale[2] = _minScale[2];
                _increasingFlags |= this_flag;
            }
            else if(_currentScale[2] > _maxScale[2])
            {
                _currentScale[2] = _maxScale[2];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & ((unsigned long)1<<24)))
    {
        if(_minScale[1] != _maxScale[1])
        {
            _currentScale[1] = scale[1];
            unsigned short this_flag = (unsigned short)1<<7;

            if(_currentScale[1] < _minScale[1])
            {
                _currentScale[1] = _minScale[1];
                _increasingFlags |= this_flag;
            }
            else if(_currentScale[1] > _maxScale[1])
            {
                _currentScale[1] = _maxScale[1];
                _increasingFlags &= ~this_flag;
            }
        }
    }

    if(!(_limitationFlags & ((unsigned long)1<<25)))
    {
        if(_minScale[0] != _maxScale[0])
        {
            _currentScale[0] = scale[0];
            unsigned short this_flag = (unsigned short)1<<6;

            if(_currentScale[0] < _minScale[0])
            {
                _currentScale[0] = _minScale[0];
                _increasingFlags |= this_flag;
            }
            else if(_currentScale[0] > _maxScale[0])
            {
                _currentScale[0] = _maxScale[0];
                _increasingFlags &= ~this_flag;
            }
        }
    }
}

void DOFTransform::animate()
{
    if(!_animationOn) return;
    //this will increment or decrement all allowed values

    Vec3 new_value = _currentTranslate;

    if(_increasingFlags & 1)
        new_value[0] += _incrementTranslate[0];
    else
        new_value[0] -= _incrementTranslate[0];

    if(_increasingFlags & 1<<1)
        new_value[1] += _incrementTranslate[1];
    else
        new_value[1] -= _incrementTranslate[1];

    if(_increasingFlags & 1<<2)
        new_value[2] += _incrementTranslate[2];
    else
        new_value[2] -= _incrementTranslate[2];

    setCurrentTranslate(new_value);

    new_value = _currentHPR;

    if(_increasingFlags & ((unsigned short)1<<3))
        new_value[1] += _incrementHPR[1];
    else
        new_value[1] -= _incrementHPR[1];

    if(_increasingFlags & ((unsigned short)1<<4))
        new_value[2] += _incrementHPR[2];
    else
        new_value[2] -= _incrementHPR[2];

    if(_increasingFlags & ((unsigned short)1<<5))
        new_value[0] += _incrementHPR[0];
    else
        new_value[0] -= _incrementHPR[0];

    setCurrentHPR(new_value);

    new_value = _currentScale;

    if(_increasingFlags & 1<<6)
        new_value[0] += _incrementScale[0];
    else
        new_value[0] -= _incrementScale[0];

    if(_increasingFlags & 1<<7)
        new_value[1] += _incrementScale[1];
    else
        new_value[1] -= _incrementScale[1];

    if(_increasingFlags & 1<<8)
        new_value[2] += _incrementScale[2];
    else
        new_value[2] -= _incrementScale[2];

    setCurrentScale(new_value);
}
<|endoftext|>


<commit_before>#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>

#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>

#include "pin.H"

#include "utils/debug.h"
#include "utils/functions_registry.h"
#include "utils/hollow_stack.h"
#include "log/ftable.h"

#define NB_FN_MAX               100000
#define MAX_DEPTH               1000
#define NB_VALS_TO_CONCLUDE     500
#define NB_CALLS_TO_CONCLUDE    500
#define SEUIL                   0.8
#define IGNORE_LIBRARIES        1
#define COUPLE_THRESHOLD        0.8

ifstream ifile;
KNOB<string> KnobInputFile(KNOB_MODE_WRITEONCE, "pintool", "i", "stdin", "Specify an intput file");
ofstream ofile;
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "stdout", "Specify an output file");

/* Call stack */
HollowStack<MAX_DEPTH, FID> call_stack;
/* Call stack is jump */
HollowStack<MAX_DEPTH, bool> is_jump_stack;

UINT64 counter;

struct timeval start, stop;

unsigned int nb_fn = 0;

typedef struct {
    ADDRINT val;
    UINT64 fid;
    UINT64 caller;
    UINT64 counter;
    UINT32 pos;
    BOOL from_main;
} param_t;

unsigned int *nb_p;
bool **param_addr;
bool *is_instrumented;
list<param_t *> *param;

bool init = false;

string read_part(char* c) {
    char m;
    string str = "";

    ifile.read(&m, 1);
    while (ifile && m != ':' && m != '\n') {
        str += m;
        ifile.read(&m, 1);
    }

    *c = m;
    return str;
}

ADDRINT val_from_reg(CONTEXT *ctxt, unsigned int pid) {

    trace_enter();

    REG reg;
    switch (pid) {
    case 0:
        reg = REG_RAX;
        break;
    case 1:
        reg = REG_RDI;
        break;
    case 2:
        reg = REG_RSI;
        break;
    case 3:
        reg = REG_RDX;
        break;
    case 4:
        reg = REG_RCX;
        break;
    case 5:
        reg = REG_R8;
        break;
    case 6:
        reg = REG_R9;
        break;
    default:

        trace_leave();

        return 0;
    }

    trace_leave();

    return PIN_GetContextReg(ctxt, reg);
}

VOID fn_call(CONTEXT *ctxt, FID fid, bool is_jump, ADDRINT inst_addr) {

    trace_enter();

    FID caller = call_stack.top();
    call_stack.push(fid);
    is_jump_stack.push(is_jump);
    counter += 1;

    bool param_pushed = false;

    if (!is_instrumented[fid]) {
        trace_leave();
        return;
    }

    for (unsigned int i = 1; i <= nb_p[fid]; i++) {
        if (param_addr[fid][i]) {
            param_t *new_param = (param_t *) malloc(sizeof(param_t));
            new_param->fid = fid;
            new_param->caller = caller;
            new_param->counter = counter;
            new_param->val = val_from_reg(ctxt, i);
            new_param->pos = i;
            if (IMG_Valid(IMG_FindByAddress(inst_addr))) {
                if (IMG_IsMainExecutable(IMG_FindByAddress(inst_addr)))
                new_param->from_main = IMG_IsMainExecutable(IMG_FindByAddress(inst_addr));
            } else {
                new_param->from_main = 1;
            }
            param->push_front(new_param);
            param_pushed = true;
        }
    }

    /* If the function is instrumented (ie for instance has an ADDR as
       a return value) AND was not logged yet, create a special
       entry to log the date of call */
    if (!param_pushed) {
        param_t *new_addr = (param_t *) malloc(sizeof(param_t));
        new_addr->fid = fid;
        new_addr->caller = caller;
        new_addr->counter = counter;
        new_addr->val = 0;
        new_addr->pos = 99;
        if (IMG_Valid(IMG_FindByAddress(inst_addr))) {
            new_addr->from_main = IMG_IsMainExecutable(IMG_FindByAddress(inst_addr));
        } else {
            new_addr->from_main = 0;
        }
        param->push_front(new_addr);
    }

    trace_leave();
    return;
}

VOID fn_icall(CONTEXT* ctxt, ADDRINT target, bool is_jump, ADDRINT inst_addr) {

    trace_enter();

    // Indirect call, we have to look up the function each time
    // The functions `fn_lookup` & `fn_register` needs PIN's Lock.
    // Locking is not implicit in inserted call, as opposed
    // to callback added with *_AddInstrumentFunction().
    PIN_LockClient();
    FID fid = fn_lookup_by_address(target);
    if (is_jump && fid == FID_UNKNOWN) {
        trace_leave();
        return;
    }
    PIN_UnlockClient();

    fn_call(ctxt, fid, is_jump, inst_addr);

    trace_leave();
    return;
}

VOID fn_ret(CONTEXT *ctxt, UINT32 fid) {
    trace_enter();

    counter += 1;

    if (!call_stack.is_top_forgotten()) {
        while (is_jump_stack.top()) {
            FID fid = call_stack.top();
            call_stack.pop();
            is_jump_stack.pop();
            FID caller = call_stack.top();
            if (is_instrumented[fid]) {
                param_t *new_ret = (param_t *) malloc(sizeof(param_t));
                new_ret->fid = fid;
                new_ret->counter = counter;
                new_ret->caller = caller;
                if (param_addr[fid][0])
                    new_ret->val = val_from_reg(ctxt, 0);
                else
                    new_ret->val = 1;
                new_ret->pos = 0;
                param->push_front(new_ret);
            }
        }
        FID fid = call_stack.top();
        call_stack.pop();
        is_jump_stack.pop();
        FID caller = call_stack.top();
        if (is_instrumented[fid]) {
            param_t *new_ret = (param_t *) malloc(sizeof(param_t));
            new_ret->fid = fid;
            new_ret->counter = counter;
            new_ret->caller = caller;
            new_ret->val = val_from_reg(ctxt, 0);
            new_ret->pos = 0;
            param->push_front(new_ret);
        }
    }

    trace_leave();
    return;
}

void fn_registered(
                    FID fid,
                    unsigned int nb_param,
                    vector<bool> type_param
                ) {

    trace_enter();

    /* Set the number of parameters */
    nb_p[fid] = nb_param;
    /* Set the array of booleans indicating which parameter is an ADDR */
    param_addr[fid] = (bool *) calloc(nb_p[fid], sizeof(bool));

    /* Is this function instrumented?*/
    is_instrumented[fid] = false;

    if (fid == FID_UNKNOWN) return;

    /* Iteration on parameters */
    for (unsigned int i = 0; i <= nb_p[fid]; i++) {
        if (type_param[i]) {
            param_addr[fid][i] = true;
            is_instrumented[fid] = true;
        }
        else {
            param_addr[fid][i] = false;
        }
    }

    trace_leave();
    return;
}

VOID Commence();

VOID Instruction(INS ins, VOID *v) {
    if (!init)
        Commence();

    ADDRINT inst_addr = INS_Address(ins);

    if (INS_IsCall(ins)) {
        if (INS_IsDirectCall(ins)) {
            ADDRINT addr = INS_DirectBranchOrCallTargetAddress(ins);
            FID fid = fn_lookup_by_address(addr);
            INS_InsertCall(ins,
                        IPOINT_BEFORE,
                        (AFUNPTR) fn_call,
                        IARG_CONST_CONTEXT,
                        IARG_UINT32, fid,
                        IARG_BOOL, false,
                        IARG_ADDRINT, inst_addr,
                        IARG_END);
        }
        else {
            INS_InsertCall(ins,
                        IPOINT_BEFORE,
                        (AFUNPTR) fn_icall,
                        IARG_CONST_CONTEXT,
                        IARG_BRANCH_TARGET_ADDR,
                        IARG_BOOL, false,
                        IARG_ADDRINT, inst_addr,
                        IARG_END);
        }
    }

    if (INS_IsIndirectBranchOrCall(ins)) {
        if (!INS_IsCall(ins)) {
            INS_InsertCall(ins,
                    IPOINT_BEFORE,
                    (AFUNPTR) fn_icall,
                    IARG_CONST_CONTEXT,
                    IARG_BRANCH_TARGET_ADDR,
                    IARG_BOOL, true,
                    IARG_ADDRINT, inst_addr,
                    IARG_END);
        }
    }

    if (INS_IsRet(ins)) {
        INS_InsertCall(ins,
                    IPOINT_BEFORE,
                    (AFUNPTR) fn_ret,
                    IARG_CONST_CONTEXT,
                    IARG_END);
    }

    return;
}

VOID Commence() {

    trace_enter();

    /* Init instruction counter */
    counter = 0;
    init = true;
    string _addr, _name;
    if (ifile.is_open()) {
        while (ifile) {
            char m;
            vector<bool> type_param;
            string img_name = read_part(&m);
            if (img_name.empty()) {
                continue;
            }
            ADDRINT img_addr = atol(read_part(&m).c_str());
            string name = read_part(&m);
            type_param.push_back(true);
            FID fid = fn_register(img_name, img_addr, name);
            if (fid != FID_UNKNOWN) {
                fn_registered(fid, 0, type_param);
            }

            type_param.clear();
            img_name = read_part(&m);
            if (img_name.empty()) {
                continue;
            }
            img_addr = atol(read_part(&m).c_str());
            name = read_part(&m);

            float rho = atof(read_part(&m).c_str());
            unsigned char param_pos = atoi(read_part(&m).c_str());

            for (unsigned char pos = 0 ; pos < param_pos ; pos++) {
                type_param.push_back(false);
            }
            type_param.push_back(true);

            if (rho > COUPLE_THRESHOLD) {
                fid = fn_register(img_name, img_addr, name);

                if (fid != FID_UNKNOWN) {
                    fn_registered(fid, param_pos, type_param);
                }
            }

        }
    }

    gettimeofday(&start, NULL);

    trace_leave();

    return;
}

VOID Fini(INT32 code, VOID *v) {

    trace_enter();

    list<param_t *>::reverse_iterator it;

    int depth = 0;
    UINT64 last_date = -1;
    bool is_in = false;

    gettimeofday(&stop, NULL);

    /* First, we log the conversion table fid <-> name */
    log_ftable(ofile);

    it = param->rbegin();

    /* Size of fields of structure */
    ofile << sizeof((*it)->val) << ":";
    ofile << sizeof((*it)->fid) << ":";
    ofile << sizeof((*it)->pos) << ":";
    ofile << sizeof((*it)->counter) << ":";
    ofile << sizeof((*it)->from_main) << endl;

    while (it != param->rend()) {
        param_t *p = *it;
        it++;
        if (last_date != p->counter) {
            if (is_in)
                depth++;
            else
                depth--;
        }
        last_date = p->counter;
        ofile.write((char *) &(p->val), sizeof(p->val));
        ofile.write((char *) &(p->fid), sizeof(p->fid));
        ofile.write((char *) &(p->pos), sizeof(p->pos));
        ofile.write((char *) &(p->counter), sizeof(p->counter));
        ofile.write((char *) &(p->from_main), sizeof(p->from_main));
//        std::cerr << p->val << ":" << p->fid << ":" << p->pos << ":" << p->counter << endl;
    }
    ofile.close();

    trace_leave();

    return;
}

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

    param_addr = (bool **) malloc(NB_FN_MAX * sizeof(bool *));
    is_instrumented = (bool *) calloc(NB_FN_MAX, sizeof(bool));
    nb_p = (unsigned int *) calloc(NB_FN_MAX, sizeof(unsigned int));
    param = new list<param_t *>();

    /* Initialize symbol table code,
       needed for rtn instrumentation */
    PIN_InitSymbols();
    PIN_SetSyntaxIntel();

    if (PIN_Init(argc, argv)) return 1;

    ifile.open(KnobInputFile.Value().c_str());
    ofile.open(KnobOutputFile.Value().c_str());

    // INS_AddInstrumentFunction(Instruction, 0);
    INS_AddInstrumentFunction(Instruction, 0);

    fn_registry_init(NB_FN_MAX);
    vector<bool> unknown_int_idx;
    fn_registered(FID_UNKNOWN, 0, unknown_int_idx);

    /* Register Fini to be called when the
       application exits */
    PIN_AddFiniFunction(Fini, 0);

    PIN_StartProgram();

    return 0;
}

<commit_msg>Small change of memalloc threshold<commit_after>#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>

#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>

#include "pin.H"

#include "utils/debug.h"
#include "utils/functions_registry.h"
#include "utils/hollow_stack.h"
#include "log/ftable.h"

#define NB_FN_MAX               100000
#define MAX_DEPTH               1000
#define NB_VALS_TO_CONCLUDE     500
#define NB_CALLS_TO_CONCLUDE    500
#define SEUIL                   0.8
#define IGNORE_LIBRARIES        1
#define COUPLE_THRESHOLD        0.9

ifstream ifile;
KNOB<string> KnobInputFile(KNOB_MODE_WRITEONCE, "pintool", "i", "stdin", "Specify an intput file");
ofstream ofile;
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "stdout", "Specify an output file");

/* Call stack */
HollowStack<MAX_DEPTH, FID> call_stack;
/* Call stack is jump */
HollowStack<MAX_DEPTH, bool> is_jump_stack;

UINT64 counter;

struct timeval start, stop;

unsigned int nb_fn = 0;

typedef struct {
    ADDRINT val;
    UINT64 fid;
    UINT64 caller;
    UINT64 counter;
    UINT32 pos;
    BOOL from_main;
} param_t;

unsigned int *nb_p;
bool **param_addr;
bool *is_instrumented;
list<param_t *> *param;

bool init = false;

string read_part(char* c) {
    char m;
    string str = "";

    ifile.read(&m, 1);
    while (ifile && m != ':' && m != '\n') {
        str += m;
        ifile.read(&m, 1);
    }

    *c = m;
    return str;
}

ADDRINT val_from_reg(CONTEXT *ctxt, unsigned int pid) {

    trace_enter();

    REG reg;
    switch (pid) {
    case 0:
        reg = REG_RAX;
        break;
    case 1:
        reg = REG_RDI;
        break;
    case 2:
        reg = REG_RSI;
        break;
    case 3:
        reg = REG_RDX;
        break;
    case 4:
        reg = REG_RCX;
        break;
    case 5:
        reg = REG_R8;
        break;
    case 6:
        reg = REG_R9;
        break;
    default:

        trace_leave();

        return 0;
    }

    trace_leave();

    return PIN_GetContextReg(ctxt, reg);
}

VOID fn_call(CONTEXT *ctxt, FID fid, bool is_jump, ADDRINT inst_addr) {

    trace_enter();

    FID caller = call_stack.top();
    call_stack.push(fid);
    is_jump_stack.push(is_jump);
    counter += 1;

    bool param_pushed = false;

    if (!is_instrumented[fid]) {
        trace_leave();
        return;
    }

    for (unsigned int i = 1; i <= nb_p[fid]; i++) {
        if (param_addr[fid][i]) {
            param_t *new_param = (param_t *) malloc(sizeof(param_t));
            new_param->fid = fid;
            new_param->caller = caller;
            new_param->counter = counter;
            new_param->val = val_from_reg(ctxt, i);
            new_param->pos = i;
            if (IMG_Valid(IMG_FindByAddress(inst_addr))) {
                if (IMG_IsMainExecutable(IMG_FindByAddress(inst_addr)))
                new_param->from_main = IMG_IsMainExecutable(IMG_FindByAddress(inst_addr));
            } else {
                new_param->from_main = 1;
            }
            param->push_front(new_param);
            param_pushed = true;
        }
    }

    /* If the function is instrumented (ie for instance has an ADDR as
       a return value) AND was not logged yet, create a special
       entry to log the date of call */
    if (!param_pushed) {
        param_t *new_addr = (param_t *) malloc(sizeof(param_t));
        new_addr->fid = fid;
        new_addr->caller = caller;
        new_addr->counter = counter;
        new_addr->val = 0;
        new_addr->pos = 99;
        if (IMG_Valid(IMG_FindByAddress(inst_addr))) {
            new_addr->from_main = IMG_IsMainExecutable(IMG_FindByAddress(inst_addr));
        } else {
            new_addr->from_main = 0;
        }
        param->push_front(new_addr);
    }

    trace_leave();
    return;
}

VOID fn_icall(CONTEXT* ctxt, ADDRINT target, bool is_jump, ADDRINT inst_addr) {

    trace_enter();

    // Indirect call, we have to look up the function each time
    // The functions `fn_lookup` & `fn_register` needs PIN's Lock.
    // Locking is not implicit in inserted call, as opposed
    // to callback added with *_AddInstrumentFunction().
    PIN_LockClient();
    FID fid = fn_lookup_by_address(target);
    if (is_jump && fid == FID_UNKNOWN) {
        trace_leave();
        return;
    }
    PIN_UnlockClient();

    fn_call(ctxt, fid, is_jump, inst_addr);

    trace_leave();
    return;
}

VOID fn_ret(CONTEXT *ctxt, UINT32 fid) {
    trace_enter();

    counter += 1;

    if (!call_stack.is_top_forgotten()) {
        while (is_jump_stack.top()) {
            FID fid = call_stack.top();
            call_stack.pop();
            is_jump_stack.pop();
            FID caller = call_stack.top();
            if (is_instrumented[fid]) {
                param_t *new_ret = (param_t *) malloc(sizeof(param_t));
                new_ret->fid = fid;
                new_ret->counter = counter;
                new_ret->caller = caller;
                if (param_addr[fid][0])
                    new_ret->val = val_from_reg(ctxt, 0);
                else
                    new_ret->val = 1;
                new_ret->pos = 0;
                param->push_front(new_ret);
            }
        }
        FID fid = call_stack.top();
        call_stack.pop();
        is_jump_stack.pop();
        FID caller = call_stack.top();
        if (is_instrumented[fid]) {
            param_t *new_ret = (param_t *) malloc(sizeof(param_t));
            new_ret->fid = fid;
            new_ret->counter = counter;
            new_ret->caller = caller;
            new_ret->val = val_from_reg(ctxt, 0);
            new_ret->pos = 0;
            param->push_front(new_ret);
        }
    }

    trace_leave();
    return;
}

void fn_registered(
                    FID fid,
                    unsigned int nb_param,
                    vector<bool> type_param
                ) {

    trace_enter();

    /* Set the number of parameters */
    nb_p[fid] = nb_param;
    /* Set the array of booleans indicating which parameter is an ADDR */
    param_addr[fid] = (bool *) calloc(nb_p[fid], sizeof(bool));

    /* Is this function instrumented?*/
    is_instrumented[fid] = false;

    if (fid == FID_UNKNOWN) return;

    /* Iteration on parameters */
    for (unsigned int i = 0; i <= nb_p[fid]; i++) {
        if (type_param[i]) {
            param_addr[fid][i] = true;
            is_instrumented[fid] = true;
        }
        else {
            param_addr[fid][i] = false;
        }
    }

    trace_leave();
    return;
}

VOID Commence();

VOID Instruction(INS ins, VOID *v) {
    if (!init)
        Commence();

    ADDRINT inst_addr = INS_Address(ins);

    if (INS_IsCall(ins)) {
        if (INS_IsDirectCall(ins)) {
            ADDRINT addr = INS_DirectBranchOrCallTargetAddress(ins);
            FID fid = fn_lookup_by_address(addr);
            INS_InsertCall(ins,
                        IPOINT_BEFORE,
                        (AFUNPTR) fn_call,
                        IARG_CONST_CONTEXT,
                        IARG_UINT32, fid,
                        IARG_BOOL, false,
                        IARG_ADDRINT, inst_addr,
                        IARG_END);
        }
        else {
            INS_InsertCall(ins,
                        IPOINT_BEFORE,
                        (AFUNPTR) fn_icall,
                        IARG_CONST_CONTEXT,
                        IARG_BRANCH_TARGET_ADDR,
                        IARG_BOOL, false,
                        IARG_ADDRINT, inst_addr,
                        IARG_END);
        }
    }

    if (INS_IsIndirectBranchOrCall(ins)) {
        if (!INS_IsCall(ins)) {
            INS_InsertCall(ins,
                    IPOINT_BEFORE,
                    (AFUNPTR) fn_icall,
                    IARG_CONST_CONTEXT,
                    IARG_BRANCH_TARGET_ADDR,
                    IARG_BOOL, true,
                    IARG_ADDRINT, inst_addr,
                    IARG_END);
        }
    }

    if (INS_IsRet(ins)) {
        INS_InsertCall(ins,
                    IPOINT_BEFORE,
                    (AFUNPTR) fn_ret,
                    IARG_CONST_CONTEXT,
                    IARG_END);
    }

    return;
}

VOID Commence() {

    trace_enter();

    /* Init instruction counter */
    counter = 0;
    init = true;
    string _addr, _name;
    if (ifile.is_open()) {
        while (ifile) {
            char m;
            vector<bool> type_param;
            string img_name = read_part(&m);
            if (img_name.empty()) {
                continue;
            }
            ADDRINT img_addr = atol(read_part(&m).c_str());
            string name = read_part(&m);
            type_param.push_back(true);
            FID fid = fn_register(img_name, img_addr, name);
            if (fid != FID_UNKNOWN) {
                fn_registered(fid, 0, type_param);
            }

            type_param.clear();
            img_name = read_part(&m);
            if (img_name.empty()) {
                continue;
            }
            img_addr = atol(read_part(&m).c_str());
            name = read_part(&m);

            float rho = atof(read_part(&m).c_str());
            unsigned char param_pos = atoi(read_part(&m).c_str());

            for (unsigned char pos = 0 ; pos < param_pos ; pos++) {
                type_param.push_back(false);
            }
            type_param.push_back(true);

            if (rho > COUPLE_THRESHOLD) {
                fid = fn_register(img_name, img_addr, name);

                if (fid != FID_UNKNOWN) {
                    fn_registered(fid, param_pos, type_param);
                }
            }

        }
    }

    gettimeofday(&start, NULL);

    trace_leave();

    return;
}

VOID Fini(INT32 code, VOID *v) {

    trace_enter();

    list<param_t *>::reverse_iterator it;

    int depth = 0;
    UINT64 last_date = -1;
    bool is_in = false;

    gettimeofday(&stop, NULL);

    /* First, we log the conversion table fid <-> name */
    log_ftable(ofile);

    it = param->rbegin();

    /* Size of fields of structure */
    ofile << sizeof((*it)->val) << ":";
    ofile << sizeof((*it)->fid) << ":";
    ofile << sizeof((*it)->pos) << ":";
    ofile << sizeof((*it)->counter) << ":";
    ofile << sizeof((*it)->from_main) << endl;

    while (it != param->rend()) {
        param_t *p = *it;
        it++;
        if (last_date != p->counter) {
            if (is_in)
                depth++;
            else
                depth--;
        }
        last_date = p->counter;
        ofile.write((char *) &(p->val), sizeof(p->val));
        ofile.write((char *) &(p->fid), sizeof(p->fid));
        ofile.write((char *) &(p->pos), sizeof(p->pos));
        ofile.write((char *) &(p->counter), sizeof(p->counter));
        ofile.write((char *) &(p->from_main), sizeof(p->from_main));
//        std::cerr << p->val << ":" << p->fid << ":" << p->pos << ":" << p->counter << endl;
    }
    ofile.close();

    trace_leave();

    return;
}

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

    param_addr = (bool **) malloc(NB_FN_MAX * sizeof(bool *));
    is_instrumented = (bool *) calloc(NB_FN_MAX, sizeof(bool));
    nb_p = (unsigned int *) calloc(NB_FN_MAX, sizeof(unsigned int));
    param = new list<param_t *>();

    /* Initialize symbol table code,
       needed for rtn instrumentation */
    PIN_InitSymbols();
    PIN_SetSyntaxIntel();

    if (PIN_Init(argc, argv)) return 1;

    ifile.open(KnobInputFile.Value().c_str());
    ofile.open(KnobOutputFile.Value().c_str());

    // INS_AddInstrumentFunction(Instruction, 0);
    INS_AddInstrumentFunction(Instruction, 0);

    fn_registry_init(NB_FN_MAX);
    vector<bool> unknown_int_idx;
    fn_registered(FID_UNKNOWN, 0, unknown_int_idx);

    /* Register Fini to be called when the
       application exits */
    PIN_AddFiniFunction(Fini, 0);

    PIN_StartProgram();

    return 0;
}

<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-

#ifndef __RD_GAME_STATE_HPP__
#define __RD_GAME_STATE_HPP__

#include "State.hpp"
#include "Hub.hpp"
#include "InputEventListener.hpp"
#include "ImageEventListener.hpp"
#include "NetworkManager.hpp"
#include "ImageManager.hpp"
#include "InputManager.hpp"
#include "MentalMap.hpp"
#include "RobotManager.hpp"
#include "AudioManager.hpp"
#include "ScreenManager.hpp"
#include "Key.hpp"
#include "WindowEvent.hpp"
#include "ProcessorImageEventListener.hpp"
#include "GameScreen.hpp"

namespace rd{

/**
* @ingroup GameStatesLib
*
* @brief Game State
* Behavior:
*  - Manages game interaction (movement, hits, player info updates)
*  - When user presses the Esc key, logs out
*  - It also plays music (important)
*/
class GameState : public State, public ManagerHub,
                  public InputEventListener, public ImageEventListener
{
    public:
        GameState(NetworkManager * networkManager, ImageManager * imageManager,
                  InputManager * inputManager, MentalMap * mentalMap,
                  RobotManager * robotManager, AudioManager * audioManager,
                  ScreenManager * screenManager);
        virtual ~GameState();
        virtual bool setup();
        virtual bool loop();
        virtual bool cleanup();

        //! @brief Returns the internal variable value as condition evaluation result
        virtual int evaluateConditions();

        static const int KILLED;
        static const int EXIT_REQUESTED;

        //-- InputEventListener interface:
        virtual bool onKeyDown(const Key & k);
        virtual bool onKeyUp(const Key & k);
        virtual bool onWindowEvent(const WindowEvent & event);

        //-- ImageEventListener interface
        virtual bool onImageArrived(ImageManager * manager);

        //-- Define keys that trigger actions
        static const Key KEY_EXIT;
        static const Key KEY_SHOOT;
        static const Key KEY_RELOAD;
        static const Key KEY_MOVE_FWD;
        static const Key KEY_MOVE_BACK;
        static const Key KEY_TURN_LEFT;
        static const Key KEY_TURN_RIGHT;
        static const Key KEY_PAN_LEFT;
        static const Key KEY_PAN_RIGHT;
        static const Key KEY_TILT_UP;
        static const Key KEY_TILT_DOWN;

    protected:
        GameScreen screen;
        bool received_exit;
        ProcessorImageEventListener processorImageEventListener;
        Image last_camera_frame;

};

}
#endif // __RD_GAME_STATE_HPP__
<commit_msg>Define GameStatesLib group, add minimal description<commit_after>// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-

#ifndef __RD_GAME_STATE_HPP__
#define __RD_GAME_STATE_HPP__

#include "State.hpp"
#include "Hub.hpp"
#include "InputEventListener.hpp"
#include "ImageEventListener.hpp"
#include "NetworkManager.hpp"
#include "ImageManager.hpp"
#include "InputManager.hpp"
#include "MentalMap.hpp"
#include "RobotManager.hpp"
#include "AudioManager.hpp"
#include "ScreenManager.hpp"
#include "Key.hpp"
#include "WindowEvent.hpp"
#include "ProcessorImageEventListener.hpp"
#include "GameScreen.hpp"

namespace rd{

/**
 * @ingroup rd_libraries
 *
 * \defgroup GameStatesLib
 *
 * @brief The GameStatesLib library contains classes derived from the State class
 */

/**
* @ingroup GameStatesLib
*
* @brief Game State
* Behavior:
*  - Manages game interaction (movement, hits, player info updates)
*  - When user presses the Esc key, logs out
*  - It also plays music (important)
*/
class GameState : public State, public ManagerHub,
                  public InputEventListener, public ImageEventListener
{
    public:
        GameState(NetworkManager * networkManager, ImageManager * imageManager,
                  InputManager * inputManager, MentalMap * mentalMap,
                  RobotManager * robotManager, AudioManager * audioManager,
                  ScreenManager * screenManager);
        virtual ~GameState();
        virtual bool setup();
        virtual bool loop();
        virtual bool cleanup();

        //! @brief Returns the internal variable value as condition evaluation result
        virtual int evaluateConditions();

        static const int KILLED;
        static const int EXIT_REQUESTED;

        //-- InputEventListener interface:
        virtual bool onKeyDown(const Key & k);
        virtual bool onKeyUp(const Key & k);
        virtual bool onWindowEvent(const WindowEvent & event);

        //-- ImageEventListener interface
        virtual bool onImageArrived(ImageManager * manager);

        //-- Define keys that trigger actions
        static const Key KEY_EXIT;
        static const Key KEY_SHOOT;
        static const Key KEY_RELOAD;
        static const Key KEY_MOVE_FWD;
        static const Key KEY_MOVE_BACK;
        static const Key KEY_TURN_LEFT;
        static const Key KEY_TURN_RIGHT;
        static const Key KEY_PAN_LEFT;
        static const Key KEY_PAN_RIGHT;
        static const Key KEY_TILT_UP;
        static const Key KEY_TILT_DOWN;

    protected:
        GameScreen screen;
        bool received_exit;
        ProcessorImageEventListener processorImageEventListener;
        Image last_camera_frame;

};

}
#endif // __RD_GAME_STATE_HPP__
<|endoftext|>


<commit_before>// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
#include "meshoptimizer.h"

#include <assert.h>
#include <string.h>

namespace meshopt
{

static unsigned int murmurHash(const char* key, size_t len, unsigned int h)
{
	const unsigned int m = 0x5bd1e995;
	const int r = 24;

	while (len >= 4)
	{
		unsigned int k = *reinterpret_cast<const unsigned int*>(key);

		k *= m;
		k ^= k >> r;
		k *= m;

		h *= m;
		h ^= k;

		key += 4;
		len -= 4;
	}

	return h;
}

struct VertexHasher
{
	const char* vertices;
	size_t vertex_size;

	size_t operator()(unsigned int index) const
	{
		return murmurHash(vertices + index * vertex_size, vertex_size, 0);
	}

	size_t operator()(unsigned int lhs, unsigned int rhs) const
	{
		return memcmp(vertices + lhs * vertex_size, vertices + rhs * vertex_size, vertex_size) == 0;
	}
};

static size_t hashBuckets(size_t count)
{
	size_t buckets = 1;
	while (buckets < count)
		buckets *= 2;

	return buckets;
}

template <typename T, typename Hash>
static T* hashLookup(T* table, size_t buckets, const Hash& hash, const T& key, const T& empty)
{
	assert(buckets > 0);
	assert((buckets & (buckets - 1)) == 0);

	size_t hashmod = buckets - 1;
	size_t bucket = hash(key) & hashmod;

	for (size_t probe = 0; probe <= hashmod; ++probe)
	{
		T& item = table[bucket];

		if (item == empty)
			return &item;

		if (hash(item, key))
			return &item;

		// hash collision, quadratic probing
		bucket = (bucket + probe + 1) & hashmod;
	}

	assert(false && "Hash table is full");
	return 0;
}

} // namespace meshopt

size_t meshopt_generateVertexRemap(unsigned int* destination, const unsigned int* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size)
{
	using namespace meshopt;

	assert(indices || index_count == vertex_count);
	assert(index_count % 3 == 0);
	assert(vertex_size > 0 && vertex_size <= 256);

	memset(destination, -1, vertex_count * sizeof(unsigned int));

	VertexHasher hasher = {static_cast<const char*>(vertices), vertex_size};

	meshopt_Buffer<unsigned int> table(hashBuckets(vertex_count));
	memset(table.data, -1, table.size * sizeof(unsigned int));

	unsigned int next_vertex = 0;

	for (size_t i = 0; i < index_count; ++i)
	{
		unsigned int index = indices ? indices[i] : unsigned(i);
		assert(index < vertex_count);

		if (destination[index] == ~0u)
		{
			unsigned int* entry = hashLookup(table.data, table.size, hasher, index, ~0u);

			if (*entry == ~0u)
			{
				*entry = index;

				destination[index] = next_vertex++;
			}
			else
			{
				assert(destination[*entry] != ~0u);

				destination[index] = destination[*entry];
			}
		}
	}

	assert(next_vertex <= vertex_count);

	return next_vertex;
}

void meshopt_remapVertexBuffer(void* destination, const void* vertices, size_t vertex_count, size_t vertex_size, const unsigned int* remap)
{
	assert(vertex_size > 0 && vertex_size <= 256);

	// support in-place remap
	meshopt_Buffer<char> vertices_copy;

	if (destination == vertices)
	{
		vertices_copy.allocate(vertex_count * vertex_size);
		memcpy(vertices_copy.data, vertices, vertex_count * vertex_size);
		vertices = vertices_copy.data;
	}

	for (size_t i = 0; i < vertex_count; ++i)
	{
		if (remap[i] != ~0u)
		{
			assert(remap[i] < vertex_count);

			memcpy(static_cast<char*>(destination) + remap[i] * vertex_size, static_cast<const char*>(vertices) + i * vertex_size, vertex_size);
		}
	}
}

void meshopt_remapIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const unsigned int* remap)
{
	assert(index_count % 3 == 0);

	for (size_t i = 0; i < index_count; ++i)
	{
		unsigned int index = indices ? indices[i] : unsigned(i);
		assert(remap[index] != ~0u);

		destination[i] = remap[index];
	}
}
<commit_msg>indexgenerator: Refactor hasher interface<commit_after>// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
#include "meshoptimizer.h"

#include <assert.h>
#include <string.h>

namespace meshopt
{

struct VertexHasher
{
	const char* vertices;
	size_t vertex_size;

	size_t hash(unsigned int index) const
	{
		// MurmurHash2
		const unsigned int m = 0x5bd1e995;
		const int r = 24;

		unsigned int h = 0;
		const char* key = vertices + index * vertex_size;
		size_t len = vertex_size;

		while (len >= 4)
		{
			unsigned int k = *reinterpret_cast<const unsigned int*>(key);

			k *= m;
			k ^= k >> r;
			k *= m;

			h *= m;
			h ^= k;

			key += 4;
			len -= 4;
		}

		return h;
	}

	bool equal(unsigned int lhs, unsigned int rhs) const
	{
		return memcmp(vertices + lhs * vertex_size, vertices + rhs * vertex_size, vertex_size) == 0;
	}
};

static size_t hashBuckets(size_t count)
{
	size_t buckets = 1;
	while (buckets < count)
		buckets *= 2;

	return buckets;
}

template <typename T, typename Hash>
static T* hashLookup(T* table, size_t buckets, const Hash& hash, const T& key, const T& empty)
{
	assert(buckets > 0);
	assert((buckets & (buckets - 1)) == 0);

	size_t hashmod = buckets - 1;
	size_t bucket = hash.hash(key) & hashmod;

	for (size_t probe = 0; probe <= hashmod; ++probe)
	{
		T& item = table[bucket];

		if (item == empty)
			return &item;

		if (hash.equal(item, key))
			return &item;

		// hash collision, quadratic probing
		bucket = (bucket + probe + 1) & hashmod;
	}

	assert(false && "Hash table is full");
	return 0;
}

} // namespace meshopt

size_t meshopt_generateVertexRemap(unsigned int* destination, const unsigned int* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size)
{
	using namespace meshopt;

	assert(indices || index_count == vertex_count);
	assert(index_count % 3 == 0);
	assert(vertex_size > 0 && vertex_size <= 256);

	memset(destination, -1, vertex_count * sizeof(unsigned int));

	VertexHasher hasher = {static_cast<const char*>(vertices), vertex_size};

	meshopt_Buffer<unsigned int> table(hashBuckets(vertex_count));
	memset(table.data, -1, table.size * sizeof(unsigned int));

	unsigned int next_vertex = 0;

	for (size_t i = 0; i < index_count; ++i)
	{
		unsigned int index = indices ? indices[i] : unsigned(i);
		assert(index < vertex_count);

		if (destination[index] == ~0u)
		{
			unsigned int* entry = hashLookup(table.data, table.size, hasher, index, ~0u);

			if (*entry == ~0u)
			{
				*entry = index;

				destination[index] = next_vertex++;
			}
			else
			{
				assert(destination[*entry] != ~0u);

				destination[index] = destination[*entry];
			}
		}
	}

	assert(next_vertex <= vertex_count);

	return next_vertex;
}

void meshopt_remapVertexBuffer(void* destination, const void* vertices, size_t vertex_count, size_t vertex_size, const unsigned int* remap)
{
	assert(vertex_size > 0 && vertex_size <= 256);

	// support in-place remap
	meshopt_Buffer<char> vertices_copy;

	if (destination == vertices)
	{
		vertices_copy.allocate(vertex_count * vertex_size);
		memcpy(vertices_copy.data, vertices, vertex_count * vertex_size);
		vertices = vertices_copy.data;
	}

	for (size_t i = 0; i < vertex_count; ++i)
	{
		if (remap[i] != ~0u)
		{
			assert(remap[i] < vertex_count);

			memcpy(static_cast<char*>(destination) + remap[i] * vertex_size, static_cast<const char*>(vertices) + i * vertex_size, vertex_size);
		}
	}
}

void meshopt_remapIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const unsigned int* remap)
{
	assert(index_count % 3 == 0);

	for (size_t i = 0; i < index_count; ++i)
	{
		unsigned int index = indices ? indices[i] : unsigned(i);
		assert(remap[index] != ~0u);

		destination[i] = remap[index];
	}
}
<|endoftext|>


<commit_before>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id: postgisfs.cc 66 2004-11-16 09:25:15Z artem $

#include "postgis.hh"

PostgisFeatureset::PostgisFeatureset(const ref_ptr<ResultSet>& rs,const CoordTransform& t)
    : rs_(rs),
      t_(t),
      totalGeomSize_(0),
      count_(0)
{
}

Feature* PostgisFeatureset::next()
{
    VectorFeature *feature=0;
    if (rs_->next())
    {
        // read gid,srid,geometry and create feature
        int id=atoi(rs_->getValue("gid"));
        int size=rs_->getFieldLength("geom");
        const char *data=rs_->getValue("geom");
        geometry_ptr geom=geometry_utils::from_wkb(data,size,-1);

        if (geom)
        {
            feature=new VectorFeature(id,geom);
            totalGeomSize_+=size;
            ++count_;
        }
    }
    else
    {
        rs_->close();
        std::cout << "totalGeomSize="<<totalGeomSize_<<" bytes"<<std::endl;
        std::cout << "count="<<count_<<std::endl;
    }
    return feature;
}

PostgisFeatureset::~PostgisFeatureset()
{
    rs_->close();
}
<commit_msg>added $Id$ substitution<commit_after>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id$

#include "postgis.hh"

PostgisFeatureset::PostgisFeatureset(const ref_ptr<ResultSet>& rs,const CoordTransform& t)
    : rs_(rs),
      t_(t),
      totalGeomSize_(0),
      count_(0)
{
}

Feature* PostgisFeatureset::next()
{
    VectorFeature *feature=0;
    if (rs_->next())
    {
        // read gid,srid,geometry and create feature
        int id=atoi(rs_->getValue("gid"));
        int size=rs_->getFieldLength("geom");
        const char *data=rs_->getValue("geom");
        geometry_ptr geom=geometry_utils::from_wkb(data,size,-1);

        if (geom)
        {
            feature=new VectorFeature(id,geom);
            totalGeomSize_+=size;
            ++count_;
        }
    }
    else
    {
        rs_->close();
        std::cout << "totalGeomSize="<<totalGeomSize_<<" bytes"<<std::endl;
        std::cout << "count="<<count_<<std::endl;
    }
    return feature;
}

PostgisFeatureset::~PostgisFeatureset()
{
    rs_->close();
}
<|endoftext|>