<commit_before>//
//  AY-3-8910.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 14/10/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "AY38910.hpp"

using namespace GI::AY38910;

AY38910::AY38910() :
		selected_register_(0),
		tone_counters_{0, 0, 0}, tone_periods_{0, 0, 0}, tone_outputs_{0, 0, 0},
		noise_shift_register_(0xffff), noise_period_(0), noise_counter_(0), noise_output_(0),
		envelope_divider_(0), envelope_period_(0), envelope_position_(0),
		master_divider_(0),
		output_registers_{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		port_handler_(nullptr) {
	output_registers_[8] = output_registers_[9] = output_registers_[10] = 0;

	// set up envelope lookup tables
	for(int c = 0; c < 16; c++) {
		for(int p = 0; p < 32; p++) {
			switch(c) {
				case 0: case 1: case 2: case 3: case 9:
					envelope_shapes_[c][p] = (p < 16) ? (p^0xf) : 0;
					envelope_overflow_masks_[c] = 0x1f;
				break;
				case 4: case 5: case 6: case 7: case 15:
					envelope_shapes_[c][p] = (p < 16) ? p : 0;
					envelope_overflow_masks_[c] = 0x1f;
				break;

				case 8:
					envelope_shapes_[c][p] = (p & 0xf) ^ 0xf;
					envelope_overflow_masks_[c] = 0x00;
				break;
				case 12:
					envelope_shapes_[c][p] = (p & 0xf);
					envelope_overflow_masks_[c] = 0x00;
				break;

				case 10:
					envelope_shapes_[c][p] = (p & 0xf) ^ ((p < 16) ? 0xf : 0x0);
					envelope_overflow_masks_[c] = 0x00;
				break;
				case 14:
					envelope_shapes_[c][p] = (p & 0xf) ^ ((p < 16) ? 0x0 : 0xf);
					envelope_overflow_masks_[c] = 0x00;
				break;

				case 11:
					envelope_shapes_[c][p] = (p < 16) ? (p^0xf) : 0xf;
					envelope_overflow_masks_[c] = 0x1f;
				break;
				case 13:
					envelope_shapes_[c][p] = (p < 16) ? p : 0xf;
					envelope_overflow_masks_[c] = 0x1f;
				break;
			}
		}
	}

	// set up volume lookup table
	float max_volume = 8192;
	float root_two = sqrtf(2.0f);
	for(int v = 0; v < 16; v++) {
		volumes_[v] = (int)(max_volume / powf(root_two, (float)(v ^ 0xf)));
	}
	volumes_[0] = 0;
}

void AY38910::set_clock_rate(double clock_rate) {
	set_input_rate((float)clock_rate);
}

void AY38910::get_samples(unsigned int number_of_samples, int16_t *target) {
	unsigned int c = 0;
	while((master_divider_&7) && c < number_of_samples) {
		target[c] = output_volume_;
		master_divider_++;
		c++;
	}

	while(c < number_of_samples) {
#define step_channel(c) \
	if(tone_counters_[c]) tone_counters_[c]--;\
	else {\
		tone_outputs_[c] ^= 1;\
		tone_counters_[c] = tone_periods_[c];\
	}

		// update the tone channels
		step_channel(0);
		step_channel(1);
		step_channel(2);

#undef step_channel

		// ... the noise generator. This recomputes the new bit repeatedly but harmlessly, only shifting
		// it into the official 17 upon divider underflow.
		if(noise_counter_) noise_counter_--;
		else {
			noise_counter_ = noise_period_;
			noise_output_ ^= noise_shift_register_&1;
			noise_shift_register_ |= ((noise_shift_register_ ^ (noise_shift_register_ >> 3))&1) << 17;
			noise_shift_register_ >>= 1;
		}

		// ... and the envelope generator. Table based for pattern lookup, with a 'refill' step — a way of
		// implementing non-repeating patterns by locking them to table position 0x1f.
		if(envelope_divider_) envelope_divider_--;
		else {
			envelope_divider_ = envelope_period_;
			envelope_position_ ++;
			if(envelope_position_ == 32) envelope_position_ = envelope_overflow_masks_[output_registers_[13]];
		}

		evaluate_output_volume();

		for(int ic = 0; ic < 8 && c < number_of_samples; ic++) {
			target[c] = output_volume_;
			c++;
			master_divider_++;
		}
	}

	master_divider_ &= 7;
}

void AY38910::evaluate_output_volume() {
	int envelope_volume = envelope_shapes_[output_registers_[13]][envelope_position_];

	// The output level for a channel is:
	//	1 if neither tone nor noise is enabled;
	//	0 if either tone or noise is enabled and its value is low.
	// The tone/noise enable bits use inverse logic — 0 = on, 1 = off — permitting the OR logic below.
#define tone_level(c, tone_bit)		(tone_outputs_[c] | (output_registers_[7] >> tone_bit))
#define noise_level(c, noise_bit)	(noise_output_ | (output_registers_[7] >> noise_bit))

#define level(c, tone_bit, noise_bit)	tone_level(c, tone_bit) & noise_level(c, noise_bit) & 1
	const int channel_levels[3] = {
		level(0, 0, 3),
		level(1, 1, 4),
		level(2, 2, 5),
	};
#undef level

		// Channel volume is a simple selection: if the bit at 0x10 is set, use the envelope volume; otherwise use the lower four bits
#define channel_volume(c)	\
	((output_registers_[c] >> 4)&1) * envelope_volume + (((output_registers_[c] >> 4)&1)^1) * (output_registers_[c]&0xf)

	const int volumes[3] = {
		channel_volume(8),
		channel_volume(9),
		channel_volume(10)
	};
#undef channel_volume

	// Mix additively.
	output_volume_ = (int16_t)(
		volumes_[volumes[0]] * channel_levels[0] +
		volumes_[volumes[1]] * channel_levels[1] +
		volumes_[volumes[2]] * channel_levels[2]
	);
}

#pragma mark - Register manipulation

void AY38910::select_register(uint8_t r) {
	selected_register_ = r;
}

void AY38910::set_register_value(uint8_t value) {
	if(selected_register_ > 15) return;
	registers_[selected_register_] = value;
	if(selected_register_ < 14) {
		int selected_register = selected_register_;
		enqueue([=] () {
			uint8_t masked_value = value;
			switch(selected_register) {
				case 0: case 2: case 4:
				case 1: case 3: case 5: {
					int channel = selected_register >> 1;

					if(selected_register & 1)
						tone_periods_[channel] = (tone_periods_[channel] & 0xff) | (uint16_t)((value&0xf) << 8);
					else
						tone_periods_[channel] = (tone_periods_[channel] & ~0xff) | value;
				}
				break;

				case 6:
					noise_period_ = value & 0x1f;
				break;

				case 11:
					envelope_period_ = (envelope_period_ & ~0xff) | value;
				break;

				case 12:
					envelope_period_ = (envelope_period_ & 0xff) | (int)(value << 8);
				break;

				case 13:
					masked_value &= 0xf;
					envelope_position_ = 0;
				break;
			}
			output_registers_[selected_register] = masked_value;
			evaluate_output_volume();
		});
	} else {
		if(port_handler_) port_handler_->set_port_output(value == 15, value);
	}
}

uint8_t AY38910::get_register_value() {
	// This table ensures that bits that aren't defined within the AY are returned as 1s
	// when read. I can't find documentation on this and don't have a machine to test, so
	// this is provisionally a guess. TODO: investigate.
	const uint8_t register_masks[16] = {
		0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0xe0, 0x00,
		0xe0, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0x00, 0x00
	};

	if(selected_register_ > 15) return 0xff;
	switch(selected_register_) {
		default:	return registers_[selected_register_] & ~register_masks[selected_register_];
		case 14:	return (registers_[0x7] & 0x40) ? registers_[14] : port_inputs_[0];
		case 15:	return (registers_[0x7] & 0x80) ? registers_[15] : port_inputs_[1];
	}
}

#pragma mark - Port handling

uint8_t AY38910::get_port_output(bool port_b) {
	return registers_[port_b ? 15 : 14];
}

#pragma mark - Bus handling

void AY38910::set_port_handler(PortHandler *handler) {
	port_handler_ = handler;
}

void AY38910::set_data_input(uint8_t r) {
	data_input_ = r;
	update_bus();
}

uint8_t AY38910::get_data_output() {
	if(control_state_ == Read && selected_register_ >= 14) {
		if(port_handler_) {
			return port_handler_->get_port_input(selected_register_ == 15);
		} else {
			return 0xff;
		}
	}
	return data_output_;
}

void AY38910::set_control_lines(ControlLines control_lines) {
	switch((int)control_lines) {
		default:					control_state_ = Inactive;		break;

		case (int)(BDIR | BC2 | BC1):
		case BDIR:
		case BC1:					control_state_ = LatchAddress;	break;

		case (int)(BC2 | BC1):		control_state_ = Read;			break;
		case (int)(BDIR | BC2):		control_state_ = Write;			break;
	}

	update_bus();
}

void AY38910::update_bus() {
	switch(control_state_) {
		default: break;
		case LatchAddress:	select_register(data_input_);			break;
		case Write:			set_register_value(data_input_);		break;
		case Read:			data_output_ = get_register_value();	break;
	}
}
<commit_msg>Quick fix: supply the port being written to correctly.<commit_after>//
//  AY-3-8910.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 14/10/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "AY38910.hpp"

using namespace GI::AY38910;

AY38910::AY38910() :
		selected_register_(0),
		tone_counters_{0, 0, 0}, tone_periods_{0, 0, 0}, tone_outputs_{0, 0, 0},
		noise_shift_register_(0xffff), noise_period_(0), noise_counter_(0), noise_output_(0),
		envelope_divider_(0), envelope_period_(0), envelope_position_(0),
		master_divider_(0),
		output_registers_{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		port_handler_(nullptr) {
	output_registers_[8] = output_registers_[9] = output_registers_[10] = 0;

	// set up envelope lookup tables
	for(int c = 0; c < 16; c++) {
		for(int p = 0; p < 32; p++) {
			switch(c) {
				case 0: case 1: case 2: case 3: case 9:
					envelope_shapes_[c][p] = (p < 16) ? (p^0xf) : 0;
					envelope_overflow_masks_[c] = 0x1f;
				break;
				case 4: case 5: case 6: case 7: case 15:
					envelope_shapes_[c][p] = (p < 16) ? p : 0;
					envelope_overflow_masks_[c] = 0x1f;
				break;

				case 8:
					envelope_shapes_[c][p] = (p & 0xf) ^ 0xf;
					envelope_overflow_masks_[c] = 0x00;
				break;
				case 12:
					envelope_shapes_[c][p] = (p & 0xf);
					envelope_overflow_masks_[c] = 0x00;
				break;

				case 10:
					envelope_shapes_[c][p] = (p & 0xf) ^ ((p < 16) ? 0xf : 0x0);
					envelope_overflow_masks_[c] = 0x00;
				break;
				case 14:
					envelope_shapes_[c][p] = (p & 0xf) ^ ((p < 16) ? 0x0 : 0xf);
					envelope_overflow_masks_[c] = 0x00;
				break;

				case 11:
					envelope_shapes_[c][p] = (p < 16) ? (p^0xf) : 0xf;
					envelope_overflow_masks_[c] = 0x1f;
				break;
				case 13:
					envelope_shapes_[c][p] = (p < 16) ? p : 0xf;
					envelope_overflow_masks_[c] = 0x1f;
				break;
			}
		}
	}

	// set up volume lookup table
	float max_volume = 8192;
	float root_two = sqrtf(2.0f);
	for(int v = 0; v < 16; v++) {
		volumes_[v] = (int)(max_volume / powf(root_two, (float)(v ^ 0xf)));
	}
	volumes_[0] = 0;
}

void AY38910::set_clock_rate(double clock_rate) {
	set_input_rate((float)clock_rate);
}

void AY38910::get_samples(unsigned int number_of_samples, int16_t *target) {
	unsigned int c = 0;
	while((master_divider_&7) && c < number_of_samples) {
		target[c] = output_volume_;
		master_divider_++;
		c++;
	}

	while(c < number_of_samples) {
#define step_channel(c) \
	if(tone_counters_[c]) tone_counters_[c]--;\
	else {\
		tone_outputs_[c] ^= 1;\
		tone_counters_[c] = tone_periods_[c];\
	}

		// update the tone channels
		step_channel(0);
		step_channel(1);
		step_channel(2);

#undef step_channel

		// ... the noise generator. This recomputes the new bit repeatedly but harmlessly, only shifting
		// it into the official 17 upon divider underflow.
		if(noise_counter_) noise_counter_--;
		else {
			noise_counter_ = noise_period_;
			noise_output_ ^= noise_shift_register_&1;
			noise_shift_register_ |= ((noise_shift_register_ ^ (noise_shift_register_ >> 3))&1) << 17;
			noise_shift_register_ >>= 1;
		}

		// ... and the envelope generator. Table based for pattern lookup, with a 'refill' step — a way of
		// implementing non-repeating patterns by locking them to table position 0x1f.
		if(envelope_divider_) envelope_divider_--;
		else {
			envelope_divider_ = envelope_period_;
			envelope_position_ ++;
			if(envelope_position_ == 32) envelope_position_ = envelope_overflow_masks_[output_registers_[13]];
		}

		evaluate_output_volume();

		for(int ic = 0; ic < 8 && c < number_of_samples; ic++) {
			target[c] = output_volume_;
			c++;
			master_divider_++;
		}
	}

	master_divider_ &= 7;
}

void AY38910::evaluate_output_volume() {
	int envelope_volume = envelope_shapes_[output_registers_[13]][envelope_position_];

	// The output level for a channel is:
	//	1 if neither tone nor noise is enabled;
	//	0 if either tone or noise is enabled and its value is low.
	// The tone/noise enable bits use inverse logic — 0 = on, 1 = off — permitting the OR logic below.
#define tone_level(c, tone_bit)		(tone_outputs_[c] | (output_registers_[7] >> tone_bit))
#define noise_level(c, noise_bit)	(noise_output_ | (output_registers_[7] >> noise_bit))

#define level(c, tone_bit, noise_bit)	tone_level(c, tone_bit) & noise_level(c, noise_bit) & 1
	const int channel_levels[3] = {
		level(0, 0, 3),
		level(1, 1, 4),
		level(2, 2, 5),
	};
#undef level

		// Channel volume is a simple selection: if the bit at 0x10 is set, use the envelope volume; otherwise use the lower four bits
#define channel_volume(c)	\
	((output_registers_[c] >> 4)&1) * envelope_volume + (((output_registers_[c] >> 4)&1)^1) * (output_registers_[c]&0xf)

	const int volumes[3] = {
		channel_volume(8),
		channel_volume(9),
		channel_volume(10)
	};
#undef channel_volume

	// Mix additively.
	output_volume_ = (int16_t)(
		volumes_[volumes[0]] * channel_levels[0] +
		volumes_[volumes[1]] * channel_levels[1] +
		volumes_[volumes[2]] * channel_levels[2]
	);
}

#pragma mark - Register manipulation

void AY38910::select_register(uint8_t r) {
	selected_register_ = r;
}

void AY38910::set_register_value(uint8_t value) {
	if(selected_register_ > 15) return;
	registers_[selected_register_] = value;
	if(selected_register_ < 14) {
		int selected_register = selected_register_;
		enqueue([=] () {
			uint8_t masked_value = value;
			switch(selected_register) {
				case 0: case 2: case 4:
				case 1: case 3: case 5: {
					int channel = selected_register >> 1;

					if(selected_register & 1)
						tone_periods_[channel] = (tone_periods_[channel] & 0xff) | (uint16_t)((value&0xf) << 8);
					else
						tone_periods_[channel] = (tone_periods_[channel] & ~0xff) | value;
				}
				break;

				case 6:
					noise_period_ = value & 0x1f;
				break;

				case 11:
					envelope_period_ = (envelope_period_ & ~0xff) | value;
				break;

				case 12:
					envelope_period_ = (envelope_period_ & 0xff) | (int)(value << 8);
				break;

				case 13:
					masked_value &= 0xf;
					envelope_position_ = 0;
				break;
			}
			output_registers_[selected_register] = masked_value;
			evaluate_output_volume();
		});
	} else {
		if(port_handler_) port_handler_->set_port_output(selected_register_ == 15, value);
	}
}

uint8_t AY38910::get_register_value() {
	// This table ensures that bits that aren't defined within the AY are returned as 1s
	// when read. I can't find documentation on this and don't have a machine to test, so
	// this is provisionally a guess. TODO: investigate.
	const uint8_t register_masks[16] = {
		0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0xe0, 0x00,
		0xe0, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0x00, 0x00
	};

	if(selected_register_ > 15) return 0xff;
	switch(selected_register_) {
		default:	return registers_[selected_register_] & ~register_masks[selected_register_];
		case 14:	return (registers_[0x7] & 0x40) ? registers_[14] : port_inputs_[0];
		case 15:	return (registers_[0x7] & 0x80) ? registers_[15] : port_inputs_[1];
	}
}

#pragma mark - Port handling

uint8_t AY38910::get_port_output(bool port_b) {
	return registers_[port_b ? 15 : 14];
}

#pragma mark - Bus handling

void AY38910::set_port_handler(PortHandler *handler) {
	port_handler_ = handler;
}

void AY38910::set_data_input(uint8_t r) {
	data_input_ = r;
	update_bus();
}

uint8_t AY38910::get_data_output() {
	if(control_state_ == Read && selected_register_ >= 14) {
		if(port_handler_) {
			return port_handler_->get_port_input(selected_register_ == 15);
		} else {
			return 0xff;
		}
	}
	return data_output_;
}

void AY38910::set_control_lines(ControlLines control_lines) {
	switch((int)control_lines) {
		default:					control_state_ = Inactive;		break;

		case (int)(BDIR | BC2 | BC1):
		case BDIR:
		case BC1:					control_state_ = LatchAddress;	break;

		case (int)(BC2 | BC1):		control_state_ = Read;			break;
		case (int)(BDIR | BC2):		control_state_ = Write;			break;
	}

	update_bus();
}

void AY38910::update_bus() {
	switch(control_state_) {
		default: break;
		case LatchAddress:	select_register(data_input_);			break;
		case Write:			set_register_value(data_input_);		break;
		case Read:			data_output_ = get_register_value();	break;
	}
}
<|endoftext|>


<commit_before>/*
    open source routing machine
    Copyright (C) Dennis Luxen, 2010

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 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 Affero 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
or see http://www.gnu.org/licenses/agpl.txt.
 */

#include "OSRM.h"

OSRM::OSRM(const char * server_ini_path) {
    BaseConfiguration serverConfig(server_ini_path);
    QueryObjectsStorage * objects = new QueryObjectsStorage(
        serverConfig.GetParameter("hsgrData"),
        serverConfig.GetParameter("ramIndex"),
        serverConfig.GetParameter("fileIndex"),
        serverConfig.GetParameter("nodesData"),
        serverConfig.GetParameter("edgesData"),
        serverConfig.GetParameter("namesData"),
        serverConfig.GetParameter("timestamp")
    );

    RegisterPlugin(new HelloWorldPlugin());
    RegisterPlugin(new LocatePlugin(objects));
    RegisterPlugin(new NearestPlugin(objects));
    RegisterPlugin(new TimestampPlugin(objects));
    RegisterPlugin(new ViaRoutePlugin(objects));
}

OSRM::~OSRM() {
    BOOST_FOREACH(PluginMap::value_type plugin_pointer, pluginMap) {
        delete plugin_pointer.second;
    }
}

void OSRM::RegisterPlugin(BasePlugin * plugin) {
    std::cout << "[plugin] " << plugin->GetDescriptor() << std::endl;
    pluginMap[plugin->GetDescriptor()] = plugin;
}

void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
    PluginMap::const_iterator iter = pluginMap.find(route_parameters.service);
    if(pluginMap.end() != iter) {
        reply.status = http::Reply::ok;
        iter->second->HandleRequest(route_parameters, reply );
    } else {
        reply = http::Reply::stockReply(http::Reply::badRequest);
    }
}
<commit_msg>Fix non-critical memory leak<commit_after>/*
    open source routing machine
    Copyright (C) Dennis Luxen, 2010

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 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 Affero 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
or see http://www.gnu.org/licenses/agpl.txt.
 */

#include "OSRM.h"

OSRM::OSRM(const char * server_ini_path) {
    BaseConfiguration serverConfig(server_ini_path);
    QueryObjectsStorage * objects = new QueryObjectsStorage(
        serverConfig.GetParameter("hsgrData"),
        serverConfig.GetParameter("ramIndex"),
        serverConfig.GetParameter("fileIndex"),
        serverConfig.GetParameter("nodesData"),
        serverConfig.GetParameter("edgesData"),
        serverConfig.GetParameter("namesData"),
        serverConfig.GetParameter("timestamp")
    );

    RegisterPlugin(new HelloWorldPlugin());
    RegisterPlugin(new LocatePlugin(objects));
    RegisterPlugin(new NearestPlugin(objects));
    RegisterPlugin(new TimestampPlugin(objects));
    RegisterPlugin(new ViaRoutePlugin(objects));
}

OSRM::~OSRM() {
    BOOST_FOREACH(PluginMap::value_type plugin_pointer, pluginMap) {
        delete plugin_pointer.second;
    }
    delete objects;
}

void OSRM::RegisterPlugin(BasePlugin * plugin) {
    std::cout << "[plugin] " << plugin->GetDescriptor() << std::endl;
    pluginMap[plugin->GetDescriptor()] = plugin;
}

void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
    PluginMap::const_iterator iter = pluginMap.find(route_parameters.service);
    if(pluginMap.end() != iter) {
        reply.status = http::Reply::ok;
        iter->second->HandleRequest(route_parameters, reply );
    } else {
        reply = http::Reply::stockReply(http::Reply::badRequest);
    }
}
<|endoftext|>


<commit_before>#include "Resources.h"
#include "Engine.h"
#include "Common.h"
#include <cstdio>

// Memory leak debug
#if defined(_MSC_VER) && defined(_WIN32) && defined(_DEBUG)
    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>

    #ifndef DBG_NEW
        #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
        #define new DBG_NEW
    #endif
#endif

int main(int argv, char* argc[])
{
#if defined(_MSC_VER) && defined(_WIN32) && defined(_DEBUG)
    // Memory leak debug
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
#endif

    init_logging(argv, argc);

    try
    {
        // Run the game, then clean up
        Engine engine;
        engine.run();
    }
    catch (const std::runtime_error& e)
    {
        LOG(FATAL) << e.what();
        errorMessage(e.what());
    }

    Magnaut::cleanup();

    LOG(INFO) << "Exiting Magnaut";

    return 0;
}<commit_msg>Clarified comments.<commit_after>#include "Resources.h"
#include "Engine.h"
#include "Common.h"
#include <cstdio>

// Memory leak debug
#if defined(_MSC_VER) && defined(_WIN32) && defined(_DEBUG)
    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>

    #ifndef DBG_NEW
        #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
        #define new DBG_NEW
    #endif
#endif

int main(int argv, char* argc[])
{
#if defined(_MSC_VER) && defined(_WIN32) && defined(_DEBUG)
    // Memory leak debug
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
#endif

    init_logging(argv, argc);

    try
    {
        // Run the game
        Engine engine;
        engine.run();
    }
    catch (const std::runtime_error& e)
    {
        LOG(FATAL) << e.what();
        errorMessage(e.what());
    }

    // Clean up global resources
    Magnaut::cleanup();

    LOG(INFO) << "Exiting Magnaut";

    return 0;
}<|endoftext|>


<commit_before>#include "test.h"
#include "test-stats.h"

#include "grok/context.h"
#include "input/input-stream.h"
#include "input/readline.h"
#include "lexer/lexer.h"
#include "object/jsbasicobject.h"
#include "object/argument.h"
#include "object/function.h"
#include "parser/parser.h"
#include "vm/codegen.h"
#include "vm/context.h"
#include "vm/instruction-list.h"
#include "vm/printer.h"
#include "vm/vm.h"
#include "common/colors.h"

#include <iostream>
#include <cerrno>
#include <chrono>
#include <algorithm>
#include <boost/filesystem.hpp>

using namespace grok;
using namespace grok::vm;
using namespace grok::parser;
using namespace grok::input;

namespace grok {
namespace test {

template<typename Diff>
void log_progress(Diff d)
{
    std::cout <<
    (double)std::chrono::duration_cast
        <std::chrono::microseconds>(d).count() / (double)1000
              << "ms" << std::flush;
}

std::shared_ptr<grok::obj::Handle>
    AssertEqual(std::shared_ptr<grok::obj::Argument> args)
{
    auto rhs = args->GetProperty("rhs")->as<grok::obj::JSObject>();
    auto lhs = args->GetProperty("lhs")->as<grok::obj::JSObject>();

    if ((rhs->GetType() == grok::obj::ObjectType::_double
        || rhs->GetType() == grok::obj::ObjectType::_number)
        && (lhs->GetType() == grok::obj::ObjectType::_double
        || lhs->GetType() == grok::obj::ObjectType::_number)
        && (rhs->ToString() == lhs->ToString())
        && (rhs->AsString() == lhs->AsString()))
        return grok::obj::CreateUndefinedObject();

    if (rhs->GetType() != lhs->GetType()) {
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " types were not same");
    }
    if (rhs->ToString() != lhs->ToString())
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " toString's were not same");

    if (rhs->AsString() != lhs->AsString())
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " asString's were not same");

    return grok::obj::CreateUndefinedObject();
}

std::shared_ptr<grok::obj::Handle>
    AssertNotEqual(std::shared_ptr<grok::obj::Argument> args)
{
    auto rhs = args->GetProperty("rhs")->as<grok::obj::JSObject>();
    auto lhs = args->GetProperty("lhs")->as<grok::obj::JSObject>();

    if (rhs->GetType() == lhs->GetType()) {
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());
    }
    if (rhs->ToString() == lhs->ToString())
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());

    if (rhs->AsString() == lhs->AsString())
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());

    return grok::obj::CreateUndefinedObject();
}

Test &Test::Prepare(std::string file)
{
    file_ = file;
    expected_result_file_ = file;
    expected_result_file_.resize(file.size() - 3);
    expected_result_file_ += ".txt";

    grok::vm::InitializeVMContext();
    auto v = grok::vm::GetGlobalVMContext()->GetVStore();
    auto func = grok::obj::CreateFunction(AssertEqual);
    func->as<grok::obj::Function>()->SetParams({ "lhs", "rhs" });
    v->StoreValue("assert_equal", func);

    func = grok::obj::CreateFunction(AssertNotEqual);
    func->as<grok::obj::Function>()->SetParams({ "lhs", "rhs" });
    v->StoreValue("assert_not_equal", func);
    return *this;
}

std::string ReadFile(std::string file_)
{
    std::string v;
    if (FILE *fp = fopen(file_.c_str(), "r"))
    {
        char buf[1024];
        while (size_t len = fread(buf, 1, sizeof(buf), fp))
            v.insert(v.end(), buf, buf + len);
        fclose(fp);
    } else {
        std::cout << "fatal: " << file_ << ": "
            << strerror(errno);
        throw std::runtime_error("");
    }
    return v;
}

bool Test::CheckResult(std::string result)
{
    std::string expected_result = ReadFile(expected_result_file_);

    return expected_result == result;
}

bool Test::StartTest(int32_t flags)
{
    std::string file = ReadFile(file_);

    auto lex = std::make_unique<Lexer>(file);

    GrokParser parser{ std::move(lex) };
    if (!parser.ParseExpression())
        return !(flags & f_syntax_errors); // test failed

    auto ast = parser.ParsedAST();

    std::shared_ptr<InstructionList> IR;
    try {
        CodeGenerator codegen;
        codegen.Generate(ast.get());

        IR = codegen.GetIR();
        if (!IR || IR->size() == 0)
            return true;

    } catch (std::exception &e) {
        if (f_print_reason & flags)
            std::cout << e.what() << std::endl;
        return !(flags & f_ir_errors);
    }

    try {
        auto vm = grok::vm::CreateVM(grok::vm::GetGlobalVMContext());
        vm->SetCounters(IR->begin(), IR->end());

        vm->Run();

        Value result = vm->GetResult();
        auto obj = result.O->as<grok::obj::JSObject>();

        std::string res = obj->AsString();

        grok::GetContext()->RunIO();
        return true;
    } catch (std::exception &e) {
        if (flags & f_print_reason)
            std::cout << e.what() << std::endl;
        return !(flags & f_vm_errors);
    }
}

}
}

int main(int argc, char *argv[])
{
    grok::InitializeContext();
    int test_id = -1;

    if (argc >= 2) {
        if (std::string(argv[1]) == "-h" ||
            std::string(argv[1]) == "--help") {
            std::cerr << "Usage: " << argv[0] << " <test_number>" << std::endl;
            return 1;
        } else {
            try {
                test_id = std::stoi(argv[1]);
            } catch (std::exception &e) {
                std::cerr << "bad number" << std::endl;
                return 1;
            }
        }
    }
    grok::GetContext()->SetDebugExecution();
    using namespace boost::filesystem;
    using namespace grok::test;
    using namespace std;

    path p("../test/testing");

    try {
        if (!exists(p)) {
            std::cerr << "There is no test directory! Did you delete it?"
             << std::endl;
        }

        if (!is_directory(p)) {
            std::cerr << "It is odd. 'test' was always a directory containing"
                " many test files but it turns out that 'test' is not a "
                "directory at all." << std::endl;
        }

        // we are good
        std::vector<std::string> files;
        size_t count = 0;
    	directory_iterator e;
        for (directory_iterator it(p); it != e; ++it) {
            std::cout << "\rCounting test files: " << count++;
            std::cout << std::flush;
            files.push_back(it->path().string());
        }
        std::cout << std::endl;

        std::sort(files.begin(), files.end());
        TestStats stats;
        size_t i = 0;

        // run the tests

        if (test_id < 0) {
            for (auto file : files) {
                auto s = std::chrono::high_resolution_clock::now();

                std::cout << "Testing '" << file + '\'' << std::endl;
                Test test{ grok::GetContext() };

                if (test.Prepare(file).StartTest(f_syntax_errors | f_ir_errors
                        | f_vm_errors | f_print_reason)) {
                    std::cout << "Test[" << ++i << "] <"
                        << file << ">: passed.";
                    stats.AddPassed();
                } else {
                    std::cout << "Test[" << ++i << "] <"
                        << file << ">: failed.";
                    stats.AddFailed();
                }

                auto e = std::chrono::high_resolution_clock::now();
                std::cout << "[ time: ";
                log_progress(e - s);
                std::cout << " ]" << std::endl;
            }
        } else {
            auto s = std::chrono::high_resolution_clock::now();
            if (test_id > files.size()) {
                std::cerr << "test not written yet!" << std::endl;
                return 1;
            }
            auto file = files[test_id];
            std::cout << "Testing '" << file + '\'' << std::endl;
            Test test{ grok::GetContext() };

            if (test.Prepare(file).StartTest(f_syntax_errors | f_ir_errors
                    | f_vm_errors | f_print_reason)) {
                std::cout << "Test[" << ++i << "] <"
                    << file << ">: passed.";
                stats.AddPassed();
            } else {
                std::cout << "Test[" << ++i << "] <"
                    << file << ">: failed.";
                stats.AddFailed();
            }

            auto e = std::chrono::high_resolution_clock::now();
            std::cout << "[ time: ";
            log_progress(e - s);
            std::cout << " ]" << std::endl;
        }

        std::cout << stats << std::endl;
        return 0;
    } catch (std::exception &e) {
        std::cerr << e.what() << std::endl;
    }
    return -1;
}

<commit_msg>Allow msg as third arg in assert_equal<commit_after>#include "test.h"
#include "test-stats.h"

#include "grok/context.h"
#include "input/input-stream.h"
#include "input/readline.h"
#include "lexer/lexer.h"
#include "object/jsbasicobject.h"
#include "object/argument.h"
#include "object/function.h"
#include "parser/parser.h"
#include "vm/codegen.h"
#include "vm/context.h"
#include "vm/instruction-list.h"
#include "vm/printer.h"
#include "vm/vm.h"
#include "common/colors.h"

#include <iostream>
#include <cerrno>
#include <chrono>
#include <algorithm>
#include <boost/filesystem.hpp>

using namespace grok;
using namespace grok::vm;
using namespace grok::parser;
using namespace grok::input;

namespace grok {
namespace test {

template<typename Diff>
void log_progress(Diff d)
{
    std::cout <<
    (double)std::chrono::duration_cast
        <std::chrono::microseconds>(d).count() / (double)1000
              << "ms" << std::flush;
}

std::shared_ptr<grok::obj::Handle>
    AssertEqual(std::shared_ptr<grok::obj::Argument> args)
{
    auto rhs = args->GetProperty("rhs")->as<grok::obj::JSObject>();
    auto lhs = args->GetProperty("lhs")->as<grok::obj::JSObject>();
    auto msg = args->GetProperty("msg")->as<grok::obj::JSObject>()->ToString();

    if ((rhs->GetType() == grok::obj::ObjectType::_double
        || rhs->GetType() == grok::obj::ObjectType::_number)
        && (lhs->GetType() == grok::obj::ObjectType::_double
        || lhs->GetType() == grok::obj::ObjectType::_number)
        && (rhs->ToString() == lhs->ToString())
        && (rhs->AsString() == lhs->AsString()))
        return grok::obj::CreateUndefinedObject();

    if (rhs->GetType() != lhs->GetType()) {
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " types were not same [ msg: " + msg + "]");
    }
    if (rhs->ToString() != lhs->ToString())
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " toString's were not same [ msg: " + msg + "]");

    if (rhs->AsString() != lhs->AsString())
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " asString's were not same [ msg: " + msg + "]");

    return grok::obj::CreateUndefinedObject();
}

std::shared_ptr<grok::obj::Handle>
    AssertNotEqual(std::shared_ptr<grok::obj::Argument> args)
{
    auto rhs = args->GetProperty("rhs")->as<grok::obj::JSObject>();
    auto lhs = args->GetProperty("lhs")->as<grok::obj::JSObject>();

    if (rhs->GetType() == lhs->GetType()) {
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());
    }
    if (rhs->ToString() == lhs->ToString())
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());

    if (rhs->AsString() == lhs->AsString())
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());

    return grok::obj::CreateUndefinedObject();
}

Test &Test::Prepare(std::string file)
{
    file_ = file;
    expected_result_file_ = file;
    expected_result_file_.resize(file.size() - 3);
    expected_result_file_ += ".txt";

    grok::vm::InitializeVMContext();
    auto v = grok::vm::GetGlobalVMContext()->GetVStore();
    auto func = grok::obj::CreateFunction(AssertEqual);
    func->as<grok::obj::Function>()->SetParams({ "lhs", "rhs", "msg" });
    v->StoreValue("assert_equal", func);

    func = grok::obj::CreateFunction(AssertNotEqual);
    func->as<grok::obj::Function>()->SetParams({ "lhs", "rhs" });
    v->StoreValue("assert_not_equal", func);
    return *this;
}

std::string ReadFile(std::string file_)
{
    std::string v;
    if (FILE *fp = fopen(file_.c_str(), "r"))
    {
        char buf[1024];
        while (size_t len = fread(buf, 1, sizeof(buf), fp))
            v.insert(v.end(), buf, buf + len);
        fclose(fp);
    } else {
        std::cout << "fatal: " << file_ << ": "
            << strerror(errno);
        throw std::runtime_error("");
    }
    return v;
}

bool Test::CheckResult(std::string result)
{
    std::string expected_result = ReadFile(expected_result_file_);

    return expected_result == result;
}

bool Test::StartTest(int32_t flags)
{
    std::string file = ReadFile(file_);

    auto lex = std::make_unique<Lexer>(file);

    GrokParser parser{ std::move(lex) };
    if (!parser.ParseExpression())
        return !(flags & f_syntax_errors); // test failed

    auto ast = parser.ParsedAST();

    std::shared_ptr<InstructionList> IR;
    try {
        CodeGenerator codegen;
        codegen.Generate(ast.get());

        IR = codegen.GetIR();
        if (!IR || IR->size() == 0)
            return true;

    } catch (std::exception &e) {
        if (f_print_reason & flags)
            std::cout << e.what() << std::endl;
        return !(flags & f_ir_errors);
    }

    try {
        auto vm = grok::vm::CreateVM(grok::vm::GetGlobalVMContext());
        vm->SetCounters(IR->begin(), IR->end());

        vm->Run();

        Value result = vm->GetResult();
        auto obj = result.O->as<grok::obj::JSObject>();

        std::string res = obj->AsString();

        grok::GetContext()->RunIO();
        return true;
    } catch (std::exception &e) {
        if (flags & f_print_reason)
            std::cout << e.what() << std::endl;
        return !(flags & f_vm_errors);
    }
}

}
}

int main(int argc, char *argv[])
{
    grok::InitializeContext();
    int test_id = -1;

    if (argc >= 2) {
        if (std::string(argv[1]) == "-h" ||
            std::string(argv[1]) == "--help") {
            std::cerr << "Usage: " << argv[0] << " <test_number>" << std::endl;
            return 1;
        } else {
            try {
                test_id = std::stoi(argv[1]);
            } catch (std::exception &e) {
                std::cerr << "bad number" << std::endl;
                return 1;
            }
        }
    }
    grok::GetContext()->SetDebugExecution();
    using namespace boost::filesystem;
    using namespace grok::test;
    using namespace std;

    path p("../test/testing");

    try {
        if (!exists(p)) {
            std::cerr << "There is no test directory! Did you delete it?"
             << std::endl;
        }

        if (!is_directory(p)) {
            std::cerr << "It is odd. 'test' was always a directory containing"
                " many test files but it turns out that 'test' is not a "
                "directory at all." << std::endl;
        }

        // we are good
        std::vector<std::string> files;
        size_t count = 0;
    	directory_iterator e;
        for (directory_iterator it(p); it != e; ++it) {
            std::cout << "\rCounting test files: " << count++;
            std::cout << std::flush;
            files.push_back(it->path().string());
        }
        std::cout << std::endl;

        std::sort(files.begin(), files.end());
        TestStats stats;
        size_t i = 0;

        // run the tests

        if (test_id < 0) {
            for (auto file : files) {
                auto s = std::chrono::high_resolution_clock::now();

                std::cout << "Testing '" << file + '\'' << std::endl;
                Test test{ grok::GetContext() };

                if (test.Prepare(file).StartTest(f_syntax_errors | f_ir_errors
                        | f_vm_errors | f_print_reason)) {
                    std::cout << "Test[" << ++i << "] <"
                        << file << ">: passed.";
                    stats.AddPassed();
                } else {
                    std::cout << "Test[" << ++i << "] <"
                        << file << ">: failed.";
                    stats.AddFailed();
                }

                auto e = std::chrono::high_resolution_clock::now();
                std::cout << "[ time: ";
                log_progress(e - s);
                std::cout << " ]" << std::endl;
            }
        } else {
            auto s = std::chrono::high_resolution_clock::now();
            if (test_id > files.size()) {
                std::cerr << "test not written yet!" << std::endl;
                return 1;
            }
            auto file = files[test_id];
            std::cout << "Testing '" << file + '\'' << std::endl;
            Test test{ grok::GetContext() };

            if (test.Prepare(file).StartTest(f_syntax_errors | f_ir_errors
                    | f_vm_errors | f_print_reason)) {
                std::cout << "Test[" << ++i << "] <"
                    << file << ">: passed.";
                stats.AddPassed();
            } else {
                std::cout << "Test[" << ++i << "] <"
                    << file << ">: failed.";
                stats.AddFailed();
            }

            auto e = std::chrono::high_resolution_clock::now();
            std::cout << "[ time: ";
            log_progress(e - s);
            std::cout << " ]" << std::endl;
        }

        std::cout << stats << std::endl;
        return 0;
    } catch (std::exception &e) {
        std::cerr << e.what() << std::endl;
    }
    return -1;
}

<|endoftext|>


<commit_before>/**
 * @file radon.cpp
 *
 */

#include "radon.h"
#include "logger_factory.h"
#include "plugin_factory.h"
#include "util.h"
#include <sstream>
#include <thread>

using namespace std;
using namespace himan::plugin;

const int MAX_WORKERS = 32;
static once_flag oflag;

radon::radon() : itsInit(false), itsRadonDB()
{
	itsLogger = unique_ptr<logger>(logger_factory::Instance()->GetLog("radon"));

	call_once(oflag, [&]() {
		PoolMaxWorkers(MAX_WORKERS);

		NFmiRadonDBPool::Instance()->Username("wetodb");
		NFmiRadonDBPool::Instance()->Password("3loHRgdio");
	});
}

void radon::PoolMaxWorkers(int maxWorkers) { NFmiRadonDBPool::Instance()->MaxWorkers(maxWorkers); }

vector<string> radon::Files(search_options& options)
{
	Init();

	vector<string> files;

	string analtime = options.time.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00");
	string levelvalue = boost::lexical_cast<string>(options.level.Value());

	string ref_prod = options.prod.Name();
	// long no_vers = options.prod.TableVersion();

	string level_name = HPLevelTypeToString.at(options.level.Type());

	vector<vector<string>> gridgeoms;
	vector<string> sourceGeoms = options.configuration->SourceGeomNames();

	if (sourceGeoms.empty())
	{
		// Get all geometries
		gridgeoms = itsRadonDB->GetGridGeoms(ref_prod, analtime);
	}
	else
	{
		for (size_t i = 0; i < sourceGeoms.size(); i++)
		{
			vector<vector<string>> geoms = itsRadonDB->GetGridGeoms(ref_prod, analtime, sourceGeoms[i]);
			gridgeoms.insert(gridgeoms.end(), geoms.begin(), geoms.end());
		}
	}

	if (gridgeoms.empty())
	{
		// No geometries found, fetcher checks this
		return files;
	}

	string forecastTypeValue = "-1";  // default, deterministic/analysis

	if (options.ftype.Type() > 2)
	{
		forecastTypeValue = boost::lexical_cast<string>(options.ftype.Value());
	}

	string forecastTypeId = boost::lexical_cast<string>(options.ftype.Type());

	if (options.time.Step() == 0 && options.ftype.Type() == 1)
	{
		// ECMWF (and maybe others) use forecast type id == 2 for analysis hour
		forecastTypeId += ",2";
	}

	for (size_t i = 0; i < gridgeoms.size(); i++)
	{
		string tablename = gridgeoms[i][1];
		string geomid = gridgeoms[i][0];

		string parm_name = options.param.Name();

		string query =
		    "SELECT param_id, level_id, level_value, forecast_period, file_location, file_server "
		    "FROM " +
		    tablename +
		    "_v "
		    "WHERE analysis_time = '" +
		    analtime +
		    "' "
		    "AND param_name = '" +
		    parm_name +
		    "' "
		    "AND level_name = upper('" +
		    level_name +
		    "') "
		    "AND level_value = " +
		    levelvalue +
		    " "
		    "AND forecast_period = '" +
		    util::MakeSQLInterval(options.time) +
		    "' "
		    "AND geometry_id = " +
		    geomid +
		    " "
		    "AND forecast_type_id IN (" +
		    forecastTypeId +
		    ") "
		    "AND forecast_type_value = " +
		    forecastTypeValue +
		    " "
		    "ORDER BY forecast_period, level_id, level_value";

		itsRadonDB->Query(query);

		vector<string> values = itsRadonDB->FetchRow();

		if (values.empty())
		{
			continue;
		}

		itsLogger->Trace("Found data for parameter " + parm_name + " from radon geometry " + gridgeoms[i][3]);

		files.push_back(values[4]);

		break;  // discontinue loop on first positive match
	}

	return files;
}

bool radon::Save(const info& resultInfo, const string& theFileName)
{
	Init();

	stringstream query;

	if (resultInfo.Grid()->Class() != kRegularGrid)
	{
		itsLogger->Error("Only grid data can be stored to radon for now");
		return false;
	}

	/*
	 * 1. Get grid information
	 * 2. Get model information
	 * 3. Get data set information (ie model run)
	 * 4. Insert or update
	 */

	himan::point firstGridPoint = resultInfo.Grid()->FirstPoint();

	// get grib1 gridType

	int gribVersion = 1;
	int gridType = -1;

	switch (resultInfo.Grid()->Type())
	{
		case kLatitudeLongitude:
			gridType = 0;
			break;
		case kRotatedLatitudeLongitude:
			gridType = 10;
			break;
		case kStereographic:
			gridType = 5;
			break;
		case kReducedGaussian:
			gridType = 24;  // "stretched" gaussian
			break;
		case kAzimuthalEquidistant:
			gribVersion = 2;
			gridType = 110;
			break;
		default:
			throw runtime_error("Unsupported projection: " + boost::lexical_cast<string>(resultInfo.Grid()->Type()) +
			                    " " + HPGridTypeToString.at(resultInfo.Grid()->Type()));
	}

	map<string, string> geominfo = itsRadonDB->GetGeometryDefinition(
	    resultInfo.Grid()->Ni(), resultInfo.Grid()->Nj(), firstGridPoint.Y(), firstGridPoint.X(),
	    resultInfo.Grid()->Di(), resultInfo.Grid()->Dj(), gribVersion, gridType);

	if (geominfo.empty())
	{
		itsLogger->Warning("Grid geometry not found from radon");
		return false;
	}

	string geom_id = geominfo["id"];

	query.str("");

	query << "SELECT "
	      << "id, table_name "
	      << "FROM as_grid "
	      << "WHERE geometry_id = '" << geom_id << "'"
	      << " AND analysis_time = '" << resultInfo.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00") << "'"
	      << " AND producer_id = " << resultInfo.Producer().Id();

	itsRadonDB->Query(query.str());

	auto row = itsRadonDB->FetchRow();

	if (row.empty())
	{
		itsLogger->Warning("Data set definition not found from radon");
		return false;
	}

	string table_name = row[1];

	query.str("");

	char host[255];
	gethostname(host, 255);

	auto paraminfo = itsRadonDB->GetParameterFromDatabaseName(resultInfo.Producer().Id(), resultInfo.Param().Name());

	if (paraminfo.empty())
	{
		itsLogger->Error("Parameter information not found from radon for parameter " + resultInfo.Param().Name() +
		                 ", producer " + boost::lexical_cast<string>(resultInfo.Producer().Id()));
		return false;
	}

	auto levelinfo = itsRadonDB->GetLevelFromGrib(resultInfo.Producer().Id(), resultInfo.Level().Type(), 1);

	if (levelinfo.empty())
	{
		itsLogger->Error("Level information not found from radon for level " +
		                 HPLevelTypeToString.at(resultInfo.Level().Type()) + ", producer " +
		                 boost::lexical_cast<string>(resultInfo.Producer().Id()));
		return false;
	}

	/*
	 * We have our own error logging for unique key violations
	 */

	// itsRadonDB->Verbose(false);
	int forecastTypeValue = -1;  // default, deterministic/analysis

	if (resultInfo.ForecastType().Type() > 2)
	{
		forecastTypeValue = static_cast<int>(resultInfo.ForecastType().Value());
	}

	string analysisTime = resultInfo.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00");

	query << "INSERT INTO data." << table_name
	      << " (producer_id, analysis_time, geometry_id, param_id, level_id, level_value, forecast_period, "
	         "forecast_type_id, forecast_type_value, file_location, file_server) VALUES ("
	      << resultInfo.Producer().Id() << ", "
	      << "'" << analysisTime << "', " << geom_id << ", " << paraminfo["id"] << ", " << levelinfo["id"] << ", "
	      << resultInfo.Level().Value() << ", "
	      << "'" << util::MakeSQLInterval(resultInfo.Time()) << "', "
	      << static_cast<int>(resultInfo.ForecastType().Type()) << ", " << forecastTypeValue << ","
	      << "'" << theFileName << "', "
	      << "'" << host << "')";

	try
	{
		itsRadonDB->Execute(query.str());
		query.str("");

		query << "UPDATE as_grid SET record_count = record_count+1 WHERE producer_id = " << resultInfo.Producer().Id()
		      << " AND geometry_id = " << geom_id << " AND analysis_time = '" << analysisTime << "'";

		itsRadonDB->Execute(query.str());
		itsRadonDB->Commit();
	}
	catch (const pqxx::unique_violation& e)
	{
		itsRadonDB->Rollback();

		query.str("");
		query << "UPDATE data." << table_name << " SET "
		      << "file_location = '" << theFileName << "', "
		      << "file_server = '" << host << "' WHERE "
		      << "producer_id = " << resultInfo.Producer().Id() << " AND "
		      << "analysis_time = '" << analysisTime << "' AND "
		      << "geometry_id = " << geom_id << " AND "
		      << "param_id = " << paraminfo["id"] << " AND "
		      << "level_id = " << levelinfo["id"] << " AND "
		      << "level_value = " << resultInfo.Level().Value() << " AND "
		      << "forecast_period = "
		      << "'" << util::MakeSQLInterval(resultInfo.Time()) << "' AND "
		      << "forecast_type_id = " << static_cast<int>(resultInfo.ForecastType().Type()) << " AND "
		      << "forecast_type_value = " << forecastTypeValue;

		itsRadonDB->Execute(query.str());
		itsRadonDB->Commit();
	}

	itsLogger->Trace("Saved information on file '" + theFileName + "' to radon");

	return true;
}

map<string, string> radon::Grib1ParameterName(long producer, long fmiParameterId, long codeTableVersion,
                                              long timeRangeIndicator, long levelId, double level_value)
{
	Init();

	map<string, string> paramName = itsRadonDB->GetParameterFromGrib1(producer, codeTableVersion, fmiParameterId,
	                                                                  timeRangeIndicator, levelId, level_value);
	return paramName;
}

map<string, string> radon::Grib2ParameterName(long fmiParameterId, long category, long discipline, long producer,
                                              long levelId, double level_value)
{
	Init();

	map<string, string> paramName =
	    itsRadonDB->GetParameterFromGrib2(producer, discipline, category, fmiParameterId, levelId, level_value);
	return paramName;
}
<commit_msg>Use min/max analysis time fields<commit_after>/**
 * @file radon.cpp
 *
 */

#include "radon.h"
#include "logger_factory.h"
#include "plugin_factory.h"
#include "util.h"
#include <sstream>
#include <thread>

using namespace std;
using namespace himan::plugin;

const int MAX_WORKERS = 32;
static once_flag oflag;

radon::radon() : itsInit(false), itsRadonDB()
{
	itsLogger = unique_ptr<logger>(logger_factory::Instance()->GetLog("radon"));

	call_once(oflag, [&]() {
		PoolMaxWorkers(MAX_WORKERS);

		NFmiRadonDBPool::Instance()->Username("wetodb");
		NFmiRadonDBPool::Instance()->Password("3loHRgdio");
	});
}

void radon::PoolMaxWorkers(int maxWorkers) { NFmiRadonDBPool::Instance()->MaxWorkers(maxWorkers); }
vector<string> radon::Files(search_options& options)
{
	Init();

	vector<string> files;

	string analtime = options.time.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00");
	string levelvalue = boost::lexical_cast<string>(options.level.Value());

	string ref_prod = options.prod.Name();
	// long no_vers = options.prod.TableVersion();

	string level_name = HPLevelTypeToString.at(options.level.Type());

	vector<vector<string>> gridgeoms;
	vector<string> sourceGeoms = options.configuration->SourceGeomNames();

	if (sourceGeoms.empty())
	{
		// Get all geometries
		gridgeoms = itsRadonDB->GetGridGeoms(ref_prod, analtime);
	}
	else
	{
		for (size_t i = 0; i < sourceGeoms.size(); i++)
		{
			vector<vector<string>> geoms = itsRadonDB->GetGridGeoms(ref_prod, analtime, sourceGeoms[i]);
			gridgeoms.insert(gridgeoms.end(), geoms.begin(), geoms.end());
		}
	}

	if (gridgeoms.empty())
	{
		// No geometries found, fetcher checks this
		return files;
	}

	string forecastTypeValue = "-1";  // default, deterministic/analysis

	if (options.ftype.Type() > 2)
	{
		forecastTypeValue = boost::lexical_cast<string>(options.ftype.Value());
	}

	string forecastTypeId = boost::lexical_cast<string>(options.ftype.Type());

	if (options.time.Step() == 0 && options.ftype.Type() == 1)
	{
		// ECMWF (and maybe others) use forecast type id == 2 for analysis hour
		forecastTypeId += ",2";
	}

	for (size_t i = 0; i < gridgeoms.size(); i++)
	{
		string tablename = gridgeoms[i][1];
		string geomid = gridgeoms[i][0];

		string parm_name = options.param.Name();

		string query =
		    "SELECT param_id, level_id, level_value, forecast_period, file_location, file_server "
		    "FROM " +
		    tablename +
		    "_v "
		    "WHERE analysis_time = '" +
		    analtime +
		    "' "
		    "AND param_name = '" +
		    parm_name +
		    "' "
		    "AND level_name = upper('" +
		    level_name +
		    "') "
		    "AND level_value = " +
		    levelvalue +
		    " "
		    "AND forecast_period = '" +
		    util::MakeSQLInterval(options.time) +
		    "' "
		    "AND geometry_id = " +
		    geomid +
		    " "
		    "AND forecast_type_id IN (" +
		    forecastTypeId +
		    ") "
		    "AND forecast_type_value = " +
		    forecastTypeValue +
		    " "
		    "ORDER BY forecast_period, level_id, level_value";

		itsRadonDB->Query(query);

		vector<string> values = itsRadonDB->FetchRow();

		if (values.empty())
		{
			continue;
		}

		itsLogger->Trace("Found data for parameter " + parm_name + " from radon geometry " + gridgeoms[i][3]);

		files.push_back(values[4]);

		break;  // discontinue loop on first positive match
	}

	return files;
}

bool radon::Save(const info& resultInfo, const string& theFileName)
{
	Init();

	stringstream query;

	if (resultInfo.Grid()->Class() != kRegularGrid)
	{
		itsLogger->Error("Only grid data can be stored to radon for now");
		return false;
	}

	/*
	 * 1. Get grid information
	 * 2. Get model information
	 * 3. Get data set information (ie model run)
	 * 4. Insert or update
	 */

	himan::point firstGridPoint = resultInfo.Grid()->FirstPoint();

	// get grib1 gridType

	int gribVersion = 1;
	int gridType = -1;

	switch (resultInfo.Grid()->Type())
	{
		case kLatitudeLongitude:
			gridType = 0;
			break;
		case kRotatedLatitudeLongitude:
			gridType = 10;
			break;
		case kStereographic:
			gridType = 5;
			break;
		case kReducedGaussian:
			gridType = 24;  // "stretched" gaussian
			break;
		case kAzimuthalEquidistant:
			gribVersion = 2;
			gridType = 110;
			break;
		default:
			throw runtime_error("Unsupported projection: " + boost::lexical_cast<string>(resultInfo.Grid()->Type()) +
			                    " " + HPGridTypeToString.at(resultInfo.Grid()->Type()));
	}

	map<string, string> geominfo = itsRadonDB->GetGeometryDefinition(
	    resultInfo.Grid()->Ni(), resultInfo.Grid()->Nj(), firstGridPoint.Y(), firstGridPoint.X(),
	    resultInfo.Grid()->Di(), resultInfo.Grid()->Dj(), gribVersion, gridType);

	if (geominfo.empty())
	{
		itsLogger->Warning("Grid geometry not found from radon");
		return false;
	}

	string geom_id = geominfo["id"];
	auto analysisTime = resultInfo.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00");

	query.str("");

	query << "SELECT "
	      << "id, table_name "
	      << "FROM as_grid "
	      << "WHERE geometry_id = '" << geom_id << "'"
	      << " AND min_analysis_time <= '" << analysisTime << "'"
	      << " AND max_analysis_time > '" << analysisTime << "'"
	      << " AND producer_id = " << resultInfo.Producer().Id();

	itsRadonDB->Query(query.str());

	auto row = itsRadonDB->FetchRow();

	if (row.empty())
	{
		itsLogger->Warning("Data set definition not found from radon");
		return false;
	}

	string table_name = row[1];

	query.str("");

	char host[255];
	gethostname(host, 255);

	auto paraminfo = itsRadonDB->GetParameterFromDatabaseName(resultInfo.Producer().Id(), resultInfo.Param().Name());

	if (paraminfo.empty())
	{
		itsLogger->Error("Parameter information not found from radon for parameter " + resultInfo.Param().Name() +
		                 ", producer " + boost::lexical_cast<string>(resultInfo.Producer().Id()));
		return false;
	}

	auto levelinfo = itsRadonDB->GetLevelFromGrib(resultInfo.Producer().Id(), resultInfo.Level().Type(), 1);

	if (levelinfo.empty())
	{
		itsLogger->Error("Level information not found from radon for level " +
		                 HPLevelTypeToString.at(resultInfo.Level().Type()) + ", producer " +
		                 boost::lexical_cast<string>(resultInfo.Producer().Id()));
		return false;
	}

	/*
	 * We have our own error logging for unique key violations
	 */

	// itsRadonDB->Verbose(false);
	int forecastTypeValue = -1;  // default, deterministic/analysis

	if (resultInfo.ForecastType().Type() > 2)
	{
		forecastTypeValue = static_cast<int>(resultInfo.ForecastType().Value());
	}

	query << "INSERT INTO data." << table_name
	      << " (producer_id, analysis_time, geometry_id, param_id, level_id, level_value, forecast_period, "
	         "forecast_type_id, forecast_type_value, file_location, file_server) VALUES ("
	      << resultInfo.Producer().Id() << ", "
	      << "'" << analysisTime << "', " << geom_id << ", " << paraminfo["id"] << ", " << levelinfo["id"] << ", "
	      << resultInfo.Level().Value() << ", "
	      << "'" << util::MakeSQLInterval(resultInfo.Time()) << "', "
	      << static_cast<int>(resultInfo.ForecastType().Type()) << ", " << forecastTypeValue << ","
	      << "'" << theFileName << "', "
	      << "'" << host << "')";

	try
	{
		itsRadonDB->Execute(query.str());
		query.str("");

		query << "UPDATE as_grid SET record_count = record_count+1 WHERE producer_id = " << resultInfo.Producer().Id()
		      << " AND geometry_id = " << geom_id << " AND analysis_time = '" << analysisTime << "'";

		itsRadonDB->Execute(query.str());
		itsRadonDB->Commit();
	}
	catch (const pqxx::unique_violation& e)
	{
		itsRadonDB->Rollback();

		query.str("");
		query << "UPDATE data." << table_name << " SET "
		      << "file_location = '" << theFileName << "', "
		      << "file_server = '" << host << "' WHERE "
		      << "producer_id = " << resultInfo.Producer().Id() << " AND "
		      << "analysis_time = '" << analysisTime << "' AND "
		      << "geometry_id = " << geom_id << " AND "
		      << "param_id = " << paraminfo["id"] << " AND "
		      << "level_id = " << levelinfo["id"] << " AND "
		      << "level_value = " << resultInfo.Level().Value() << " AND "
		      << "forecast_period = "
		      << "'" << util::MakeSQLInterval(resultInfo.Time()) << "' AND "
		      << "forecast_type_id = " << static_cast<int>(resultInfo.ForecastType().Type()) << " AND "
		      << "forecast_type_value = " << forecastTypeValue;

		itsRadonDB->Execute(query.str());
		itsRadonDB->Commit();
	}

	itsLogger->Trace("Saved information on file '" + theFileName + "' to radon");

	return true;
}

map<string, string> radon::Grib1ParameterName(long producer, long fmiParameterId, long codeTableVersion,
                                              long timeRangeIndicator, long levelId, double level_value)
{
	Init();

	map<string, string> paramName = itsRadonDB->GetParameterFromGrib1(producer, codeTableVersion, fmiParameterId,
	                                                                  timeRangeIndicator, levelId, level_value);
	return paramName;
}

map<string, string> radon::Grib2ParameterName(long fmiParameterId, long category, long discipline, long producer,
                                              long levelId, double level_value)
{
	Init();

	map<string, string> paramName =
	    itsRadonDB->GetParameterFromGrib2(producer, discipline, category, fmiParameterId, levelId, level_value);
	return paramName;
}
<|endoftext|>


<commit_before>//put global includes in 'BasicIncludes'
// hi

#include "BasicIncludes.h"
#include "rand.h"
#include "Camera.h"
#include "Input.h"
#include "Object.h"

//Function List
void Update(double);
void Draw();
void CameraInput();
void MouseInput();
void InitializeWindow();
void Terminate();
void Run();

//Variables
GLFWwindow* mainThread;
glm::uvec2 SCREEN_SIZE;
Camera camera = Camera();
glm::vec2 mouseChangeDegrees;
double deltaTime;

std::vector<Object*> objects;

void Terminate() {
	glfwTerminate();
	exit(0);
}

void InitializeWindow() {

	//
	if (!glfwInit()) {
		Terminate();
	}

	//set screen size
	const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());

	SCREEN_SIZE = glm::uvec2(720,720);

	//basic aa done for us ;D
	glfwWindowHint(GLFW_SAMPLES, 16);
	glfwWindowHint(GLFW_VISIBLE, GL_TRUE);

	//can change the screen setting later

	//if (window == FULLSCREEN) {

	//	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
	//	mainThread = glfwCreateWindow(SCREEN_SIZE.x, SCREEN_SIZE.y, "LifeSim", glfwGetPrimaryMonitor(), NULL);

	//}
	//else if (window == WINDOWED) {

		glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
		mainThread = glfwCreateWindow(SCREEN_SIZE.x, SCREEN_SIZE.y, "LifeSim", NULL, NULL);

	//}
	//else if (BORDERLESS) {

	//	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	//	const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
	//	glfwWindowHint(GLFW_RED_BITS, mode->redBits);
	//	glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
	//	glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
	//	glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
	//	mainThread = glfwCreateWindow(mode->width, mode->height, "LifeSim", glfwGetPrimaryMonitor(), NULL);

	//}

	if (!mainThread) {
		glfwTerminate();
		throw std::runtime_error("GLFW window failed");
	}

	glfwMakeContextCurrent(mainThread);

	// initialise GLEW
	if (glewInit() != GLEW_OK) {
		throw std::runtime_error("glewInit failed");
	}

	glewExperimental = GL_TRUE; //stops glew crashing on OSX :-/

	glfwSetInputMode(mainThread, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
	glfwSetCursorPos(mainThread, SCREEN_SIZE.x / 2.0, SCREEN_SIZE.y / 2.0);

	//Discard all the errors
	while (glGetError() != GL_NO_ERROR) {}

	glEnable(GL_DEPTH_TEST); // enable depth-testing
	glDepthMask(GL_TRUE);  // turn on
	glDepthFunc(GL_LEQUAL);
	glDepthRange(0.0f, 1.0f);
	glEnable(GL_TEXTURE_2D);

	mouseChangeDegrees = glm::vec2(0);

	// setup camera
	camera.setViewportAspectRatio(SCREEN_SIZE.x / (float)SCREEN_SIZE.y);

	camera.setPosition(glm::vec3(0.0f, 0.0f, (METER)));
	camera.offsetOrientation(0.0f, -45);

	//unsigned concurentThreadsSupported = std::thread::hardware_concurrency();
	//threads = new ThreadPool(concurentThreadsSupported);

	//for keyboard controls
	glfwSetKeyCallback(mainThread, InputKeyboardCallback);
	SetInputWindow(mainThread);
}

void Run() {
		deltaTime = 1.0 / 60;
		InitializeWindow();

		Object testObj = Object();
		objects.push_back(&testObj);

		//timer info for loop
		double t = 0.0f;
		double currentTime = glfwGetTime();
		double accumulator = 0.0f;

		glfwPollEvents();		//stop loop when glfw exit is called
		glfwSetCursorPos(mainThread, SCREEN_SIZE.x / 2.0f, SCREEN_SIZE.y / 2.0f);

		while (!glfwWindowShouldClose(mainThread)) {
			double newTime = glfwGetTime();
			double frameTime = newTime - currentTime;
			//std::cout << "FPS:: " <<1.0f / frameTime << std::endl;

			//setting up timers
			if (frameTime > 0.25) {
				frameTime = 0.25;
			}
			currentTime = newTime;
			accumulator += frameTime;

			//# of updates based on accumulated time

			while (accumulator >= deltaTime) {

				MouseInput();//update mouse change
				glfwPollEvents(); //executes all set input callbacks

				CameraInput(); //bypasses input system for direct camera manipulation
				Update(deltaTime); //updates all objects based on the constant deltaTime.

				t += deltaTime;
				accumulator -= deltaTime;
			}

			//draw
			glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			Draw();

			glfwSwapBuffers(mainThread);
	}
}
void MouseInput() {
	double xPos;
	double yPos;
	glfwGetCursorPos(mainThread, &xPos, &yPos);
	xPos -= (SCREEN_SIZE.x / 2.0);
	yPos -= (SCREEN_SIZE.y / 2.0);

	mouseChangeDegrees.x = (float)(xPos / SCREEN_SIZE.x *camera.fieldOfView().x);
	mouseChangeDegrees.y = (float)(yPos / SCREEN_SIZE.y *camera.fieldOfView().y);

	/*std::cout << "Change in x (mouse): " << mouseChangeDegrees.x << std::endl;
	std::cout << "Change in y (mouse): " << mouseChangeDegrees.y << std::endl;*/

	camera.offsetOrientation(mouseChangeDegrees.x, mouseChangeDegrees.y);

	glfwSetCursorPos(mainThread, SCREEN_SIZE.x / 2.0f, SCREEN_SIZE.y / 2.0f);
}
void CameraInput() {
	double moveSpeed;
	if (glfwGetKey(mainThread, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) {
		moveSpeed = 9 * METER * deltaTime;
	}
	else if (glfwGetKey(mainThread, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) {
		moveSpeed = 1 * METER * deltaTime;
	}
	else {
		moveSpeed = 4.5 * METER * deltaTime;
	}

	if (glfwGetKey(mainThread, GLFW_KEY_S) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * -camera.forward());
	}
	else if (glfwGetKey(mainThread, GLFW_KEY_W) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * camera.forward());
	}
	if (glfwGetKey(mainThread, GLFW_KEY_A) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * -camera.right());
	}
	else if (glfwGetKey(mainThread, GLFW_KEY_D) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * camera.right());
	}
	if (glfwGetKey(mainThread, GLFW_KEY_Z) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * -glm::vec3(0, 0, 1));
	}
	else if (glfwGetKey(mainThread, GLFW_KEY_X) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * glm::vec3(0, 0, 1));
	}
}

void Update(double dt) {

}
void Draw() {
	for (int i = 0; i < objects.size();i++){
		objects[i]->Draw(camera);
	}
}
int main(){

	Run();

	Terminate();

	return 0;
}
<commit_msg>Added bullet, I think<commit_after>//put global includes in 'BasicIncludes'
// hi

#include "BasicIncludes.h"
#include "rand.h"
#include "Camera.h"
#include "Input.h"
#include "Object.h"

//Function List
void Update(double);
void Draw();
void CameraInput();
void MouseInput();
void InitializeWindow();
void Terminate();
void Run();

//Variables
GLFWwindow* mainThread;
glm::uvec2 SCREEN_SIZE;
Camera camera = Camera();
glm::vec2 mouseChangeDegrees;
double deltaTime;

std::vector<Object*> objects;

void Terminate() {
	glfwTerminate();
	exit(0);
}

void InitializeWindow() {

	if (!glfwInit()) {
		Terminate();
	}

	//set screen size
	const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());

	SCREEN_SIZE = glm::uvec2(720,720);

	//basic aa done for us ;D
	glfwWindowHint(GLFW_SAMPLES, 16);
	glfwWindowHint(GLFW_VISIBLE, GL_TRUE);

	//can change the screen setting later

	//if (window == FULLSCREEN) {

	//	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
	//	mainThread = glfwCreateWindow(SCREEN_SIZE.x, SCREEN_SIZE.y, "LifeSim", glfwGetPrimaryMonitor(), NULL);

	//}
	//else if (window == WINDOWED) {

		glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
		mainThread = glfwCreateWindow(SCREEN_SIZE.x, SCREEN_SIZE.y, "LifeSim", NULL, NULL);

	//}
	//else if (BORDERLESS) {

	//	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	//	const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
	//	glfwWindowHint(GLFW_RED_BITS, mode->redBits);
	//	glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
	//	glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
	//	glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
	//	mainThread = glfwCreateWindow(mode->width, mode->height, "LifeSim", glfwGetPrimaryMonitor(), NULL);

	//}

	if (!mainThread) {
		glfwTerminate();
		throw std::runtime_error("GLFW window failed");
	}

	glfwMakeContextCurrent(mainThread);

	// initialise GLEW
	if (glewInit() != GLEW_OK) {
		throw std::runtime_error("glewInit failed");
	}

	glewExperimental = GL_TRUE; //stops glew crashing on OSX :-/

	glfwSetInputMode(mainThread, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
	glfwSetCursorPos(mainThread, SCREEN_SIZE.x / 2.0, SCREEN_SIZE.y / 2.0);

	//Discard all the errors
	while (glGetError() != GL_NO_ERROR) {}

	glEnable(GL_DEPTH_TEST); // enable depth-testing
	glDepthMask(GL_TRUE);  // turn on
	glDepthFunc(GL_LEQUAL);
	glDepthRange(0.0f, 1.0f);
	glEnable(GL_TEXTURE_2D);

	mouseChangeDegrees = glm::vec2(0);

	// setup camera
	camera.setViewportAspectRatio(SCREEN_SIZE.x / (float)SCREEN_SIZE.y);

	camera.setPosition(glm::vec3(0.0f, 0.0f, (METER)));
	camera.offsetOrientation(0.0f, -45);

	//unsigned concurentThreadsSupported = std::thread::hardware_concurrency();
	//threads = new ThreadPool(concurentThreadsSupported);

	//for keyboard controls
	glfwSetKeyCallback(mainThread, InputKeyboardCallback);
	SetInputWindow(mainThread);
}

void Run() {
		deltaTime = 1.0 / 60;
		InitializeWindow();

		Object testObj = Object();
		objects.push_back(&testObj);

		//timer info for loop
		double t = 0.0f;
		double currentTime = glfwGetTime();
		double accumulator = 0.0f;

		glfwPollEvents();		//stop loop when glfw exit is called
		glfwSetCursorPos(mainThread, SCREEN_SIZE.x / 2.0f, SCREEN_SIZE.y / 2.0f);

		while (!glfwWindowShouldClose(mainThread)) {
			double newTime = glfwGetTime();
			double frameTime = newTime - currentTime;
			//std::cout << "FPS:: " <<1.0f / frameTime << std::endl;

			//setting up timers
			if (frameTime > 0.25) {
				frameTime = 0.25;
			}
			currentTime = newTime;
			accumulator += frameTime;

			//# of updates based on accumulated time

			while (accumulator >= deltaTime) {

				MouseInput();//update mouse change
				glfwPollEvents(); //executes all set input callbacks

				CameraInput(); //bypasses input system for direct camera manipulation
				Update(deltaTime); //updates all objects based on the constant deltaTime.

				t += deltaTime;
				accumulator -= deltaTime;
			}

			//draw
			glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			Draw();

			glfwSwapBuffers(mainThread);
	}
}
void MouseInput() {
	double xPos;
	double yPos;
	glfwGetCursorPos(mainThread, &xPos, &yPos);
	xPos -= (SCREEN_SIZE.x / 2.0);
	yPos -= (SCREEN_SIZE.y / 2.0);

	mouseChangeDegrees.x = (float)(xPos / SCREEN_SIZE.x *camera.fieldOfView().x);
	mouseChangeDegrees.y = (float)(yPos / SCREEN_SIZE.y *camera.fieldOfView().y);

	/*std::cout << "Change in x (mouse): " << mouseChangeDegrees.x << std::endl;
	std::cout << "Change in y (mouse): " << mouseChangeDegrees.y << std::endl;*/

	camera.offsetOrientation(mouseChangeDegrees.x, mouseChangeDegrees.y);

	glfwSetCursorPos(mainThread, SCREEN_SIZE.x / 2.0f, SCREEN_SIZE.y / 2.0f);
}
void CameraInput() {
	double moveSpeed;
	if (glfwGetKey(mainThread, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) {
		moveSpeed = 9 * METER * deltaTime;
	}
	else if (glfwGetKey(mainThread, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) {
		moveSpeed = 1 * METER * deltaTime;
	}
	else {
		moveSpeed = 4.5 * METER * deltaTime;
	}

	if (glfwGetKey(mainThread, GLFW_KEY_S) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * -camera.forward());
	}
	else if (glfwGetKey(mainThread, GLFW_KEY_W) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * camera.forward());
	}
	if (glfwGetKey(mainThread, GLFW_KEY_A) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * -camera.right());
	}
	else if (glfwGetKey(mainThread, GLFW_KEY_D) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * camera.right());
	}
	if (glfwGetKey(mainThread, GLFW_KEY_Z) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * -glm::vec3(0, 0, 1));
	}
	else if (glfwGetKey(mainThread, GLFW_KEY_X) == GLFW_PRESS) {
		camera.offsetPosition(float(moveSpeed) * glm::vec3(0, 0, 1));
	}
}

void Update(double dt) {

}
void Draw() {
	for (int i = 0; i < objects.size();i++){
		objects[i]->Draw(camera);
	}
}
int main(){

	Run();

	Terminate();

	return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <fstream>
#include "StringLibrary.h"
#include <stdlib.h>
#include <string>
#include "LinkerEngine.h"
#include "ModuleEngine.h"
#include "ObjectCode.h"
#include "FileLibrary.h"
using std::cout;
using std::cin;
using std::advance;
using std::string;
using std::ifstream;

int main(int argc, char *argv[]) {
#ifdef _DEBUG
	//seta programaticamente os argumentos em modo debug
	argv[1] = "arquivoTesteA.o";
	argv[2] = "arquivoTesteB.o";
	argv[3] = "arquivoTesteA.o";
	argv[4] = "arquivoTeste.e";
#else
	//pega os argumentos da linha de comando em modo release
	if (argc > 5 || argc < 4) {
		printf("Selecione ate 3 arquivos objetos para o ligador,juntamente com o arquivo .e ligador:\n");
		printf("cmd>Ligador <Arquivo de Entrada1> <Arquivo de Entrada2><Arquivo de Entrada3> <Arquivo de Saida>\n");
		return 1;
	}
#endif // DEBUG
	FileLibrary leitor;
	ifstream fileStream;
	for (int i = 1; i < argc-1 ; i++) {//confere todos os arquivos .o se estao no formato correto
		if (!leitor.VerifyFile(argv[i], "o", "O Ligador aceita somente arquivos .o para sua leitura", &fileStream)) {
			return 1;
		}
	}
	auto linker =  LinkerEngine();
	for (int  i = 1; i < argc-1 ; i++) {//adiciona todos os arquivos ao ligador
		auto File =  ModuleEngine(argv[i]);
		linker.AddModule(File);
	}

	linker.Merge(argv[argc-1]);
	//getchar();
	return 0;
}
<commit_msg>Feitos ajustes no ligador<commit_after>#include <stdio.h>
#include <fstream>
#include "StringLibrary.h"
#include <stdlib.h>
#include <string>
#include "LinkerEngine.h"
#include "ModuleEngine.h"
#include "ObjectCode.h"
#include "FileLibrary.h"
using std::cout;
using std::cin;
using std::advance;
using std::string;
using std::ifstream;

int main(int argc, char *argv[]) {
#ifdef _DEBUG
	//seta programaticamente os argumentos em modo debug
	argv[1] = "arquivoTesteA.o";
	argv[2] = "arquivoTesteB.o";
	argv[3] = "arquivoTeste.e";
	argc = 4;
#else
	//pega os argumentos da linha de comando em modo release
	if (argc > 5 || argc < 4) {
		printf("Selecione entre 2 e 3 arquivos objetos e a saida\n");
		printf("cmd>Ligador <Arquivo de Entrada1> <Arquivo de Entrada2> (<Arquivo de Entrada3> opcional) <Arquivo de Saida>\n");
		return 1;
	}
#endif // DEBUG
	FileLibrary leitor;
	ifstream fileStream;
	for (int i = 1; i < argc-1 ; i++) {//confere todos os arquivos .o se estao no formato correto
		if (!leitor.VerifyFile(argv[i], "o", "O Ligador aceita somente arquivos .o para sua leitura", &fileStream)) {
			return 1;
		}
	}
	auto linker =  LinkerEngine();
	for (int  i = 1; i < argc-1 ; i++) {//adiciona todos os arquivos ao ligador
		auto File =  ModuleEngine(argv[i]);
		linker.AddModule(File);
	}

	linker.Merge(argv[argc-1]);
	getchar();
	return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.2.0, packaged on September 2009.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_primitivegroup.cpp implementation of the GLC_PrimitiveGroup class.

#include "glc_primitivegroup.h"
#include "../glc_state.h"

GLC_PrimitiveGroup::GLC_PrimitiveGroup(GLC_uint materialId)
: m_ID(materialId)
, m_TrianglesIndex()
, m_pBaseTrianglesOffset(NULL)
, m_BaseTrianglesOffseti(0)
, m_StripsIndex()
, m_StripIndexSizes()
, m_StripIndexOffset()
, m_StripIndexOffseti()
, m_FansIndex()
, m_FansIndexSizes()
, m_FanIndexOffset()
, m_FanIndexOffseti()
, m_IsFinished(false)
, m_TrianglesIndexSize(0)
, m_TrianglesStripSize(0)
, m_TrianglesFanSize(0)
{

}
//! Copy constructor
GLC_PrimitiveGroup::GLC_PrimitiveGroup(const GLC_PrimitiveGroup& group)
: m_ID(group.m_ID)
, m_TrianglesIndex(group.m_TrianglesIndex)
, m_pBaseTrianglesOffset(group.m_pBaseTrianglesOffset)
, m_BaseTrianglesOffseti(group.m_BaseTrianglesOffseti)
, m_StripsIndex(group.m_StripsIndex)
, m_StripIndexSizes(group.m_StripIndexSizes)
, m_StripIndexOffset(group.m_StripIndexOffset)
, m_StripIndexOffseti(group.m_StripIndexOffseti)
, m_FansIndex(group.m_FansIndex)
, m_FansIndexSizes(group.m_FansIndexSizes)
, m_FanIndexOffset(group.m_FanIndexOffset)
, m_FanIndexOffseti(group.m_FanIndexOffseti)
, m_IsFinished(group.m_IsFinished)
, m_TrianglesIndexSize(group.m_TrianglesIndexSize)
, m_TrianglesStripSize(group.m_TrianglesStripSize)
, m_TrianglesFanSize(group.m_TrianglesFanSize)
{

}

//! Copy constructor
GLC_PrimitiveGroup::GLC_PrimitiveGroup(const GLC_PrimitiveGroup& group, GLC_uint id)
: m_ID(id)
, m_TrianglesIndex(group.m_TrianglesIndex)
, m_pBaseTrianglesOffset(group.m_pBaseTrianglesOffset)
, m_BaseTrianglesOffseti(group.m_BaseTrianglesOffseti)
, m_StripsIndex(group.m_StripsIndex)
, m_StripIndexSizes(group.m_StripIndexSizes)
, m_StripIndexOffset(group.m_StripIndexOffset)
, m_StripIndexOffseti(group.m_StripIndexOffseti)
, m_FansIndex(group.m_FansIndex)
, m_FansIndexSizes(group.m_FansIndexSizes)
, m_FanIndexOffset(group.m_FanIndexOffset)
, m_FanIndexOffseti(group.m_FanIndexOffseti)
, m_IsFinished(group.m_IsFinished)
, m_TrianglesIndexSize(group.m_TrianglesIndexSize)
, m_TrianglesStripSize(group.m_TrianglesStripSize)
, m_TrianglesFanSize(group.m_TrianglesFanSize)
{

}

// = operator
GLC_PrimitiveGroup& GLC_PrimitiveGroup::operator=(const GLC_PrimitiveGroup& group)
{
	if (this != &group)
	{
		m_ID= group.m_ID;
		m_TrianglesIndex= group.m_TrianglesIndex;
		m_pBaseTrianglesOffset= group.m_pBaseTrianglesOffset;
		m_BaseTrianglesOffseti= group.m_BaseTrianglesOffseti;
		m_StripsIndex= group.m_StripsIndex;
		m_StripIndexSizes= group.m_StripIndexSizes;
		m_StripIndexOffset= group.m_StripIndexOffset;
		m_StripIndexOffseti= group.m_StripIndexOffseti;
		m_FansIndex= group.m_FansIndex;
		m_FansIndexSizes= group.m_FansIndexSizes;
		m_FanIndexOffset= group.m_FanIndexOffset;
		m_FanIndexOffseti= group.m_FanIndexOffseti;
		m_IsFinished= group.m_IsFinished;
		m_TrianglesIndexSize= group.m_TrianglesIndexSize;
		m_TrianglesStripSize= group.m_TrianglesStripSize;
		m_TrianglesFanSize= group.m_TrianglesFanSize;
	}
	return *this;
}

GLC_PrimitiveGroup::~GLC_PrimitiveGroup()
{

}

// Add triangle strip to the group
void GLC_PrimitiveGroup::addTrianglesStrip(const IndexList& input)
{
	m_StripsIndex+= input;
	m_TrianglesStripSize= m_StripsIndex.size();

	m_StripIndexSizes.append(static_cast<GLsizei>(input.size()));

	if (m_StripIndexOffseti.isEmpty())
	{
		m_StripIndexOffseti.append(0);
	}
	int offset= m_StripIndexOffseti.last() + m_StripIndexSizes.last();
	m_StripIndexOffseti.append(offset);
}

// Set base triangle strip offset
void GLC_PrimitiveGroup::setBaseTrianglesStripOffset(GLvoid* pOffset)
{
	m_StripIndexOffseti.pop_back();
	const int size= m_StripIndexOffseti.size();
	for (int i= 0; i < size; ++i)
	{
		m_StripIndexOffset.append(BUFFER_OFFSET(static_cast<GLsizei>(m_StripIndexOffseti[i]) * sizeof(GLuint) + reinterpret_cast<GLsizeiptr>(pOffset)));
	}
	m_StripIndexOffseti.clear();
}

// Set base triangle strip offset
void GLC_PrimitiveGroup::setBaseTrianglesStripOffseti(int offset)
{
	m_StripIndexOffseti.pop_back();
	const int size= m_StripIndexOffseti.size();
	for (int i= 0; i < size; ++i)
	{
		m_StripIndexOffseti[i]= m_StripIndexOffseti[i] + offset;
	}
}

//! Add triangle fan to the group
void GLC_PrimitiveGroup::addTrianglesFan(const IndexList& input)
{
	m_FansIndex+= input;
	m_TrianglesFanSize= m_FansIndex.size();

	m_FansIndexSizes.append(static_cast<GLsizei>(input.size()));

	if (m_FanIndexOffseti.isEmpty())
	{
		m_FanIndexOffseti.append(0);
	}
	int offset= m_FanIndexOffseti.last() + m_FansIndexSizes.last();
	m_FanIndexOffseti.append(offset);

}

// Set base triangle fan offset
void GLC_PrimitiveGroup::setBaseTrianglesFanOffset(GLvoid* pOffset)
{
	m_FanIndexOffseti.pop_back();
	const int size= m_FanIndexOffseti.size();
	for (int i= 0; i < size; ++i)
	{
		m_FanIndexOffset.append(BUFFER_OFFSET(static_cast<GLsizei>(m_FanIndexOffseti[i]) * sizeof(GLuint) + reinterpret_cast<GLsizeiptr>(pOffset)));
	}
	m_FanIndexOffseti.clear();
}

// Set base triangle fan offset
void GLC_PrimitiveGroup::setBaseTrianglesFanOffseti(int offset)
{
	m_FanIndexOffseti.pop_back();
	const int size= m_FanIndexOffseti.size();
	for (int i= 0; i < size; ++i)
	{
		m_FanIndexOffseti[i]= m_FanIndexOffseti[i] + offset;
	}
}

// Change index to VBO mode
void GLC_PrimitiveGroup::changeToVboMode()
{
	m_pBaseTrianglesOffset= BUFFER_OFFSET(static_cast<GLsizei>(m_BaseTrianglesOffseti) * sizeof(GLuint));
	m_BaseTrianglesOffseti= 0;

	m_StripIndexOffset.clear();
	const int stripOffsetSize= m_StripIndexOffseti.size();
	for (int i= 0; i < stripOffsetSize; ++i)
	{
		m_StripIndexOffset.append(BUFFER_OFFSET(static_cast<GLsizei>(m_StripIndexOffseti.at(i)) * sizeof(GLuint)));
	}
	m_StripIndexOffseti.clear();

	m_FanIndexOffset.clear();
	const int fanOffsetSize= m_FanIndexOffseti.size();
	for (int i= 0; i < fanOffsetSize; ++i)
	{
		m_FanIndexOffset.append(BUFFER_OFFSET(static_cast<GLsizei>(m_FanIndexOffseti.at(i)) * sizeof(GLuint)));
	}
	m_FanIndexOffseti.clear();
}

// Clear the group
void GLC_PrimitiveGroup::clear()
{
	m_TrianglesIndex.clear();
	m_pBaseTrianglesOffset= NULL;
	m_BaseTrianglesOffseti= 0;
	m_StripsIndex.clear();
	m_StripIndexSizes.clear();
	m_StripIndexOffset.clear();
	m_StripIndexOffseti.clear();
	m_FansIndex.clear();
	m_FansIndexSizes.clear();
	m_FanIndexOffset.clear();
	m_FanIndexOffseti.clear();
	m_IsFinished= false;
	m_TrianglesIndexSize= 0;
	m_TrianglesStripSize= 0;
	m_TrianglesFanSize= 0;
}

// Non Member methods
#define GLC_BINARY_CHUNK_ID 0xA700
// Non-member stream operator
QDataStream &operator<<(QDataStream &stream, const GLC_PrimitiveGroup &primitiveGroup)
{
	Q_ASSERT(primitiveGroup.isFinished());
	quint32 chunckId= GLC_BINARY_CHUNK_ID;
	stream << chunckId;

	// Primitive group id
	stream << primitiveGroup.m_ID;

	// Triangles, strips and fan offset index
	GLuint baseTrianglesOffseti;
	OffsetVectori stripIndexOffseti;
	OffsetVectori fanIndexOffseti;

	// Get triangles, strips and fans offset
	if (GLC_State::vboUsed())
	{
		// Convert offset to index
		// Triangles offset
		baseTrianglesOffseti= static_cast<GLuint>(reinterpret_cast<GLsizeiptr>(primitiveGroup.m_pBaseTrianglesOffset) / sizeof(GLuint));

		// Trips offsets
		for (int i= 0; i < primitiveGroup.m_TrianglesStripSize; ++i)
		{
			stripIndexOffseti.append(static_cast<GLuint>(reinterpret_cast<GLsizeiptr>(primitiveGroup.m_StripIndexOffset.at(i)) / sizeof(GLuint)));
		}
		// Fans offsets
		for (int i= 0; i < primitiveGroup.m_TrianglesFanSize; ++i)
		{
			fanIndexOffseti.append(static_cast<GLuint>(reinterpret_cast<GLsizeiptr>(primitiveGroup.m_FanIndexOffset.at(i)) / sizeof(GLuint)));
		}
	}
	else
	{
		baseTrianglesOffseti= primitiveGroup.m_BaseTrianglesOffseti;
		stripIndexOffseti= primitiveGroup.m_StripIndexOffseti;
		fanIndexOffseti= primitiveGroup.m_FanIndexOffseti;
	}
	// Triangles index
	stream << primitiveGroup.m_TrianglesIndexSize;
	stream << baseTrianglesOffseti;

	// Triangles strips index
	stream << primitiveGroup.m_TrianglesStripSize;
	stream << stripIndexOffseti;
	stream << primitiveGroup.m_StripIndexSizes;

	// Triangles fans index
	stream << primitiveGroup.m_TrianglesFanSize;
	stream << fanIndexOffseti;
	stream << primitiveGroup.m_FansIndexSizes;

	return stream;
}
QDataStream &operator>>(QDataStream &stream, GLC_PrimitiveGroup &primitiveGroup)
{
	quint32 chunckId;
	stream >> chunckId;
	Q_ASSERT(chunckId == GLC_BINARY_CHUNK_ID);
	stream >> primitiveGroup.m_ID;

	// Triangles index
	stream >> primitiveGroup.m_TrianglesIndexSize;
	stream >> primitiveGroup.m_BaseTrianglesOffseti;

	// Triangles strips index
	stream >> primitiveGroup.m_TrianglesStripSize;
	stream >> primitiveGroup.m_StripIndexOffseti;
	stream >> primitiveGroup.m_StripIndexSizes;

	// Triangles fans index
	stream >> primitiveGroup.m_TrianglesFanSize;
	stream >> primitiveGroup.m_FanIndexOffseti;
	stream >> primitiveGroup.m_FansIndexSizes;

	primitiveGroup.finished();

	return stream;
}

<commit_msg>Fix a bug in serialisation when VBO is activated.<commit_after>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.2.0, packaged on September 2009.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_primitivegroup.cpp implementation of the GLC_PrimitiveGroup class.

#include "glc_primitivegroup.h"
#include "../glc_state.h"

GLC_PrimitiveGroup::GLC_PrimitiveGroup(GLC_uint materialId)
: m_ID(materialId)
, m_TrianglesIndex()
, m_pBaseTrianglesOffset(NULL)
, m_BaseTrianglesOffseti(0)
, m_StripsIndex()
, m_StripIndexSizes()
, m_StripIndexOffset()
, m_StripIndexOffseti()
, m_FansIndex()
, m_FansIndexSizes()
, m_FanIndexOffset()
, m_FanIndexOffseti()
, m_IsFinished(false)
, m_TrianglesIndexSize(0)
, m_TrianglesStripSize(0)
, m_TrianglesFanSize(0)
{

}
//! Copy constructor
GLC_PrimitiveGroup::GLC_PrimitiveGroup(const GLC_PrimitiveGroup& group)
: m_ID(group.m_ID)
, m_TrianglesIndex(group.m_TrianglesIndex)
, m_pBaseTrianglesOffset(group.m_pBaseTrianglesOffset)
, m_BaseTrianglesOffseti(group.m_BaseTrianglesOffseti)
, m_StripsIndex(group.m_StripsIndex)
, m_StripIndexSizes(group.m_StripIndexSizes)
, m_StripIndexOffset(group.m_StripIndexOffset)
, m_StripIndexOffseti(group.m_StripIndexOffseti)
, m_FansIndex(group.m_FansIndex)
, m_FansIndexSizes(group.m_FansIndexSizes)
, m_FanIndexOffset(group.m_FanIndexOffset)
, m_FanIndexOffseti(group.m_FanIndexOffseti)
, m_IsFinished(group.m_IsFinished)
, m_TrianglesIndexSize(group.m_TrianglesIndexSize)
, m_TrianglesStripSize(group.m_TrianglesStripSize)
, m_TrianglesFanSize(group.m_TrianglesFanSize)
{

}

//! Copy constructor
GLC_PrimitiveGroup::GLC_PrimitiveGroup(const GLC_PrimitiveGroup& group, GLC_uint id)
: m_ID(id)
, m_TrianglesIndex(group.m_TrianglesIndex)
, m_pBaseTrianglesOffset(group.m_pBaseTrianglesOffset)
, m_BaseTrianglesOffseti(group.m_BaseTrianglesOffseti)
, m_StripsIndex(group.m_StripsIndex)
, m_StripIndexSizes(group.m_StripIndexSizes)
, m_StripIndexOffset(group.m_StripIndexOffset)
, m_StripIndexOffseti(group.m_StripIndexOffseti)
, m_FansIndex(group.m_FansIndex)
, m_FansIndexSizes(group.m_FansIndexSizes)
, m_FanIndexOffset(group.m_FanIndexOffset)
, m_FanIndexOffseti(group.m_FanIndexOffseti)
, m_IsFinished(group.m_IsFinished)
, m_TrianglesIndexSize(group.m_TrianglesIndexSize)
, m_TrianglesStripSize(group.m_TrianglesStripSize)
, m_TrianglesFanSize(group.m_TrianglesFanSize)
{

}

// = operator
GLC_PrimitiveGroup& GLC_PrimitiveGroup::operator=(const GLC_PrimitiveGroup& group)
{
	if (this != &group)
	{
		m_ID= group.m_ID;
		m_TrianglesIndex= group.m_TrianglesIndex;
		m_pBaseTrianglesOffset= group.m_pBaseTrianglesOffset;
		m_BaseTrianglesOffseti= group.m_BaseTrianglesOffseti;
		m_StripsIndex= group.m_StripsIndex;
		m_StripIndexSizes= group.m_StripIndexSizes;
		m_StripIndexOffset= group.m_StripIndexOffset;
		m_StripIndexOffseti= group.m_StripIndexOffseti;
		m_FansIndex= group.m_FansIndex;
		m_FansIndexSizes= group.m_FansIndexSizes;
		m_FanIndexOffset= group.m_FanIndexOffset;
		m_FanIndexOffseti= group.m_FanIndexOffseti;
		m_IsFinished= group.m_IsFinished;
		m_TrianglesIndexSize= group.m_TrianglesIndexSize;
		m_TrianglesStripSize= group.m_TrianglesStripSize;
		m_TrianglesFanSize= group.m_TrianglesFanSize;
	}
	return *this;
}

GLC_PrimitiveGroup::~GLC_PrimitiveGroup()
{

}

// Add triangle strip to the group
void GLC_PrimitiveGroup::addTrianglesStrip(const IndexList& input)
{
	m_StripsIndex+= input;
	m_TrianglesStripSize= m_StripsIndex.size();

	m_StripIndexSizes.append(static_cast<GLsizei>(input.size()));

	if (m_StripIndexOffseti.isEmpty())
	{
		m_StripIndexOffseti.append(0);
	}
	int offset= m_StripIndexOffseti.last() + m_StripIndexSizes.last();
	m_StripIndexOffseti.append(offset);
}

// Set base triangle strip offset
void GLC_PrimitiveGroup::setBaseTrianglesStripOffset(GLvoid* pOffset)
{
	m_StripIndexOffseti.pop_back();
	const int size= m_StripIndexOffseti.size();
	for (int i= 0; i < size; ++i)
	{
		m_StripIndexOffset.append(BUFFER_OFFSET(static_cast<GLsizei>(m_StripIndexOffseti[i]) * sizeof(GLuint) + reinterpret_cast<GLsizeiptr>(pOffset)));
	}
	m_StripIndexOffseti.clear();
}

// Set base triangle strip offset
void GLC_PrimitiveGroup::setBaseTrianglesStripOffseti(int offset)
{
	m_StripIndexOffseti.pop_back();
	const int size= m_StripIndexOffseti.size();
	for (int i= 0; i < size; ++i)
	{
		m_StripIndexOffseti[i]= m_StripIndexOffseti[i] + offset;
	}
}

//! Add triangle fan to the group
void GLC_PrimitiveGroup::addTrianglesFan(const IndexList& input)
{
	m_FansIndex+= input;
	m_TrianglesFanSize= m_FansIndex.size();

	m_FansIndexSizes.append(static_cast<GLsizei>(input.size()));

	if (m_FanIndexOffseti.isEmpty())
	{
		m_FanIndexOffseti.append(0);
	}
	int offset= m_FanIndexOffseti.last() + m_FansIndexSizes.last();
	m_FanIndexOffseti.append(offset);

}

// Set base triangle fan offset
void GLC_PrimitiveGroup::setBaseTrianglesFanOffset(GLvoid* pOffset)
{
	m_FanIndexOffseti.pop_back();
	const int size= m_FanIndexOffseti.size();
	for (int i= 0; i < size; ++i)
	{
		m_FanIndexOffset.append(BUFFER_OFFSET(static_cast<GLsizei>(m_FanIndexOffseti[i]) * sizeof(GLuint) + reinterpret_cast<GLsizeiptr>(pOffset)));
	}
	m_FanIndexOffseti.clear();
}

// Set base triangle fan offset
void GLC_PrimitiveGroup::setBaseTrianglesFanOffseti(int offset)
{
	m_FanIndexOffseti.pop_back();
	const int size= m_FanIndexOffseti.size();
	for (int i= 0; i < size; ++i)
	{
		m_FanIndexOffseti[i]= m_FanIndexOffseti[i] + offset;
	}
}

// Change index to VBO mode
void GLC_PrimitiveGroup::changeToVboMode()
{
	m_pBaseTrianglesOffset= BUFFER_OFFSET(static_cast<GLsizei>(m_BaseTrianglesOffseti) * sizeof(GLuint));
	m_BaseTrianglesOffseti= 0;

	m_StripIndexOffset.clear();
	const int stripOffsetSize= m_StripIndexOffseti.size();
	for (int i= 0; i < stripOffsetSize; ++i)
	{
		m_StripIndexOffset.append(BUFFER_OFFSET(static_cast<GLsizei>(m_StripIndexOffseti.at(i)) * sizeof(GLuint)));
	}
	m_StripIndexOffseti.clear();

	m_FanIndexOffset.clear();
	const int fanOffsetSize= m_FanIndexOffseti.size();
	for (int i= 0; i < fanOffsetSize; ++i)
	{
		m_FanIndexOffset.append(BUFFER_OFFSET(static_cast<GLsizei>(m_FanIndexOffseti.at(i)) * sizeof(GLuint)));
	}
	m_FanIndexOffseti.clear();
}

// Clear the group
void GLC_PrimitiveGroup::clear()
{
	m_TrianglesIndex.clear();
	m_pBaseTrianglesOffset= NULL;
	m_BaseTrianglesOffseti= 0;
	m_StripsIndex.clear();
	m_StripIndexSizes.clear();
	m_StripIndexOffset.clear();
	m_StripIndexOffseti.clear();
	m_FansIndex.clear();
	m_FansIndexSizes.clear();
	m_FanIndexOffset.clear();
	m_FanIndexOffseti.clear();
	m_IsFinished= false;
	m_TrianglesIndexSize= 0;
	m_TrianglesStripSize= 0;
	m_TrianglesFanSize= 0;
}

// Non Member methods
#define GLC_BINARY_CHUNK_ID 0xA700
// Non-member stream operator
QDataStream &operator<<(QDataStream &stream, const GLC_PrimitiveGroup &primitiveGroup)
{
	Q_ASSERT(primitiveGroup.isFinished());
	quint32 chunckId= GLC_BINARY_CHUNK_ID;
	stream << chunckId;

	// Primitive group id
	stream << primitiveGroup.m_ID;

	// Triangles, strips and fan offset index
	GLuint baseTrianglesOffseti;
	OffsetVectori stripIndexOffseti;
	OffsetVectori fanIndexOffseti;

	// Get triangles, strips and fans offset
	if (GLC_State::vboUsed())
	{
		// Convert offset to index
		// Triangles offset
		baseTrianglesOffseti= static_cast<GLuint>(reinterpret_cast<GLsizeiptr>(primitiveGroup.m_pBaseTrianglesOffset) / sizeof(GLuint));

		// Trips offsets
		const int stripIndexOffsetSize= primitiveGroup.m_StripIndexOffset.size();
		for (int i= 0; i < stripIndexOffsetSize; ++i)
		{
			stripIndexOffseti.append(static_cast<GLuint>(reinterpret_cast<GLsizeiptr>(primitiveGroup.m_StripIndexOffset.at(i)) / sizeof(GLuint)));
		}
		// Fans offsets
		const int fanIndexOffsetSize= primitiveGroup.m_FanIndexOffset.size();
		for (int i= 0; i < fanIndexOffsetSize; ++i)
		{
			fanIndexOffseti.append(static_cast<GLuint>(reinterpret_cast<GLsizeiptr>(primitiveGroup.m_FanIndexOffset.at(i)) / sizeof(GLuint)));
		}
	}
	else
	{
		baseTrianglesOffseti= primitiveGroup.m_BaseTrianglesOffseti;
		stripIndexOffseti= primitiveGroup.m_StripIndexOffseti;
		fanIndexOffseti= primitiveGroup.m_FanIndexOffseti;
	}
	// Triangles index
	stream << primitiveGroup.m_TrianglesIndexSize;
	stream << baseTrianglesOffseti;

	// Triangles strips index
	stream << primitiveGroup.m_TrianglesStripSize;
	stream << stripIndexOffseti;
	stream << primitiveGroup.m_StripIndexSizes;

	// Triangles fans index
	stream << primitiveGroup.m_TrianglesFanSize;
	stream << fanIndexOffseti;
	stream << primitiveGroup.m_FansIndexSizes;

	return stream;
}
QDataStream &operator>>(QDataStream &stream, GLC_PrimitiveGroup &primitiveGroup)
{
	quint32 chunckId;
	stream >> chunckId;
	Q_ASSERT(chunckId == GLC_BINARY_CHUNK_ID);
	stream >> primitiveGroup.m_ID;

	// Triangles index
	stream >> primitiveGroup.m_TrianglesIndexSize;
	stream >> primitiveGroup.m_BaseTrianglesOffseti;

	// Triangles strips index
	stream >> primitiveGroup.m_TrianglesStripSize;
	stream >> primitiveGroup.m_StripIndexOffseti;
	stream >> primitiveGroup.m_StripIndexSizes;

	// Triangles fans index
	stream >> primitiveGroup.m_TrianglesFanSize;
	stream >> primitiveGroup.m_FanIndexOffseti;
	stream >> primitiveGroup.m_FansIndexSizes;

	primitiveGroup.finished();

	return stream;
}

<|endoftext|>