<commit_before>/*************************************************************************/
/*  spin_box.cpp                                                         */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                    http://www.godotengine.org                         */
/*************************************************************************/
/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/
#include "spin_box.h"
#include "os/input.h"

Size2 SpinBox::get_minimum_size() const {

	Size2 ms = line_edit->get_combined_minimum_size();
	ms.width+=last_w;
	return ms;
}

void SpinBox::_value_changed(double) {

	String value = String::num(get_val(),Math::step_decimals(get_step()));
	if (prefix!="")
		value=prefix+" "+value;
	if (suffix!="")
		value+=" "+suffix;
	line_edit->set_text(value);
}

void SpinBox::_text_entered(const String& p_string) {

	//if (!p_string.is_numeric())
	//	return;
	String value = p_string;
	if (prefix!="" && p_string.begins_with(prefix))
		value = p_string.substr(prefix.length(), p_string.length()-prefix.length());
	set_val( value.to_double() );
	_value_changed(0);
}

LineEdit *SpinBox::get_line_edit() {

	return line_edit;
}

void SpinBox::_line_edit_input(const InputEvent& p_event) {

}

void SpinBox::_range_click_timeout() {

	if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {

		bool up = get_local_mouse_pos().y < (get_size().height/2);
		set_val( get_val() + (up?get_step():-get_step()));

		if (range_click_timer->is_one_shot()) {
			range_click_timer->set_wait_time(0.075);
			range_click_timer->set_one_shot(false);
			range_click_timer->start();
		}

	} else {
		range_click_timer->stop();
	}
}

void SpinBox::_input_event(const InputEvent& p_event) {

	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) {
		const InputEventMouseButton &mb=p_event.mouse_button;

		if (mb.doubleclick)
			return; //ignore doubleclick

		bool up = mb.y < (get_size().height/2);

		switch(mb.button_index) {

			case BUTTON_LEFT: {

				set_val( get_val() + (up?get_step():-get_step()));

				range_click_timer->set_wait_time(0.6);
				range_click_timer->set_one_shot(true);
				range_click_timer->start();

			} break;
			case BUTTON_RIGHT: {

				set_val(  (up?get_max():get_min()) );

			} break;
			case BUTTON_WHEEL_UP: {

				set_val( get_val() + get_step() );
			} break;
			case BUTTON_WHEEL_DOWN: {

				set_val( get_val() - get_step() );
			} break;
		}
	}

	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {

		//set_default_cursor_shape(CURSOR_VSIZE);
		Vector2 cpos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y);
		drag.mouse_pos=cpos;
	}

	if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {

		//set_default_cursor_shape(CURSOR_ARROW);
		range_click_timer->stop();

		if (drag.enabled) {
			drag.enabled=false;
			Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
			warp_mouse(drag.capture_pos);
		}
	}

	if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_button.button_mask&1) {

		Vector2 cpos = Vector2(p_event.mouse_motion.x,p_event.mouse_motion.y);
		if (drag.enabled) {

			float diff_y = drag.mouse_pos.y - cpos.y;
			diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y);
			diff_y*=0.1;

			drag.mouse_pos=cpos;
			drag.base_val=CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max());

			set_val( drag.base_val);

		} else if (drag.mouse_pos.distance_to(cpos)>2) {

			Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
			drag.enabled=true;
			drag.base_val=get_val();
			drag.mouse_pos=cpos;
			drag.capture_pos=cpos;

		}
	}
}

void SpinBox::_line_edit_focus_exit() {

	_text_entered(line_edit->get_text());
}

void SpinBox::_notification(int p_what) {

	if (p_what==NOTIFICATION_DRAW) {

		Ref<Texture> updown = get_icon("updown");

		int w = updown->get_width();
		if (w!=last_w) {
			line_edit->set_margin(MARGIN_RIGHT,w);
			last_w=w;
		}

		RID ci = get_canvas_item();
		Size2i size = get_size();

		updown->draw(ci,Point2i(size.width-updown->get_width(),(size.height-updown->get_height())/2));

	} else if (p_what==NOTIFICATION_FOCUS_EXIT) {

		//_value_changed(0);
	} else if (p_what==NOTIFICATION_ENTER_TREE) {

		_value_changed(0);
	}

}

void SpinBox::set_suffix(const String& p_suffix) {

	suffix=p_suffix;
	_value_changed(0);

}

String SpinBox::get_suffix() const{

	return suffix;
}

void SpinBox::set_prefix(const String& p_prefix) {

	prefix=p_prefix;
	_value_changed(0);

}

String SpinBox::get_prefix() const{

	return prefix;
}

void SpinBox::set_editable(bool p_editable) {
	line_edit->set_editable(p_editable);
}

bool SpinBox::is_editable() const {

	return line_edit->is_editable();
}

void SpinBox::_bind_methods() {

	//ObjectTypeDB::bind_method(_MD("_value_changed"),&SpinBox::_value_changed);
	ObjectTypeDB::bind_method(_MD("_input_event"),&SpinBox::_input_event);
	ObjectTypeDB::bind_method(_MD("_text_entered"),&SpinBox::_text_entered);
	ObjectTypeDB::bind_method(_MD("set_suffix","suffix"),&SpinBox::set_suffix);
	ObjectTypeDB::bind_method(_MD("get_suffix"),&SpinBox::get_suffix);
	ObjectTypeDB::bind_method(_MD("set_prefix","prefix"),&SpinBox::set_prefix);
	ObjectTypeDB::bind_method(_MD("get_prefix"),&SpinBox::get_prefix);
	ObjectTypeDB::bind_method(_MD("set_editable","editable"),&SpinBox::set_editable);
	ObjectTypeDB::bind_method(_MD("is_editable"),&SpinBox::is_editable);
	ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit);
	ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit);
	ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input);
	ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&SpinBox::_range_click_timeout);

	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable"));
	ADD_PROPERTY(PropertyInfo(Variant::STRING,"prefix"),_SCS("set_prefix"),_SCS("get_prefix"));
	ADD_PROPERTY(PropertyInfo(Variant::STRING,"suffix"),_SCS("set_suffix"),_SCS("get_suffix"));

}

SpinBox::SpinBox() {

	last_w = 0;
	line_edit = memnew( LineEdit );
	add_child(line_edit);

	line_edit->set_area_as_parent_rect();
	//connect("value_changed",this,"_value_changed");
	line_edit->connect("text_entered",this,"_text_entered",Vector<Variant>(),CONNECT_DEFERRED);
	line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED);
	line_edit->connect("input_event",this,"_line_edit_input");
	drag.enabled=false;

	range_click_timer = memnew( Timer );
	range_click_timer->connect("timeout",this,"_range_click_timeout");
	add_child(range_click_timer);
}
<commit_msg>Prevent Spinbox value update while not focused or disabled<commit_after>/*************************************************************************/
/*  spin_box.cpp                                                         */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                    http://www.godotengine.org                         */
/*************************************************************************/
/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/
#include "spin_box.h"
#include "os/input.h"

Size2 SpinBox::get_minimum_size() const {

	Size2 ms = line_edit->get_combined_minimum_size();
	ms.width+=last_w;
	return ms;
}

void SpinBox::_value_changed(double) {

	String value = String::num(get_val(),Math::step_decimals(get_step()));
	if (prefix!="")
		value=prefix+" "+value;
	if (suffix!="")
		value+=" "+suffix;
	line_edit->set_text(value);
}

void SpinBox::_text_entered(const String& p_string) {

	//if (!p_string.is_numeric())
	//	return;
	String value = p_string;
	if (prefix!="" && p_string.begins_with(prefix))
		value = p_string.substr(prefix.length(), p_string.length()-prefix.length());
	set_val( value.to_double() );
	_value_changed(0);
}

LineEdit *SpinBox::get_line_edit() {

	return line_edit;
}

void SpinBox::_line_edit_input(const InputEvent& p_event) {

}

void SpinBox::_range_click_timeout() {

	if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {

		bool up = get_local_mouse_pos().y < (get_size().height/2);
		set_val( get_val() + (up?get_step():-get_step()));

		if (range_click_timer->is_one_shot()) {
			range_click_timer->set_wait_time(0.075);
			range_click_timer->set_one_shot(false);
			range_click_timer->start();
		}

	} else {
		range_click_timer->stop();
	}
}

void SpinBox::_input_event(const InputEvent& p_event) {

	if (!is_editable()) {
		return;
	}
	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) {
		const InputEventMouseButton &mb=p_event.mouse_button;

		if (mb.doubleclick)
			return; //ignore doubleclick

		bool up = mb.y < (get_size().height/2);

		switch(mb.button_index) {

			case BUTTON_LEFT: {

				set_val( get_val() + (up?get_step():-get_step()));

				range_click_timer->set_wait_time(0.6);
				range_click_timer->set_one_shot(true);
				range_click_timer->start();

				line_edit->grab_focus();
			} break;
			case BUTTON_RIGHT: {

				set_val(  (up?get_max():get_min()) );
				line_edit->grab_focus();
			} break;
			case BUTTON_WHEEL_UP: {
				if (line_edit->has_focus()) {
					set_val( get_val() + get_step() );
					accept_event();
				}
			} break;
			case BUTTON_WHEEL_DOWN: {
				if (line_edit->has_focus()) {
					set_val( get_val() - get_step() );
					accept_event();
				}
			} break;
		}
	}

	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {

		//set_default_cursor_shape(CURSOR_VSIZE);
		Vector2 cpos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y);
		drag.mouse_pos=cpos;
	}

	if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {

		//set_default_cursor_shape(CURSOR_ARROW);
		range_click_timer->stop();

		if (drag.enabled) {
			drag.enabled=false;
			Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
			warp_mouse(drag.capture_pos);
		}
	}

	if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_button.button_mask&1) {

		Vector2 cpos = Vector2(p_event.mouse_motion.x,p_event.mouse_motion.y);
		if (drag.enabled) {

			float diff_y = drag.mouse_pos.y - cpos.y;
			diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y);
			diff_y*=0.1;

			drag.mouse_pos=cpos;
			drag.base_val=CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max());

			set_val( drag.base_val);

		} else if (drag.mouse_pos.distance_to(cpos)>2) {

			Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
			drag.enabled=true;
			drag.base_val=get_val();
			drag.mouse_pos=cpos;
			drag.capture_pos=cpos;

		}
	}
}

void SpinBox::_line_edit_focus_exit() {

	_text_entered(line_edit->get_text());
}

void SpinBox::_notification(int p_what) {

	if (p_what==NOTIFICATION_DRAW) {

		Ref<Texture> updown = get_icon("updown");

		int w = updown->get_width();
		if (w!=last_w) {
			line_edit->set_margin(MARGIN_RIGHT,w);
			last_w=w;
		}

		RID ci = get_canvas_item();
		Size2i size = get_size();

		updown->draw(ci,Point2i(size.width-updown->get_width(),(size.height-updown->get_height())/2));

	} else if (p_what==NOTIFICATION_FOCUS_EXIT) {

		//_value_changed(0);
	} else if (p_what==NOTIFICATION_ENTER_TREE) {

		_value_changed(0);
	}

}

void SpinBox::set_suffix(const String& p_suffix) {

	suffix=p_suffix;
	_value_changed(0);

}

String SpinBox::get_suffix() const{

	return suffix;
}

void SpinBox::set_prefix(const String& p_prefix) {

	prefix=p_prefix;
	_value_changed(0);

}

String SpinBox::get_prefix() const{

	return prefix;
}

void SpinBox::set_editable(bool p_editable) {
	line_edit->set_editable(p_editable);
}

bool SpinBox::is_editable() const {

	return line_edit->is_editable();
}

void SpinBox::_bind_methods() {

	//ObjectTypeDB::bind_method(_MD("_value_changed"),&SpinBox::_value_changed);
	ObjectTypeDB::bind_method(_MD("_input_event"),&SpinBox::_input_event);
	ObjectTypeDB::bind_method(_MD("_text_entered"),&SpinBox::_text_entered);
	ObjectTypeDB::bind_method(_MD("set_suffix","suffix"),&SpinBox::set_suffix);
	ObjectTypeDB::bind_method(_MD("get_suffix"),&SpinBox::get_suffix);
	ObjectTypeDB::bind_method(_MD("set_prefix","prefix"),&SpinBox::set_prefix);
	ObjectTypeDB::bind_method(_MD("get_prefix"),&SpinBox::get_prefix);
	ObjectTypeDB::bind_method(_MD("set_editable","editable"),&SpinBox::set_editable);
	ObjectTypeDB::bind_method(_MD("is_editable"),&SpinBox::is_editable);
	ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit);
	ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit);
	ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input);
	ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&SpinBox::_range_click_timeout);

	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable"));
	ADD_PROPERTY(PropertyInfo(Variant::STRING,"prefix"),_SCS("set_prefix"),_SCS("get_prefix"));
	ADD_PROPERTY(PropertyInfo(Variant::STRING,"suffix"),_SCS("set_suffix"),_SCS("get_suffix"));

}

SpinBox::SpinBox() {

	last_w = 0;
	line_edit = memnew( LineEdit );
	add_child(line_edit);

	line_edit->set_area_as_parent_rect();
	//connect("value_changed",this,"_value_changed");
	line_edit->connect("text_entered",this,"_text_entered",Vector<Variant>(),CONNECT_DEFERRED);
	line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED);
	line_edit->connect("input_event",this,"_line_edit_input");
	drag.enabled=false;

	range_click_timer = memnew( Timer );
	range_click_timer->connect("timeout",this,"_range_click_timeout");
	add_child(range_click_timer);
}
<|endoftext|>


<commit_before>/*
** Copyright 2014 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cstring>
#include "com/centreon/broker/bam/impact_values.hh"
#include "com/centreon/broker/bam/kpi_service.hh"
#include "com/centreon/broker/bam/kpi_status.hh"
#include "com/centreon/broker/bam/stream.hh"
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/neb/service_status.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::bam;

/**
 *  Default constructor.
 */
kpi_service::kpi_service()
  : _acknowledged(false),
    _downtimed(false),
    _host_id(0),
    _service_id(0),
    _state_hard(0),
    _state_soft(0),
    _state_type(0) {
  for (unsigned int i(0); i < sizeof(_impacts) / sizeof(*_impacts); ++i)
    _impacts[i] = 0.0;
}

/**
 *  Copy constructor.
 *
 *  @param[in] right Object to copy.
 */
kpi_service::kpi_service(kpi_service const& right)
  : service_listener(right), kpi(right) {
  _internal_copy(right);
}

/**
 *  Destructor.
 */
kpi_service::~kpi_service() {}

/**
 *  Assignment operator.
 *
 *  @param[in] right Object to copy.
 *
 *  @return This object.
 */
kpi_service& kpi_service::operator=(kpi_service const& right) {
  if (this != &right) {
    service_listener::operator=(right);
    kpi::operator=(right);
    _internal_copy(right);
  }
  return (*this);
}

/**
 *  Unused callback.
 *
 *  @param[in]  child    Unused.
 *  @param[out] visitor  Unused.
 *
 *  @return              True.
 */
bool kpi_service::child_has_update(computable* child, stream* visitor) {
  (void)child;
  (void)visitor;
  return true;
}

/**
 *  Get host ID.
 *
 *  @return Host ID.
 */
unsigned int kpi_service::get_host_id() const {
  return (_host_id);
}

/**
 *  Get the impact applied when service is CRITICAL.
 *
 *  @return The impact applied when service is CRITICAL.
 */
double kpi_service::get_impact_critical() const {
  return (_impacts[2]);
}

/**
 *  Get the impact applied when service is UNKNOWN.
 *
 *  @return The impact applied when service is UNKNOWN.
 */
double kpi_service::get_impact_unknown() const {
  return (_impacts[3]);
}

/**
 *  Get the impact applied when service is WARNING.
 *
 *  @return The impact applied when service is WARNING.
 */
double kpi_service::get_impact_warning() const {
  return (_impacts[1]);
}

/**
 *  Get the service ID.
 *
 *  @return Service ID.
 */
unsigned int kpi_service::get_service_id() const {
  return (_service_id);
}

/**
 *  Get the hard state of the service.
 *
 *  @return Hard state of the service.
 */
short kpi_service::get_state_hard() const {
  return (_state_hard);
}

/**
 *  Get the soft state of the service.
 *
 *  @return Soft state of the service.
 */
short kpi_service::get_state_soft() const {
  return (_state_soft);
}

/**
 *  Get current state type.
 *
 *  @return State type.
 */
short kpi_service::get_state_type() const {
  return (_state_type);
}

/**
 *  Compute impact implied by the hard service state.
 *
 *  @param[out] impact Impacts implied by the hard service state.
 */
void kpi_service::impact_hard(impact_values& impact) {
  _fill_impact(impact, _state_hard);
  return ;
}

/**
 *  Compute impact implied by the soft service state.
 *
 *  @param[out] impact Impacts implied by the soft service state.
 */
void kpi_service::impact_soft(impact_values& impact) {
  _fill_impact(impact, _state_soft);
  return ;
}

/**
 *  Check if service is in downtime.
 *
 *  @return True if the service is in downtime.
 */
bool kpi_service::in_downtime() const {
  return (_downtimed);
}

/**
 *  Check if service is acknowledged.
 *
 *  @return True if the service is acknowledged.
 */
bool kpi_service::is_acknowledged() const {
  return (_acknowledged);
}

/**
 *  Service got updated !
 *
 *  @param[in]  status   Service status.
 *  @param[out] visitor  Object that will receive events.
 */
void kpi_service::service_update(
                    misc::shared_ptr<neb::service_status> const& status,
                    stream* visitor) {
  if (!status.isNull()
      && (status->host_id == _host_id)
      && (status->service_id == _service_id)) {
    // Log.
    logging::debug(logging::low) << "BAM: updating KPI of service ("
      << status->host_id << ", " << status->service_id << ")";

    // Update information.
    _acknowledged = status->problem_has_been_acknowledged;
    _downtimed = status->scheduled_downtime_depth;
    _state_hard = status->last_hard_state;
    _state_soft = status->current_state;
    _state_type = status->state_type;

    // Generate status event.
    visit(visitor);

    // Propagate change.
    propagate_update(visitor);
  }
  return ;
}

/**
 *  Set service as acknowledged.
 *
 *  @param[in] acknowledged Acknowledged flag.
 */
void kpi_service::set_acknowledged(bool acknowledged) {
  _acknowledged = acknowledged;
  return ;
}

/**
 *  Set service as downtimed.
 *
 *  @param[in] downtimed Downtimed flag.
 */
void kpi_service::set_downtimed(bool downtimed) {
  _downtimed = downtimed;
  return ;
}

/**
 *  Set host ID.
 *
 *  @param[in] host_id Host ID.
 */
void kpi_service::set_host_id(unsigned int host_id) {
  _host_id = host_id;
  return ;
}

/**
 *  Set impact implied when service is CRITICAL.
 *
 *  @param[in] impact Impact if service is CRITICAL.
 */
void kpi_service::set_impact_critical(double impact) {
  _impacts[2] = impact;
  return ;
}

/**
 *  Set impact implied when service is UNKNOWN.
 *
 *  @param[in] impact Impact if service is UNKNOWN.
 */
void kpi_service::set_impact_unknown(double impact) {
  _impacts[3] = impact;
  return ;
}

/**
 *  Set impact implied when service is WARNING.
 *
 *  @param[in] impact Impact if service is WARNING.
 */
void kpi_service::set_impact_warning(double impact) {
  _impacts[1] = impact;
  return ;
}

/**
 *  Set service ID.
 *
 *  @param[in] service_id Service ID.
 */
void kpi_service::set_service_id(unsigned int service_id) {
  _service_id = service_id;
  return ;
}

/**
 *  Set hard state.
 *
 *  @param[in] state Service hard state.
 */
void kpi_service::set_state_hard(short state) {
  _state_hard = state;
  return ;
}

/**
 *  Set soft state.
 *
 *  @param[in] state Service soft state.
 */
void kpi_service::set_state_soft(short state) {
  _state_soft = state;
  return ;
}

/**
 *  Set state type.
 *
 *  @param[in] type Current state type.
 */
void kpi_service::set_state_type(short type) {
  _state_type = type;
  return ;
}

/**
 *  Visit service KPI.
 *
 *  @param[out] visitor  Object that will receive status.
 */
void kpi_service::visit(stream* visitor) {
  if (visitor) {
    // Get information.
    impact_values hard_values;
    impact_values soft_values;
    impact_hard(hard_values);
    impact_soft(soft_values);

    // Generate status event.
    misc::shared_ptr<kpi_status> status(new kpi_status);
    status->kpi_id = _id;
    status->level_acknowledgement_hard = hard_values.get_acknowledgement();
    status->level_acknowledgement_soft = soft_values.get_acknowledgement();
    status->level_downtime_hard = hard_values.get_downtime();
    status->level_downtime_soft = soft_values.get_downtime();
    status->level_nominal_hard = hard_values.get_nominal();
    status->level_nominal_soft = soft_values.get_nominal();
    status->state_hard = _state_hard;
    status->state_soft = _state_soft;
    visitor->write(status.staticCast<io::data>());

    // If no event was cached, create one.
    if (_event.isNull()) {
      _open_new_event();
      return ;
    }

    // If the status was changed, close the current event, write it
    // and create a new one
    if (_state_hard != _event->status) {
      _event->duration = std::difftime(time(NULL), _event->start_time);
      visitor->write(_event.staticCast<io::data>());
      _open_new_event();
    }
    return;
  }
}

/**
 *  Fill impact values from a state.
 *
 *  @param[out] impact Impacts of the state.
 *  @param[in]  state  Service state.
 */
void kpi_service::_fill_impact(impact_values& impact, short state) {
  if ((state < 0)
      || (static_cast<size_t>(state)
          >= (sizeof(_impacts) / sizeof(*_impacts))))
    throw (exceptions::msg()
           << "BAM: could not get impact introduced by state "
           << state);
  double nominal(_impacts[state]);
  impact.set_nominal(nominal);
  impact.set_acknowledgement(_acknowledged ? nominal : 0.0);
  impact.set_downtime(_downtimed ? nominal : 0.0);
  return ;
}

/**
 *  Copy internal data members.
 *
 *  @param[in] right Object to copy.
 */
void kpi_service::_internal_copy(kpi_service const& right) {
  _acknowledged = right._acknowledged;
  _downtimed = right._downtimed;
  _host_id = right._host_id;
  memcpy(_impacts, right._impacts, sizeof(_impacts));
  _service_id = right._service_id;
  _state_hard = right._state_hard;
  _state_soft = right._state_soft;
  _state_type = right._state_type;
  return ;
}

/**
 *  Open a new event for this kpi.
 */
void kpi_service::_open_new_event() {
  _event = new(kpi_event);

  _event->kpi_id = _id;
  _event->start_time = time(NULL);
  _event->status = _state_hard;
}
<commit_msg>BAM: Add downtime management for kpi event in kpi_service.<commit_after>/*
** Copyright 2014 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cstring>
#include "com/centreon/broker/bam/impact_values.hh"
#include "com/centreon/broker/bam/kpi_service.hh"
#include "com/centreon/broker/bam/kpi_status.hh"
#include "com/centreon/broker/bam/stream.hh"
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/neb/service_status.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::bam;

/**
 *  Default constructor.
 */
kpi_service::kpi_service()
  : _acknowledged(false),
    _downtimed(false),
    _host_id(0),
    _service_id(0),
    _state_hard(0),
    _state_soft(0),
    _state_type(0) {
  for (unsigned int i(0); i < sizeof(_impacts) / sizeof(*_impacts); ++i)
    _impacts[i] = 0.0;
}

/**
 *  Copy constructor.
 *
 *  @param[in] right Object to copy.
 */
kpi_service::kpi_service(kpi_service const& right)
  : service_listener(right), kpi(right) {
  _internal_copy(right);
}

/**
 *  Destructor.
 */
kpi_service::~kpi_service() {}

/**
 *  Assignment operator.
 *
 *  @param[in] right Object to copy.
 *
 *  @return This object.
 */
kpi_service& kpi_service::operator=(kpi_service const& right) {
  if (this != &right) {
    service_listener::operator=(right);
    kpi::operator=(right);
    _internal_copy(right);
  }
  return (*this);
}

/**
 *  Unused callback.
 *
 *  @param[in]  child    Unused.
 *  @param[out] visitor  Unused.
 *
 *  @return              True.
 */
bool kpi_service::child_has_update(computable* child, stream* visitor) {
  (void)child;
  (void)visitor;
  return true;
}

/**
 *  Get host ID.
 *
 *  @return Host ID.
 */
unsigned int kpi_service::get_host_id() const {
  return (_host_id);
}

/**
 *  Get the impact applied when service is CRITICAL.
 *
 *  @return The impact applied when service is CRITICAL.
 */
double kpi_service::get_impact_critical() const {
  return (_impacts[2]);
}

/**
 *  Get the impact applied when service is UNKNOWN.
 *
 *  @return The impact applied when service is UNKNOWN.
 */
double kpi_service::get_impact_unknown() const {
  return (_impacts[3]);
}

/**
 *  Get the impact applied when service is WARNING.
 *
 *  @return The impact applied when service is WARNING.
 */
double kpi_service::get_impact_warning() const {
  return (_impacts[1]);
}

/**
 *  Get the service ID.
 *
 *  @return Service ID.
 */
unsigned int kpi_service::get_service_id() const {
  return (_service_id);
}

/**
 *  Get the hard state of the service.
 *
 *  @return Hard state of the service.
 */
short kpi_service::get_state_hard() const {
  return (_state_hard);
}

/**
 *  Get the soft state of the service.
 *
 *  @return Soft state of the service.
 */
short kpi_service::get_state_soft() const {
  return (_state_soft);
}

/**
 *  Get current state type.
 *
 *  @return State type.
 */
short kpi_service::get_state_type() const {
  return (_state_type);
}

/**
 *  Compute impact implied by the hard service state.
 *
 *  @param[out] impact Impacts implied by the hard service state.
 */
void kpi_service::impact_hard(impact_values& impact) {
  _fill_impact(impact, _state_hard);
  return ;
}

/**
 *  Compute impact implied by the soft service state.
 *
 *  @param[out] impact Impacts implied by the soft service state.
 */
void kpi_service::impact_soft(impact_values& impact) {
  _fill_impact(impact, _state_soft);
  return ;
}

/**
 *  Check if service is in downtime.
 *
 *  @return True if the service is in downtime.
 */
bool kpi_service::in_downtime() const {
  return (_downtimed);
}

/**
 *  Check if service is acknowledged.
 *
 *  @return True if the service is acknowledged.
 */
bool kpi_service::is_acknowledged() const {
  return (_acknowledged);
}

/**
 *  Service got updated !
 *
 *  @param[in]  status   Service status.
 *  @param[out] visitor  Object that will receive events.
 */
void kpi_service::service_update(
                    misc::shared_ptr<neb::service_status> const& status,
                    stream* visitor) {
  if (!status.isNull()
      && (status->host_id == _host_id)
      && (status->service_id == _service_id)) {
    // Log.
    logging::debug(logging::low) << "BAM: updating KPI of service ("
      << status->host_id << ", " << status->service_id << ")";

    // Update information.
    _acknowledged = status->problem_has_been_acknowledged;
    _downtimed = status->scheduled_downtime_depth;
    _state_hard = status->last_hard_state;
    _state_soft = status->current_state;
    _state_type = status->state_type;

    // Generate status event.
    visit(visitor);

    // Propagate change.
    propagate_update(visitor);
  }
  return ;
}

/**
 *  Set service as acknowledged.
 *
 *  @param[in] acknowledged Acknowledged flag.
 */
void kpi_service::set_acknowledged(bool acknowledged) {
  _acknowledged = acknowledged;
  return ;
}

/**
 *  Set service as downtimed.
 *
 *  @param[in] downtimed Downtimed flag.
 */
void kpi_service::set_downtimed(bool downtimed) {
  _downtimed = downtimed;
  return ;
}

/**
 *  Set host ID.
 *
 *  @param[in] host_id Host ID.
 */
void kpi_service::set_host_id(unsigned int host_id) {
  _host_id = host_id;
  return ;
}

/**
 *  Set impact implied when service is CRITICAL.
 *
 *  @param[in] impact Impact if service is CRITICAL.
 */
void kpi_service::set_impact_critical(double impact) {
  _impacts[2] = impact;
  return ;
}

/**
 *  Set impact implied when service is UNKNOWN.
 *
 *  @param[in] impact Impact if service is UNKNOWN.
 */
void kpi_service::set_impact_unknown(double impact) {
  _impacts[3] = impact;
  return ;
}

/**
 *  Set impact implied when service is WARNING.
 *
 *  @param[in] impact Impact if service is WARNING.
 */
void kpi_service::set_impact_warning(double impact) {
  _impacts[1] = impact;
  return ;
}

/**
 *  Set service ID.
 *
 *  @param[in] service_id Service ID.
 */
void kpi_service::set_service_id(unsigned int service_id) {
  _service_id = service_id;
  return ;
}

/**
 *  Set hard state.
 *
 *  @param[in] state Service hard state.
 */
void kpi_service::set_state_hard(short state) {
  _state_hard = state;
  return ;
}

/**
 *  Set soft state.
 *
 *  @param[in] state Service soft state.
 */
void kpi_service::set_state_soft(short state) {
  _state_soft = state;
  return ;
}

/**
 *  Set state type.
 *
 *  @param[in] type Current state type.
 */
void kpi_service::set_state_type(short type) {
  _state_type = type;
  return ;
}

/**
 *  Visit service KPI.
 *
 *  @param[out] visitor  Object that will receive status.
 */
void kpi_service::visit(stream* visitor) {
  if (visitor) {
    // Get information.
    impact_values hard_values;
    impact_values soft_values;
    impact_hard(hard_values);
    impact_soft(soft_values);

    // Generate status event.
    misc::shared_ptr<kpi_status> status(new kpi_status);
    status->kpi_id = _id;
    status->level_acknowledgement_hard = hard_values.get_acknowledgement();
    status->level_acknowledgement_soft = soft_values.get_acknowledgement();
    status->level_downtime_hard = hard_values.get_downtime();
    status->level_downtime_soft = soft_values.get_downtime();
    status->level_nominal_hard = hard_values.get_nominal();
    status->level_nominal_soft = soft_values.get_nominal();
    status->state_hard = _state_hard;
    status->state_soft = _state_soft;
    visitor->write(status.staticCast<io::data>());

    // If no event was cached, create one.
    if (_event.isNull()) {
      _open_new_event();
      return ;
    }

    // If the status was changed, close the current event, write it
    // and create a new one
    if (_state_hard != _event->status ||
        _downtimed != _event->in_downtime) {
      _event->duration = std::difftime(time(NULL), _event->start_time);
      visitor->write(_event.staticCast<io::data>());
      _open_new_event();
    }
    return;
  }
}

/**
 *  Fill impact values from a state.
 *
 *  @param[out] impact Impacts of the state.
 *  @param[in]  state  Service state.
 */
void kpi_service::_fill_impact(impact_values& impact, short state) {
  if ((state < 0)
      || (static_cast<size_t>(state)
          >= (sizeof(_impacts) / sizeof(*_impacts))))
    throw (exceptions::msg()
           << "BAM: could not get impact introduced by state "
           << state);
  double nominal(_impacts[state]);
  impact.set_nominal(nominal);
  impact.set_acknowledgement(_acknowledged ? nominal : 0.0);
  impact.set_downtime(_downtimed ? nominal : 0.0);
  return ;
}

/**
 *  Copy internal data members.
 *
 *  @param[in] right Object to copy.
 */
void kpi_service::_internal_copy(kpi_service const& right) {
  _acknowledged = right._acknowledged;
  _downtimed = right._downtimed;
  _host_id = right._host_id;
  memcpy(_impacts, right._impacts, sizeof(_impacts));
  _service_id = right._service_id;
  _state_hard = right._state_hard;
  _state_soft = right._state_soft;
  _state_type = right._state_type;
  return ;
}

/**
 *  Open a new event for this kpi.
 */
void kpi_service::_open_new_event() {
  _event = new(kpi_event);

  _event->kpi_id = _id;
  _event->start_time = time(NULL);
  _event->status = _state_hard;
  _event->in_downtime = _downtimed;
}
<|endoftext|>


<commit_before>#include "LogicalDevice.hpp"

#include "Graphics/Graphics.hpp"
#include "Instance.hpp"
#include "PhysicalDevice.hpp"
#include "Surface.hpp"

namespace acid {
const std::vector<const char *> LogicalDevice::DeviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; // VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME

LogicalDevice::LogicalDevice(const Instance *instance, const PhysicalDevice *physicalDevice, const Surface *surface) :
	instance(instance),
	physicalDevice(physicalDevice),
	surface(surface) {
	CreateQueueIndices();
	CreateLogicalDevice();
}

LogicalDevice::~LogicalDevice() {
	Graphics::CheckVk(vkDeviceWaitIdle(logicalDevice));

	vkDestroyDevice(logicalDevice, nullptr);
}

void LogicalDevice::CreateQueueIndices() {
	uint32_t deviceQueueFamilyPropertyCount;
	vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &deviceQueueFamilyPropertyCount, nullptr);
	std::vector<VkQueueFamilyProperties> deviceQueueFamilyProperties(deviceQueueFamilyPropertyCount);
	vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &deviceQueueFamilyPropertyCount, deviceQueueFamilyProperties.data());

	std::optional<uint32_t> graphicsFamily, presentFamily, computeFamily, transferFamily;

	for (uint32_t i = 0; i < deviceQueueFamilyPropertyCount; i++) {
		// Check for graphics support.
		if (deviceQueueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
			graphicsFamily = i;
			this->graphicsFamily = i;
			supportedQueues |= VK_QUEUE_GRAPHICS_BIT;
		}

		// Check for presentation support.
		VkBool32 presentSupport;
		vkGetPhysicalDeviceSurfaceSupportKHR(*physicalDevice, i, *surface, &presentSupport);

		if (deviceQueueFamilyProperties[i].queueCount > 0 && presentSupport) {
			presentFamily = i;
			this->presentFamily = i;
		}

		// Check for compute support.
		if (deviceQueueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
			computeFamily = i;
			this->computeFamily = i;
			supportedQueues |= VK_QUEUE_COMPUTE_BIT;
		}

		// Check for transfer support.
		if (deviceQueueFamilyProperties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
			transferFamily = i;
			this->transferFamily = i;
			supportedQueues |= VK_QUEUE_TRANSFER_BIT;
		}

		if (graphicsFamily && presentFamily && computeFamily && transferFamily) {
			break;
		}
	}

	if (!graphicsFamily)
		throw std::runtime_error("Failed to find queue family supporting VK_QUEUE_GRAPHICS_BIT");
}

void LogicalDevice::CreateLogicalDevice() {
	auto physicalDeviceFeatures = physicalDevice->GetFeatures();

	std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
	float queuePriorities[1] = {0.0f};

	if (supportedQueues & VK_QUEUE_GRAPHICS_BIT) {
		VkDeviceQueueCreateInfo graphicsQueueCreateInfo = {};
		graphicsQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
		graphicsQueueCreateInfo.queueFamilyIndex = graphicsFamily;
		graphicsQueueCreateInfo.queueCount = 1;
		graphicsQueueCreateInfo.pQueuePriorities = queuePriorities;
		queueCreateInfos.emplace_back(graphicsQueueCreateInfo);
	} else {
		graphicsFamily = (uint32_t)VK_NULL_HANDLE;
	}

	if (supportedQueues & VK_QUEUE_COMPUTE_BIT && computeFamily != graphicsFamily) {
		VkDeviceQueueCreateInfo computeQueueCreateInfo = {};
		computeQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
		computeQueueCreateInfo.queueFamilyIndex = computeFamily;
		computeQueueCreateInfo.queueCount = 1;
		computeQueueCreateInfo.pQueuePriorities = queuePriorities;
		queueCreateInfos.emplace_back(computeQueueCreateInfo);
	} else {
		computeFamily = graphicsFamily;
	}

	if (supportedQueues & VK_QUEUE_TRANSFER_BIT && transferFamily != graphicsFamily && transferFamily != computeFamily) {
		VkDeviceQueueCreateInfo transferQueueCreateInfo = {};
		transferQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
		transferQueueCreateInfo.queueFamilyIndex = transferFamily;
		transferQueueCreateInfo.queueCount = 1;
		transferQueueCreateInfo.pQueuePriorities = queuePriorities;
		queueCreateInfos.emplace_back(transferQueueCreateInfo);
	} else {
		transferFamily = graphicsFamily;
	}

	VkPhysicalDeviceFeatures enabledFeatures = {};

	// Enable sample rate shading filtering if supported.
	if (physicalDeviceFeatures.sampleRateShading)
		enabledFeatures.sampleRateShading = VK_TRUE;

	// Fill mode non solid is required for wireframe display.
	if (physicalDeviceFeatures.fillModeNonSolid) {
		enabledFeatures.fillModeNonSolid = VK_TRUE;

		// Wide lines must be present for line width > 1.0f.
		if (physicalDeviceFeatures.wideLines)
			enabledFeatures.wideLines = VK_TRUE;
	} else {
		Log::Warning("Selected GPU does not support wireframe pipelines!\n");
	}

	if (physicalDeviceFeatures.samplerAnisotropy)
		enabledFeatures.samplerAnisotropy = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support sampler anisotropy!\n");

	if (physicalDeviceFeatures.textureCompressionBC)
		enabledFeatures.textureCompressionBC = VK_TRUE;
	else if (physicalDeviceFeatures.textureCompressionASTC_LDR)
		enabledFeatures.textureCompressionASTC_LDR = VK_TRUE;
	else if (physicalDeviceFeatures.textureCompressionETC2)
		enabledFeatures.textureCompressionETC2 = VK_TRUE;

	if (physicalDeviceFeatures.vertexPipelineStoresAndAtomics)
		enabledFeatures.vertexPipelineStoresAndAtomics = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support vertex pipeline stores and atomics!\n");

	if (physicalDeviceFeatures.fragmentStoresAndAtomics)
		enabledFeatures.fragmentStoresAndAtomics = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support fragment stores and atomics!\n");

	if (physicalDeviceFeatures.shaderStorageImageExtendedFormats)
		enabledFeatures.shaderStorageImageExtendedFormats = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support shader storage extended formats!\n");

	if (physicalDeviceFeatures.shaderStorageImageWriteWithoutFormat)
		enabledFeatures.shaderStorageImageWriteWithoutFormat = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support shader storage write without format!\n");

	//enabledFeatures.shaderClipDistance = VK_TRUE;
	//enabledFeatures.shaderCullDistance = VK_TRUE;

	if (physicalDeviceFeatures.geometryShader)
		enabledFeatures.geometryShader = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support geometry shaders!\n");

	if (physicalDeviceFeatures.tessellationShader)
		enabledFeatures.tessellationShader = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support tessellation shaders!\n");

	if (physicalDeviceFeatures.multiViewport)
		enabledFeatures.multiViewport = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support multi viewports!\n");

	VkDeviceCreateInfo deviceCreateInfo = {};
	deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
	deviceCreateInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
	deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
	if (instance->GetEnableValidationLayers()) {
		deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(Instance::ValidationLayers.size());
		deviceCreateInfo.ppEnabledLayerNames = Instance::ValidationLayers.data();
	}
	deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
	deviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.data();
	deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
	Graphics::CheckVk(vkCreateDevice(*physicalDevice, &deviceCreateInfo, nullptr, &logicalDevice));

	volkLoadDevice(logicalDevice);

	vkGetDeviceQueue(logicalDevice, graphicsFamily, 0, &graphicsQueue);
	vkGetDeviceQueue(logicalDevice, presentFamily, 0, &presentQueue);
	vkGetDeviceQueue(logicalDevice, computeFamily, 0, &computeQueue);
	vkGetDeviceQueue(logicalDevice, transferFamily, 0, &transferQueue);
}
}
<commit_msg>Update LogicalDevice.cpp<commit_after>#include "LogicalDevice.hpp"

#include "Graphics/Graphics.hpp"
#include "Instance.hpp"
#include "PhysicalDevice.hpp"
#include "Surface.hpp"

namespace acid {
const std::vector<const char *> LogicalDevice::DeviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; // VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME

LogicalDevice::LogicalDevice(const Instance *instance, const PhysicalDevice *physicalDevice, const Surface *surface) :
	instance(instance),
	physicalDevice(physicalDevice),
	surface(surface) {
	CreateQueueIndices();
	CreateLogicalDevice();
}

LogicalDevice::~LogicalDevice() {
	Graphics::CheckVk(vkDeviceWaitIdle(logicalDevice));

	vkDestroyDevice(logicalDevice, nullptr);
}

void LogicalDevice::CreateQueueIndices() {
	uint32_t deviceQueueFamilyPropertyCount;
	vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &deviceQueueFamilyPropertyCount, nullptr);
	std::vector<VkQueueFamilyProperties> deviceQueueFamilyProperties(deviceQueueFamilyPropertyCount);
	vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &deviceQueueFamilyPropertyCount, deviceQueueFamilyProperties.data());

	std::optional<uint32_t> graphicsFamily, presentFamily, computeFamily, transferFamily;

	for (uint32_t i = 0; i < deviceQueueFamilyPropertyCount; i++) {
		// Check for graphics support.
		if (deviceQueueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
			graphicsFamily = i;
			this->graphicsFamily = i;
			supportedQueues |= VK_QUEUE_GRAPHICS_BIT;
		}

		// Check for presentation support.
		VkBool32 presentSupport;
		vkGetPhysicalDeviceSurfaceSupportKHR(*physicalDevice, i, *surface, &presentSupport);

		if (deviceQueueFamilyProperties[i].queueCount > 0 && presentSupport) {
			presentFamily = i;
			this->presentFamily = i;
		}

		// Check for compute support.
		if (deviceQueueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
			computeFamily = i;
			this->computeFamily = i;
			supportedQueues |= VK_QUEUE_COMPUTE_BIT;
		}

		// Check for transfer support.
		if (deviceQueueFamilyProperties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
			transferFamily = i;
			this->transferFamily = i;
			supportedQueues |= VK_QUEUE_TRANSFER_BIT;
		}

		if (graphicsFamily && presentFamily && computeFamily && transferFamily) {
			break;
		}
	}

	if (!graphicsFamily)
		throw std::runtime_error("Failed to find queue family supporting VK_QUEUE_GRAPHICS_BIT");
}

void LogicalDevice::CreateLogicalDevice() {
	auto physicalDeviceFeatures = physicalDevice->GetFeatures();

	std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
	float queuePriorities[1] = {0.0f};

	if (supportedQueues & VK_QUEUE_GRAPHICS_BIT) {
		VkDeviceQueueCreateInfo graphicsQueueCreateInfo = {};
		graphicsQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
		graphicsQueueCreateInfo.queueFamilyIndex = graphicsFamily;
		graphicsQueueCreateInfo.queueCount = 1;
		graphicsQueueCreateInfo.pQueuePriorities = queuePriorities;
		queueCreateInfos.emplace_back(graphicsQueueCreateInfo);
	} else {
		graphicsFamily = 0; // VK_NULL_HANDLE;
	}

	if (supportedQueues & VK_QUEUE_COMPUTE_BIT && computeFamily != graphicsFamily) {
		VkDeviceQueueCreateInfo computeQueueCreateInfo = {};
		computeQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
		computeQueueCreateInfo.queueFamilyIndex = computeFamily;
		computeQueueCreateInfo.queueCount = 1;
		computeQueueCreateInfo.pQueuePriorities = queuePriorities;
		queueCreateInfos.emplace_back(computeQueueCreateInfo);
	} else {
		computeFamily = graphicsFamily;
	}

	if (supportedQueues & VK_QUEUE_TRANSFER_BIT && transferFamily != graphicsFamily && transferFamily != computeFamily) {
		VkDeviceQueueCreateInfo transferQueueCreateInfo = {};
		transferQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
		transferQueueCreateInfo.queueFamilyIndex = transferFamily;
		transferQueueCreateInfo.queueCount = 1;
		transferQueueCreateInfo.pQueuePriorities = queuePriorities;
		queueCreateInfos.emplace_back(transferQueueCreateInfo);
	} else {
		transferFamily = graphicsFamily;
	}

	VkPhysicalDeviceFeatures enabledFeatures = {};

	// Enable sample rate shading filtering if supported.
	if (physicalDeviceFeatures.sampleRateShading)
		enabledFeatures.sampleRateShading = VK_TRUE;

	// Fill mode non solid is required for wireframe display.
	if (physicalDeviceFeatures.fillModeNonSolid) {
		enabledFeatures.fillModeNonSolid = VK_TRUE;

		// Wide lines must be present for line width > 1.0f.
		if (physicalDeviceFeatures.wideLines)
			enabledFeatures.wideLines = VK_TRUE;
	} else {
		Log::Warning("Selected GPU does not support wireframe pipelines!\n");
	}

	if (physicalDeviceFeatures.samplerAnisotropy)
		enabledFeatures.samplerAnisotropy = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support sampler anisotropy!\n");

	if (physicalDeviceFeatures.textureCompressionBC)
		enabledFeatures.textureCompressionBC = VK_TRUE;
	else if (physicalDeviceFeatures.textureCompressionASTC_LDR)
		enabledFeatures.textureCompressionASTC_LDR = VK_TRUE;
	else if (physicalDeviceFeatures.textureCompressionETC2)
		enabledFeatures.textureCompressionETC2 = VK_TRUE;

	if (physicalDeviceFeatures.vertexPipelineStoresAndAtomics)
		enabledFeatures.vertexPipelineStoresAndAtomics = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support vertex pipeline stores and atomics!\n");

	if (physicalDeviceFeatures.fragmentStoresAndAtomics)
		enabledFeatures.fragmentStoresAndAtomics = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support fragment stores and atomics!\n");

	if (physicalDeviceFeatures.shaderStorageImageExtendedFormats)
		enabledFeatures.shaderStorageImageExtendedFormats = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support shader storage extended formats!\n");

	if (physicalDeviceFeatures.shaderStorageImageWriteWithoutFormat)
		enabledFeatures.shaderStorageImageWriteWithoutFormat = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support shader storage write without format!\n");

	//enabledFeatures.shaderClipDistance = VK_TRUE;
	//enabledFeatures.shaderCullDistance = VK_TRUE;

	if (physicalDeviceFeatures.geometryShader)
		enabledFeatures.geometryShader = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support geometry shaders!\n");

	if (physicalDeviceFeatures.tessellationShader)
		enabledFeatures.tessellationShader = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support tessellation shaders!\n");

	if (physicalDeviceFeatures.multiViewport)
		enabledFeatures.multiViewport = VK_TRUE;
	else
		Log::Warning("Selected GPU does not support multi viewports!\n");

	VkDeviceCreateInfo deviceCreateInfo = {};
	deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
	deviceCreateInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
	deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
	if (instance->GetEnableValidationLayers()) {
		deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(Instance::ValidationLayers.size());
		deviceCreateInfo.ppEnabledLayerNames = Instance::ValidationLayers.data();
	}
	deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
	deviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.data();
	deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
	Graphics::CheckVk(vkCreateDevice(*physicalDevice, &deviceCreateInfo, nullptr, &logicalDevice));

	volkLoadDevice(logicalDevice);

	vkGetDeviceQueue(logicalDevice, graphicsFamily, 0, &graphicsQueue);
	vkGetDeviceQueue(logicalDevice, presentFamily, 0, &presentQueue);
	vkGetDeviceQueue(logicalDevice, computeFamily, 0, &computeQueue);
	vkGetDeviceQueue(logicalDevice, transferFamily, 0, &transferQueue);
}
}
<|endoftext|>


<commit_before>#include "Object.h"
#include "../StarComponents.h"
#include "../Components/TransformComponent.h"
#include "../Graphics/GraphicsManager.h"
#include "../Scenes/BaseScene.h"
#include "../Physics/Collision/CollisionManager.h"
#include <algorithm>
#include <typeinfo>

namespace star
{
	Object::Object(void)
		: m_bIsInitialized(false)
		, m_IsVisible(true)
		, m_IsFrozen(false)
		, m_pParentGameObject(nullptr)
		, m_pPathFindComp(nullptr)
		, m_pScene(nullptr)
		, m_pComponents()
		, m_pGarbageComponents()
		, m_pChildren()
		, m_pGarbageChildren()
		, m_Name(_T("Default"))
		, m_CollisionTag(_T("Default"))
	{
		m_pComponents.push_back(new TransformComponent(this));
	}

	Object::~Object(void)
	{
		for(auto comp : m_pComponents)
		{
			delete comp;
		}
		m_pComponents.clear();

		for(auto child : m_pChildren)
		{
			delete child;
		}
		m_pChildren.clear();
	}

	Object* Object::GetParent() const
	{
		return (m_pParentGameObject);
	}

	void Object::BaseInitialize()
	{
		if (m_bIsInitialized)
		{
			return;
		}

		Initialize();
		for(auto comp : m_pComponents)
		{
			if(comp && !comp->IsInitialized())
			{
				comp->Initialize();
			}
		}

		for(auto child : m_pChildren)
		{
			if(child && !child->m_bIsInitialized)
			{
				child->BaseInitialize();
			}
		}
		BaseAfterInitialized();
		m_bIsInitialized = true;
	}

	void Object::Initialize()
	{
		//DO nothing, unless a derived class overrides this
	}

	void Object::BaseAfterInitialized()
	{
		AfterInitialized();
	}

	void Object::AfterInitialized()
	{
		//DO nothing, unless a derived class overrides this
	}

	void Object::Update(const Context& context)
	{
		//DO nothing, unless a derived class overrides this
	}

	void Object::BaseUpdate(const Context & context)
	{
		CollectGarbage();
		if(!m_IsFrozen)
		{
			Update(context);
			for(auto component : m_pComponents)
			{
				if(component)
				{
					component->BaseUpdate(context);
				}
			}

			for(auto child : m_pChildren)
			{
				if(child)
				{
					child->BaseUpdate(context);
				}
			}
		}
	}

	void Object::Draw()
	{
		//DO nothing, unless a derived class overrides this
	}

	void Object::BaseDraw()
	{
		if(m_IsVisible)
		{
			Draw();
			for(auto component : m_pComponents)
			{
				if(component)
				{
					component->BaseDraw();
				}
			}

			for(auto child : m_pChildren)
			{
				if(child)
				{
					child->BaseDraw();
				}
			}
		}
	}

	const tstring& Object::GetName() const
	{
		return m_Name;
	}

	void Object::SetName(const tstring& name)
	{
		m_Name = name;
	}

	void Object::AddComponent(BaseComponent *pComponent)
	{
		bool isValid(true);
		for(auto comp : m_pComponents)
		{
			if(typeid(*comp) == typeid(*pComponent))
			{
				isValid = false;
				break;
			}
		}

		ASSERT(isValid, _T("Adding 2 components of the same type to the same object is illegal."));

		if(isValid)
		{
			pComponent->SetParent(this);

			if(m_bIsInitialized && ! pComponent->IsInitialized())
			{
				pComponent->Initialize();
			}

			m_pComponents.push_back(pComponent);
		}
	}

	void Object::AddChild(Object *pChild)
	{
		pChild->m_pParentGameObject = this;

		if(m_bIsInitialized && !pChild->m_bIsInitialized)
		{
			pChild->BaseInitialize();
		}

		m_pChildren.push_back(pChild);

		//Logger::GetInstance()->Log(LogLevel::Info, _T("Child Added"));
	}

	void Object::RemoveChild(const Object* pObject)
	{
		auto it = std::find(m_pChildren.begin(), m_pChildren.end(), pObject);
		ASSERT(it != m_pChildren.end(), _T("Object::RemoveChild: \
										   The object you tried to remove is not a child of this object!"));
		m_pGarbageChildren.push_back(*it);
	}

	std::vector<Object*>& Object::GetChildren()
	{
		return m_pChildren;
	}

	void Object::SetVisible(bool visible)
	{
		m_IsVisible = visible;
	}

	bool Object::IsVisible() const
	{
		return m_IsVisible;
	}

	void Object::Freeze(bool freeze)
	{
		m_IsFrozen = freeze;
	}

	bool Object::IsFrozen() const
	{
		return m_IsFrozen;
	}

	void Object::SetDisabled(bool disabled)
	{
		m_IsVisible = !disabled;
		m_IsFrozen = disabled;
	}

	bool Object::IsDisabled() const
	{
		return !m_IsVisible && m_IsFrozen;
	}

	void Object::SetScene(BaseScene * pScene)
	{
		m_pScene = pScene;
	}

	void Object::UnsetScene()
	{
		m_pScene = nullptr;
	}

	TransformComponent * Object::GetTransform() const
	{
		return GetComponent<TransformComponent>();
	}

	BaseScene * Object::GetScene() const
	{
		return m_pScene;
	}

	void Object::CollectGarbage()
	{
		for(auto component : m_pGarbageComponents)
		{
			auto it = std::find(m_pComponents.begin(), m_pComponents.end(), component);
			ASSERT(it != m_pComponents.end(), _T("Object::CollectGarbage: \
												 trying to delete unknown object!"));
			m_pComponents.erase(it);
			delete component;
			Logger::GetInstance()->Log(LogLevel::Info, _T("Component Removed"));
		}
		m_pGarbageComponents.clear();

		for(auto child : m_pGarbageChildren)
		{
			auto it = std::find(m_pChildren.begin(), m_pChildren.end(), child);
			ASSERT(it != m_pChildren.end(), _T("Object::CollectGarbage: \
												 trying to delete unknown child!"));
			m_pChildren.erase(it);
			delete child;
			Logger::GetInstance()->Log(LogLevel::Info, _T("Child Removed"));
		}
		m_pGarbageChildren.clear();
	}
}
<commit_msg>Cleaned up some code<commit_after>#include "Object.h"
#include "../StarComponents.h"
#include "../Components/TransformComponent.h"
#include "../Graphics/GraphicsManager.h"
#include "../Scenes/BaseScene.h"
#include "../Physics/Collision/CollisionManager.h"
#include <algorithm>
#include <typeinfo>

namespace star
{
	Object::Object(void)
		: m_bIsInitialized(false)
		, m_IsVisible(true)
		, m_IsFrozen(false)
		, m_pParentGameObject(nullptr)
		, m_pPathFindComp(nullptr)
		, m_pScene(nullptr)
		, m_pComponents()
		, m_pGarbageComponents()
		, m_pChildren()
		, m_pGarbageChildren()
		, m_Name(_T("Default"))
		, m_CollisionTag(_T("Default"))
	{
		m_pComponents.push_back(new TransformComponent(this));
	}

	Object::~Object(void)
	{
		for(auto comp : m_pComponents)
		{
			delete comp;
		}
		m_pComponents.clear();

		for(auto child : m_pChildren)
		{
			delete child;
		}
		m_pChildren.clear();
	}

	Object* Object::GetParent() const
	{
		return (m_pParentGameObject);
	}

	void Object::BaseInitialize()
	{
		if (m_bIsInitialized)
		{
			return;
		}

		Initialize();
		for(auto comp : m_pComponents)
		{
			if(comp && !comp->IsInitialized())
			{
				comp->Initialize();
			}
		}

		for(auto child : m_pChildren)
		{
			if(child && !child->m_bIsInitialized)
			{
				child->BaseInitialize();
			}
		}
		BaseAfterInitialized();
		m_bIsInitialized = true;
	}

	void Object::Initialize()
	{
		//DO nothing, unless a derived class overrides this
	}

	void Object::BaseAfterInitialized()
	{
		AfterInitialized();
	}

	void Object::AfterInitialized()
	{
		//DO nothing, unless a derived class overrides this
	}

	void Object::Update(const Context& context)
	{
		//DO nothing, unless a derived class overrides this
	}

	void Object::BaseUpdate(const Context & context)
	{
		CollectGarbage();
		if(!m_IsFrozen)
		{
			Update(context);
			for(auto component : m_pComponents)
			{
				if(component)
				{
					component->BaseUpdate(context);
				}
			}

			for(auto child : m_pChildren)
			{
				if(child)
				{
					child->BaseUpdate(context);
				}
			}
		}
	}

	void Object::Draw()
	{
		//DO nothing, unless a derived class overrides this
	}

	void Object::BaseDraw()
	{
		if(m_IsVisible)
		{
			Draw();
			for(auto component : m_pComponents)
			{
				if(component)
				{
					component->BaseDraw();
				}
			}

			for(auto child : m_pChildren)
			{
				if(child)
				{
					child->BaseDraw();
				}
			}
		}
	}

	const tstring& Object::GetName() const
	{
		return m_Name;
	}

	void Object::SetName(const tstring& name)
	{
		m_Name = name;
	}

	void Object::AddComponent(BaseComponent *pComponent)
	{
		for(auto comp : m_pComponents)
		{
			ASSERT(typeid(*comp) != typeid(*pComponent),
				_T("Object::AddComponent: \
				   Adding 2 components of the same type to the same object is illegal."));
		}

		pComponent->SetParent(this);

		if(m_bIsInitialized && ! pComponent->IsInitialized())
		{
			pComponent->Initialize();
		}

		m_pComponents.push_back(pComponent);
	}

	void Object::AddChild(Object *pChild)
	{
		pChild->m_pParentGameObject = this;

		if(m_bIsInitialized && !pChild->m_bIsInitialized)
		{
			pChild->BaseInitialize();
		}

		m_pChildren.push_back(pChild);

		//Logger::GetInstance()->Log(LogLevel::Info, _T("Child Added"));
	}

	void Object::RemoveChild(const Object* pObject)
	{
		auto it = std::find(m_pChildren.begin(), m_pChildren.end(), pObject);
		ASSERT(it != m_pChildren.end(), _T("Object::RemoveChild: \
										   The object you tried to remove is not a child of this object!"));
		m_pGarbageChildren.push_back(*it);
	}

	std::vector<Object*>& Object::GetChildren()
	{
		return m_pChildren;
	}

	void Object::SetVisible(bool visible)
	{
		m_IsVisible = visible;
	}

	bool Object::IsVisible() const
	{
		return m_IsVisible;
	}

	void Object::Freeze(bool freeze)
	{
		m_IsFrozen = freeze;
	}

	bool Object::IsFrozen() const
	{
		return m_IsFrozen;
	}

	void Object::SetDisabled(bool disabled)
	{
		m_IsVisible = !disabled;
		m_IsFrozen = disabled;
	}

	bool Object::IsDisabled() const
	{
		return !m_IsVisible && m_IsFrozen;
	}

	void Object::SetScene(BaseScene * pScene)
	{
		m_pScene = pScene;
	}

	void Object::UnsetScene()
	{
		m_pScene = nullptr;
	}

	TransformComponent * Object::GetTransform() const
	{
		return GetComponent<TransformComponent>();
	}

	BaseScene * Object::GetScene() const
	{
		return m_pScene;
	}

	void Object::CollectGarbage()
	{
		for(auto component : m_pGarbageComponents)
		{
			auto it = std::find(m_pComponents.begin(), m_pComponents.end(), component);
			ASSERT(it != m_pComponents.end(), _T("Object::CollectGarbage: \
												 trying to delete unknown object!"));
			m_pComponents.erase(it);
			delete component;
			Logger::GetInstance()->Log(LogLevel::Info, _T("Component Removed"));
		}
		m_pGarbageComponents.clear();

		for(auto child : m_pGarbageChildren)
		{
			auto it = std::find(m_pChildren.begin(), m_pChildren.end(), child);
			ASSERT(it != m_pChildren.end(), _T("Object::CollectGarbage: \
												 trying to delete unknown child!"));
			m_pChildren.erase(it);
			delete child;
			Logger::GetInstance()->Log(LogLevel::Info, _T("Child Removed"));
		}
		m_pGarbageChildren.clear();
	}
}
<|endoftext|>


<commit_before>#include <QString>
#include <typeinfo>
#include "kernel.h"
#include "range.h"
#include "domainitem.h"
#include "numericrange.h"
#include "domainitem.h"
#include "numericitem.h"
#include "itemrange.h"
#include "numericitemrange.h"

using namespace Ilwis;

NumericItemRange::NumericItemRange()
{
    _vt = itNUMERICITEM;
}

QString NumericItemRange::value(quint32 index) const
{
    if ( index < _items.size())
        return _items[index]->name();
    return sUNDEF;

}

quint32 NumericItemRange::count() const
{
    return _items.size();
}

SPDomainItem NumericItemRange::item(quint32 index) const
{
       if ( index < _items.size())
           return _items[index];
       return SPDomainItem();
}

SPDomainItem NumericItemRange::item(const QString &name) const
{
    for(const SPNumericItem& it: _items) {
        if ( it->name() == name)
            return it;
    }
    return SPDomainItem();
}

double NumericItemRange::index(double v) const
{
    if (!isValid())
        return rUNDEF;

    for(quint32 ind = 0; ind < _items.size(); ++ind) {
        quint32 mark1=iUNDEF, mark2=iUNDEF;
        const NumericRange& rng = _items[ind]->range();
        if ( v >= rng.min()){
            mark1 = ind;
        }
        if ( v <= rng.max()){
            mark2 = ind;
        }
        if ( mark1 != iUNDEF && mark2 != iUNDEF) {
            if ( isContinous())
                return ind + (v - rng.min()) / rng.distance();
            return ind;
        }
    }
    return rUNDEF;
}

bool NumericItemRange::contains(const QString &name) const
{
    for(const SPNumericItem& it: _items) {
        if ( it->name() == name)
            return true;
    }
    return false;
}

bool NumericItemRange::isValid() const
{
    return _items.size() != 0;
}

void NumericItemRange::add(DomainItem *item)
{
    if (!item)
        return;

    if ( item->valueType() != itNUMERICITEM)
        return;

    if (!item->isValid())
        return;
    SPNumericItem nitem(static_cast<NumericItem *>(item));
    for(auto iter = _items.rbegin(); iter != _items.rend(); ++iter) {
        if ( nitem->range() > (*iter)->range()) {
            _items.insert(iter.base(),1, nitem );
            return;
        }
    }
    if ( _items.size() == 0) // no overlapping items allowed; so the only case that is legal here is the first
        _items.push_back(nitem);

}

void NumericItemRange::remove(const QString &nm)
{
     for(auto iter = _items.begin(); iter != _items.begin(); ++iter) {
        if ( (*iter)->name() == nm) {
            _items.erase(iter);
        }
     }
}

QString NumericItemRange::toString() const
{   if ( _items.size() == 0)
        return sUNDEF;
    QString names;
    for(const SPNumericItem& it: _items) {
        if ( names != "")
            names += ";";
        names += it->name();
    }
    return names;
}

ItemRange *NumericItemRange::clone() const
{
    ItemRange *items = new NumericItemRange();
    for(const SPNumericItem& it: _items) {
        items->add(it->clone());
    }

    return items;

}

NumericItemRange &NumericItemRange::operator <<(const QString &itemdef)
{
    QStringList parts = itemdef.split(" ");
    if( parts.size() > 1) {
        bool ok;
        double step = 0;
        double mn = parts[0].toDouble(&ok);
        if(ok) {
            double mx = parts[1].toDouble(&ok);
            if ( ok) {
                if ( parts.size() == 3) {
                    step = parts[2].toDouble(&ok);

                }
                if (ok) {
                    add(new NumericItem({mn,mx, step}));
                }
            }
        }
        ERROR1(ERR_NO_INITIALIZED_1, "numeric item range");
    } if ( parts.size() == 1) {
        if ( count() == 0) {
            ERROR1(ERR_NO_INITIALIZED_1, "numeric item range");
            return *this;
        }
        bool ok;
        double vmin = _items[_items.size() - 1]->range().max();
        double vmax = itemdef.toDouble(&ok) ;
        if (!ok) {
            ERROR1(ERR_NO_INITIALIZED_1, "numeric item range");
        }
        double step = _items[0]->range().step();
        if ( step == 0)
            vmin += EPS8;
        add(new NumericItem({vmin+step,vmax, step}));
    }
    return *this;
}

bool NumericItemRange::isContinous() const
{
    return _interpolation != "";
}

QString NumericItemRange::interpolation() const
{
    return _interpolation;
}

void NumericItemRange::interpolation(const QString &ip)
{
    _interpolation = ip;
}

void NumericItemRange::addRange(const ItemRange &range)
{
    ItemRange::addRange(range);
    _interpolation = static_cast<const NumericItemRange&>(range).interpolation();
}

<commit_msg>fall through wasnt correct in the '<<' overload. Generated an error message in the log file which wasnt needed (worked ok though)<commit_after>#include <QString>
#include <typeinfo>
#include "kernel.h"
#include "range.h"
#include "domainitem.h"
#include "numericrange.h"
#include "domainitem.h"
#include "numericitem.h"
#include "itemrange.h"
#include "numericitemrange.h"

using namespace Ilwis;

NumericItemRange::NumericItemRange()
{
    _vt = itNUMERICITEM;
}

QString NumericItemRange::value(quint32 index) const
{
    if ( index < _items.size())
        return _items[index]->name();
    return sUNDEF;

}

quint32 NumericItemRange::count() const
{
    return _items.size();
}

SPDomainItem NumericItemRange::item(quint32 index) const
{
       if ( index < _items.size())
           return _items[index];
       return SPDomainItem();
}

SPDomainItem NumericItemRange::item(const QString &name) const
{
    for(const SPNumericItem& it: _items) {
        if ( it->name() == name)
            return it;
    }
    return SPDomainItem();
}

double NumericItemRange::index(double v) const
{
    if (!isValid())
        return rUNDEF;

    for(quint32 ind = 0; ind < _items.size(); ++ind) {
        quint32 mark1=iUNDEF, mark2=iUNDEF;
        const NumericRange& rng = _items[ind]->range();
        if ( v >= rng.min()){
            mark1 = ind;
        }
        if ( v <= rng.max()){
            mark2 = ind;
        }
        if ( mark1 != iUNDEF && mark2 != iUNDEF) {
            if ( isContinous())
                return ind + (v - rng.min()) / rng.distance();
            return ind;
        }
    }
    return rUNDEF;
}

bool NumericItemRange::contains(const QString &name) const
{
    for(const SPNumericItem& it: _items) {
        if ( it->name() == name)
            return true;
    }
    return false;
}

bool NumericItemRange::isValid() const
{
    return _items.size() != 0;
}

void NumericItemRange::add(DomainItem *item)
{
    if (!item)
        return;

    if ( item->valueType() != itNUMERICITEM)
        return;

    if (!item->isValid())
        return;
    SPNumericItem nitem(static_cast<NumericItem *>(item));
    for(auto iter = _items.rbegin(); iter != _items.rend(); ++iter) {
        if ( nitem->range() > (*iter)->range()) {
            _items.insert(iter.base(),1, nitem );
            return;
        }
    }
    if ( _items.size() == 0) // no overlapping items allowed; so the only case that is legal here is the first
        _items.push_back(nitem);

}

void NumericItemRange::remove(const QString &nm)
{
     for(auto iter = _items.begin(); iter != _items.begin(); ++iter) {
        if ( (*iter)->name() == nm) {
            _items.erase(iter);
        }
     }
}

QString NumericItemRange::toString() const
{   if ( _items.size() == 0)
        return sUNDEF;
    QString names;
    for(const SPNumericItem& it: _items) {
        if ( names != "")
            names += ";";
        names += it->name();
    }
    return names;
}

ItemRange *NumericItemRange::clone() const
{
    ItemRange *items = new NumericItemRange();
    for(const SPNumericItem& it: _items) {
        items->add(it->clone());
    }

    return items;

}

NumericItemRange &NumericItemRange::operator <<(const QString &itemdef)
{
    QStringList parts = itemdef.split(" ");
    if( parts.size() > 1) {
        bool ok;
        double step = 0;
        double mn = parts[0].toDouble(&ok);
        if(ok) {
            double mx = parts[1].toDouble(&ok);
            if ( ok) {
                if ( parts.size() == 3) {
                    step = parts[2].toDouble(&ok);

                }
                if (ok) {
                    add(new NumericItem({mn,mx, step}));
                    return *this;
                }
            }
        }
        ERROR1(ERR_NO_INITIALIZED_1, "numeric item range");
    } if ( parts.size() == 1) {
        if ( count() == 0) {
            ERROR1(ERR_NO_INITIALIZED_1, "numeric item range");
            return *this;
        }
        bool ok;
        double vmin = _items[_items.size() - 1]->range().max();
        double vmax = itemdef.toDouble(&ok) ;
        if (!ok) {
            ERROR1(ERR_NO_INITIALIZED_1, "numeric item range");
        }
        double step = _items[0]->range().step();
        if ( step == 0)
            vmin += EPS8;
        add(new NumericItem({vmin+step,vmax, step}));
    }
    return *this;
}

bool NumericItemRange::isContinous() const
{
    return _interpolation != "";
}

QString NumericItemRange::interpolation() const
{
    return _interpolation;
}

void NumericItemRange::interpolation(const QString &ip)
{
    _interpolation = ip;
}

void NumericItemRange::addRange(const ItemRange &range)
{
    ItemRange::addRange(range);
    _interpolation = static_cast<const NumericItemRange&>(range).interpolation();
}

<|endoftext|>


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

// This include needs to be the very first to prevent problems with warnings
// regarding redefinition of _POSIX_C_SOURCE
#include <boost/python.hpp>

#include <iostream>

#include "IECore/IndexedIOInterface.h"
#include "IECore/FileSystemIndexedIO.h"
#include "IECore/SQLiteIndexedIO.h"
#include "IECore/FileIndexedIO.h"
#include "IECore/VectorTypedData.h"
#include "IECore/bindings/IntrusivePtrPatch.h"

using namespace boost::python;
using namespace IECore;

void bindIndexedIOEntry(const char *bindName);
void bindIndexedIOEntryList(const char *bindName);

void bindIndexedIOFilter(const char *bindName);
void bindIndexedIONullFilter(const char *bindName);
void bindIndexedIOEntryTypeFilter(const char *bindName);
void bindIndexedIORegexFilter(const char *bindName);

void bindIndexedIOInterface(const char *bindName);
void bindFileSystemIndexedIO(const char *bindName);
void bindSQLiteIndexedIO(const char *bindName);
void bindFileIndexedIO(const char *bindName);

void stupidTest();

void bindIndexedIO()
{
	bindIndexedIOEntry("IndexedIOEntry");
	bindIndexedIOEntryList("IndexedIOEntryList");

	bindIndexedIOFilter("IndexedIOFilter");
	bindIndexedIONullFilter("IndexedIONullFilter");
	bindIndexedIOEntryTypeFilter("IndexedIOEntryTypeFilter");
	bindIndexedIORegexFilter("IndexedIORegexFilter");

	bindIndexedIOInterface("IndexedIOInterface");
	bindFileSystemIndexedIO("FileSystemIndexedIO");
#ifdef IECORE_WITH_SQLITE
	bindSQLiteIndexedIO("SQLiteIndexedIO");
#endif // IECORE_WITH_SQLITE
	bindFileIndexedIO("FileIndexedIO");
}

struct IndexedIOInterfaceHelper
{
	static IndexedIO::Entry ls(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name)
	{
		assert(p);

		return p->ls(name);
	}

	static IndexedIO::EntryList ls(IndexedIOInterfacePtr p)
	{
		assert(p);

		return p->ls();
	}

	static IndexedIO::EntryList ls(IndexedIOInterfacePtr p, IndexedIOFilterPtr f)
	{
		assert(p);

		return p->ls(f);
	}

	template<typename T>
	static void writeVector(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name,
		const boost::intrusive_ptr< TypedData < T > > &x)
	{
		assert(p);

		const typename T::value_type *data = &(x->readable())[0];
		p->write( name, data, (unsigned long)x->readable().size() );
	}

	template<typename T>
	static boost::intrusive_ptr<TypedData<T> > readSingle(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name, const IndexedIO::Entry &entry)
	{
		T data;
		p->read(name, data);
		return new TypedData<T>( data );
	}

	template<typename T>
	static boost::intrusive_ptr<TypedData< std::vector<T> > > readArray(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name, const IndexedIO::Entry &entry)
	{
		unsigned long count = entry.arrayLength();
		boost::intrusive_ptr< TypedData<std::vector<T> > > x = new TypedData<std::vector<T> > ();
		x->writable().resize( entry.arrayLength() );
		T *data = &(x->writable()[0]);
		p->read(name, data, count);

		return x;
	}

	static DataPtr read(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name)
	{
		assert(p);

		IndexedIO::Entry entry = p->ls(name);

		switch( entry.dataType() )
		{
			case IndexedIO::Float:
				return readSingle<float>(p, name, entry);
			case IndexedIO::Double:
				return readSingle<double>(p, name, entry);
			case IndexedIO::Int:
				return readSingle<int>(p, name, entry);
			case IndexedIO::Long:
				return readSingle<long>(p, name, entry);
			case IndexedIO::String:
				return readSingle<std::string>(p, name, entry);
			case IndexedIO::StringArray:
				return readArray<std::string>(p, name, entry);
			case IndexedIO::FloatArray:
				return readArray<float>(p, name, entry);
			case IndexedIO::DoubleArray:
				return readArray<double>(p, name, entry);
			case IndexedIO::IntArray:
				return readArray<int>(p, name, entry);
			case IndexedIO::LongArray:
				return readArray<long>(p, name, entry);
			case IndexedIO::UInt:
				return readSingle<unsigned int>(p, name, entry);
			case IndexedIO::UIntArray:
				return readArray<unsigned int>(p, name, entry);
			case IndexedIO::Char:
				return readSingle<char>(p, name, entry);
			case IndexedIO::CharArray:
				return readArray<char>(p, name, entry);
			case IndexedIO::UChar:
				return readSingle<unsigned char>(p, name, entry);
			case IndexedIO::UCharArray:
				return readArray<unsigned char>(p, name, entry);
			default:
				throw IOException(name);
		}
	}

	static std::string readString(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name)
	{
		assert(p);

		std::string x;
		p->read(name, x);
		return x;
	}
};

void bindIndexedIOInterface(const char *bindName)
{
	IndexedIO::EntryList (*lsNoFilter)(IndexedIOInterfacePtr) = &IndexedIOInterfaceHelper::ls;
	IndexedIO::EntryList (*lsFilter)(IndexedIOInterfacePtr, IndexedIOFilterPtr) = &IndexedIOInterfaceHelper::ls;
	IndexedIO::Entry (*lsEntry)(IndexedIOInterfacePtr, const IndexedIO::EntryID &) = &IndexedIOInterfaceHelper::ls;

	void (IndexedIOInterface::*writeFloat)(const IndexedIO::EntryID &, const float &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeDouble)(const IndexedIO::EntryID &, const double &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeInt)(const IndexedIO::EntryID &, const int &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeLong)(const IndexedIO::EntryID &, const long &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeString)(const IndexedIO::EntryID &, const std::string &) = &IndexedIOInterface::write;
#if 0
	void (IndexedIOInterface::*writeUInt)(const IndexedIO::EntryID &, const unsigned int &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeChar)(const IndexedIO::EntryID &, const char &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeUChar)(const IndexedIO::EntryID &, const unsigned char &) = &IndexedIOInterface::write;
#endif

	enum_< IndexedIO::OpenModeFlags> ("IndexedIOOpenMode")
		.value("Read", IndexedIO::Read)
		.value("Write", IndexedIO::Write)
		.value("Append", IndexedIO::Append)
		.value("Shared", IndexedIO::Shared)
		.value("Exclusive", IndexedIO::Exclusive)
		.export_values()
	;

	enum_< IndexedIO::EntryType > ("IndexedIOEntryType")
		.value("Directory", IndexedIO::Directory)
		.value("File", IndexedIO::File)
		.export_values()
	;

	enum_< IndexedIO::DataType > ("IndexedIODataType")
		.value("Float", IndexedIO::Float)
		.value("FloatArray", IndexedIO::FloatArray)
		.value("Double", IndexedIO::Double)
		.value("DoubleArray", IndexedIO::DoubleArray)
		.value("Int", IndexedIO::Int)
		.value("IntArray", IndexedIO::IntArray)
		.value("Long", IndexedIO::Long)
		.value("LongArray", IndexedIO::LongArray)
		.value("String", IndexedIO::String)
		.value("UInt", IndexedIO::UInt)
		.value("UIntArray", IndexedIO::UIntArray)
		.value("Char", IndexedIO::Char)
		.value("CharArray", IndexedIO::CharArray)
		.value("UChar", IndexedIO::UChar)
		.value("UChar", IndexedIO::UCharArray)
		.export_values()
	;

	typedef class_< IndexedIOInterface, boost::noncopyable, IndexedIOInterfacePtr, bases<RefCounted> > IndexedIOInterfacePyClass;
	IndexedIOInterfacePyClass( bindName, no_init )
		.def("resetRoot", &IndexedIOInterface::resetRoot)
		.def("chdir", &IndexedIOInterface::chdir)
		.def("mkdir", &IndexedIOInterface::mkdir)
		.def("pwd", &IndexedIOInterface::pwd)
		.def("rm", &IndexedIOInterface::rm)
		.def("ls", lsFilter)
		.def("ls", lsNoFilter)
		.def("ls", lsEntry)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<float> >)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<double> >)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<int> >)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<long> >)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<std::string> >)
		.def("write", writeFloat)
		.def("write", writeDouble)
		.def("write", writeInt)
		.def("write", writeLong)
		.def("write", writeString)
#if 0
		// We dont really want to bind these because they don't represent natural Python datatypes
		.def("write", writeUInt)
		.def("write", writeChar)
		.def("write", writeUChar)
#endif
		.def("read", &IndexedIOInterfaceHelper::read)
		.def("create", &IndexedIOInterface::create ).staticmethod("create")

	;
	INTRUSIVE_PTR_PATCH( IndexedIOInterface, IndexedIOInterfacePyClass );

	implicitly_convertible<IndexedIOInterfacePtr, RefCountedPtr>();
}

void bindFileSystemIndexedIO(const char *bindName)
{
	class_< FileSystemIndexedIO, FileSystemIndexedIOPtr, boost::noncopyable, bases<IndexedIOInterface> >(bindName, no_init)
		.def(init<const std::string &, const std::string &, IndexedIO::OpenMode >())
	;

	implicitly_convertible< FileSystemIndexedIOPtr, IndexedIOInterfacePtr >();
}

#ifdef IECORE_WITH_SQLITE
void bindSQLiteIndexedIO(const char *bindName)
{
	class_< SQLiteIndexedIO, SQLiteIndexedIOPtr, boost::noncopyable, bases<IndexedIOInterface> >(bindName, no_init)
		.def(init<const std::string &, const std::string &, IndexedIO::OpenMode >())
	;

	implicitly_convertible< SQLiteIndexedIOPtr, IndexedIOInterfacePtr >();
}
#endif // IECORE_WITH_SQLITE

void bindFileIndexedIO(const char *bindName)
{
	class_< FileIndexedIO, FileIndexedIOPtr, boost::noncopyable, bases<IndexedIOInterface> >(bindName, no_init)
		.def(init<const std::string &, const std::string &, IndexedIO::OpenMode >())
	;

	implicitly_convertible< FileIndexedIOPtr, IndexedIOInterfacePtr >();
}

void bindIndexedIOEntry(const char *bindName)
{
	class_< IndexedIO::Entry>(bindName, no_init)
		.def("id", &IndexedIO::Entry::id)
		.def("entryType", &IndexedIO::Entry::entryType)
		.def("dataType", &IndexedIO::Entry::dataType)
		.def("arrayLength", &IndexedIO::Entry::arrayLength)
		;
}

struct EntryListAccessor
{
	static IndexedIO::Entry get(const IndexedIO::EntryList &x, int i)
	{
		if (i < 0)
			i += x.size();

		if (i >= 0 && i < static_cast<int>(x.size()))
		{
			int idx = 0;

			IndexedIO::EntryList::const_iterator it = x.begin();
			while (idx != i)
				it++, idx++;

			assert(it != x.end());

			return *it;
		}
		else
		{
			throw std::out_of_range("");
		}
	}

	static int len(const IndexedIO::EntryList &x)
	{
		return static_cast<int>(x.size());
	}
};

void bindIndexedIOEntryList(const char *bindName)
{
	class_< IndexedIO::EntryList>(bindName, no_init)
		.def("__getitem__", &EntryListAccessor::get)
		.def("__len__", &EntryListAccessor::len)
	;
}

void bindIndexedIOFilter(const char *bindName)
{
	class_< IndexedIOFilter, boost::noncopyable, IndexedIOFilterPtr>(bindName, no_init)
		.def("add", &IndexedIOFilter::add )
		.def("apply", &IndexedIOFilter::apply )
		.def("filter", &IndexedIOFilter::filter )
	;
}

void bindIndexedIONullFilter(const char *bindName)
{
	class_<IndexedIONullFilter, IndexedIONullFilterPtr, bases<IndexedIOFilter> >(bindName, no_init)
		.def(init<>())
	;

	// Ensure we can upcast from a IndexedIOEntryTypeFilterPtr to a IndexedIOFilterPtr
	implicitly_convertible< IndexedIONullFilterPtr, IndexedIOFilterPtr >();
}

void bindIndexedIOEntryTypeFilter(const char *bindName)
{
	class_<IndexedIOEntryTypeFilter, IndexedIOEntryTypeFilterPtr, bases<IndexedIOFilter> >(bindName, no_init)
		.def(init<IndexedIO::EntryType>())
	;

	// Ensure we can upcast from a IndexedIOEntryTypeFilterPtr to a IndexedIOFilterPtr
	implicitly_convertible< IndexedIOEntryTypeFilterPtr, IndexedIOFilterPtr >();
}

void bindIndexedIORegexFilter(const char *bindName)
{
	class_<IndexedIORegexFilter, IndexedIORegexFilterPtr, bases<IndexedIOFilter> >(bindName, no_init)
		.def(init<const std::string &>())
	;

	// Ensure we can upcast from a IndexedIOEntryTypeFilterPtr to a IndexedIOFilterPtr
	implicitly_convertible< IndexedIORegexFilterPtr, IndexedIOFilterPtr >();
}
<commit_msg>Removed some nonsense.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

// This include needs to be the very first to prevent problems with warnings
// regarding redefinition of _POSIX_C_SOURCE
#include <boost/python.hpp>

#include <iostream>

#include "IECore/IndexedIOInterface.h"
#include "IECore/FileSystemIndexedIO.h"
#include "IECore/SQLiteIndexedIO.h"
#include "IECore/FileIndexedIO.h"
#include "IECore/VectorTypedData.h"
#include "IECore/bindings/IntrusivePtrPatch.h"

using namespace boost::python;
using namespace IECore;

void bindIndexedIOEntry(const char *bindName);
void bindIndexedIOEntryList(const char *bindName);

void bindIndexedIOFilter(const char *bindName);
void bindIndexedIONullFilter(const char *bindName);
void bindIndexedIOEntryTypeFilter(const char *bindName);
void bindIndexedIORegexFilter(const char *bindName);

void bindIndexedIOInterface(const char *bindName);
void bindFileSystemIndexedIO(const char *bindName);
void bindSQLiteIndexedIO(const char *bindName);
void bindFileIndexedIO(const char *bindName);

void bindIndexedIO()
{
	bindIndexedIOEntry("IndexedIOEntry");
	bindIndexedIOEntryList("IndexedIOEntryList");

	bindIndexedIOFilter("IndexedIOFilter");
	bindIndexedIONullFilter("IndexedIONullFilter");
	bindIndexedIOEntryTypeFilter("IndexedIOEntryTypeFilter");
	bindIndexedIORegexFilter("IndexedIORegexFilter");

	bindIndexedIOInterface("IndexedIOInterface");
	bindFileSystemIndexedIO("FileSystemIndexedIO");
#ifdef IECORE_WITH_SQLITE
	bindSQLiteIndexedIO("SQLiteIndexedIO");
#endif // IECORE_WITH_SQLITE
	bindFileIndexedIO("FileIndexedIO");
}

struct IndexedIOInterfaceHelper
{
	static IndexedIO::Entry ls(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name)
	{
		assert(p);

		return p->ls(name);
	}

	static IndexedIO::EntryList ls(IndexedIOInterfacePtr p)
	{
		assert(p);

		return p->ls();
	}

	static IndexedIO::EntryList ls(IndexedIOInterfacePtr p, IndexedIOFilterPtr f)
	{
		assert(p);

		return p->ls(f);
	}

	template<typename T>
	static void writeVector(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name,
		const boost::intrusive_ptr< TypedData < T > > &x)
	{
		assert(p);

		const typename T::value_type *data = &(x->readable())[0];
		p->write( name, data, (unsigned long)x->readable().size() );
	}

	template<typename T>
	static boost::intrusive_ptr<TypedData<T> > readSingle(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name, const IndexedIO::Entry &entry)
	{
		T data;
		p->read(name, data);
		return new TypedData<T>( data );
	}

	template<typename T>
	static boost::intrusive_ptr<TypedData< std::vector<T> > > readArray(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name, const IndexedIO::Entry &entry)
	{
		unsigned long count = entry.arrayLength();
		boost::intrusive_ptr< TypedData<std::vector<T> > > x = new TypedData<std::vector<T> > ();
		x->writable().resize( entry.arrayLength() );
		T *data = &(x->writable()[0]);
		p->read(name, data, count);

		return x;
	}

	static DataPtr read(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name)
	{
		assert(p);

		IndexedIO::Entry entry = p->ls(name);

		switch( entry.dataType() )
		{
			case IndexedIO::Float:
				return readSingle<float>(p, name, entry);
			case IndexedIO::Double:
				return readSingle<double>(p, name, entry);
			case IndexedIO::Int:
				return readSingle<int>(p, name, entry);
			case IndexedIO::Long:
				return readSingle<long>(p, name, entry);
			case IndexedIO::String:
				return readSingle<std::string>(p, name, entry);
			case IndexedIO::StringArray:
				return readArray<std::string>(p, name, entry);
			case IndexedIO::FloatArray:
				return readArray<float>(p, name, entry);
			case IndexedIO::DoubleArray:
				return readArray<double>(p, name, entry);
			case IndexedIO::IntArray:
				return readArray<int>(p, name, entry);
			case IndexedIO::LongArray:
				return readArray<long>(p, name, entry);
			case IndexedIO::UInt:
				return readSingle<unsigned int>(p, name, entry);
			case IndexedIO::UIntArray:
				return readArray<unsigned int>(p, name, entry);
			case IndexedIO::Char:
				return readSingle<char>(p, name, entry);
			case IndexedIO::CharArray:
				return readArray<char>(p, name, entry);
			case IndexedIO::UChar:
				return readSingle<unsigned char>(p, name, entry);
			case IndexedIO::UCharArray:
				return readArray<unsigned char>(p, name, entry);
			default:
				throw IOException(name);
		}
	}

	static std::string readString(IndexedIOInterfacePtr p, const IndexedIO::EntryID &name)
	{
		assert(p);

		std::string x;
		p->read(name, x);
		return x;
	}
};

void bindIndexedIOInterface(const char *bindName)
{
	IndexedIO::EntryList (*lsNoFilter)(IndexedIOInterfacePtr) = &IndexedIOInterfaceHelper::ls;
	IndexedIO::EntryList (*lsFilter)(IndexedIOInterfacePtr, IndexedIOFilterPtr) = &IndexedIOInterfaceHelper::ls;
	IndexedIO::Entry (*lsEntry)(IndexedIOInterfacePtr, const IndexedIO::EntryID &) = &IndexedIOInterfaceHelper::ls;

	void (IndexedIOInterface::*writeFloat)(const IndexedIO::EntryID &, const float &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeDouble)(const IndexedIO::EntryID &, const double &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeInt)(const IndexedIO::EntryID &, const int &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeLong)(const IndexedIO::EntryID &, const long &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeString)(const IndexedIO::EntryID &, const std::string &) = &IndexedIOInterface::write;
#if 0
	void (IndexedIOInterface::*writeUInt)(const IndexedIO::EntryID &, const unsigned int &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeChar)(const IndexedIO::EntryID &, const char &) = &IndexedIOInterface::write;
	void (IndexedIOInterface::*writeUChar)(const IndexedIO::EntryID &, const unsigned char &) = &IndexedIOInterface::write;
#endif

	enum_< IndexedIO::OpenModeFlags> ("IndexedIOOpenMode")
		.value("Read", IndexedIO::Read)
		.value("Write", IndexedIO::Write)
		.value("Append", IndexedIO::Append)
		.value("Shared", IndexedIO::Shared)
		.value("Exclusive", IndexedIO::Exclusive)
		.export_values()
	;

	enum_< IndexedIO::EntryType > ("IndexedIOEntryType")
		.value("Directory", IndexedIO::Directory)
		.value("File", IndexedIO::File)
		.export_values()
	;

	enum_< IndexedIO::DataType > ("IndexedIODataType")
		.value("Float", IndexedIO::Float)
		.value("FloatArray", IndexedIO::FloatArray)
		.value("Double", IndexedIO::Double)
		.value("DoubleArray", IndexedIO::DoubleArray)
		.value("Int", IndexedIO::Int)
		.value("IntArray", IndexedIO::IntArray)
		.value("Long", IndexedIO::Long)
		.value("LongArray", IndexedIO::LongArray)
		.value("String", IndexedIO::String)
		.value("UInt", IndexedIO::UInt)
		.value("UIntArray", IndexedIO::UIntArray)
		.value("Char", IndexedIO::Char)
		.value("CharArray", IndexedIO::CharArray)
		.value("UChar", IndexedIO::UChar)
		.value("UChar", IndexedIO::UCharArray)
		.export_values()
	;

	typedef class_< IndexedIOInterface, boost::noncopyable, IndexedIOInterfacePtr, bases<RefCounted> > IndexedIOInterfacePyClass;
	IndexedIOInterfacePyClass( bindName, no_init )
		.def("resetRoot", &IndexedIOInterface::resetRoot)
		.def("chdir", &IndexedIOInterface::chdir)
		.def("mkdir", &IndexedIOInterface::mkdir)
		.def("pwd", &IndexedIOInterface::pwd)
		.def("rm", &IndexedIOInterface::rm)
		.def("ls", lsFilter)
		.def("ls", lsNoFilter)
		.def("ls", lsEntry)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<float> >)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<double> >)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<int> >)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<long> >)
		.def("write", &IndexedIOInterfaceHelper::writeVector<std::vector<std::string> >)
		.def("write", writeFloat)
		.def("write", writeDouble)
		.def("write", writeInt)
		.def("write", writeLong)
		.def("write", writeString)
#if 0
		// We dont really want to bind these because they don't represent natural Python datatypes
		.def("write", writeUInt)
		.def("write", writeChar)
		.def("write", writeUChar)
#endif
		.def("read", &IndexedIOInterfaceHelper::read)
		.def("create", &IndexedIOInterface::create ).staticmethod("create")

	;
	INTRUSIVE_PTR_PATCH( IndexedIOInterface, IndexedIOInterfacePyClass );

	implicitly_convertible<IndexedIOInterfacePtr, RefCountedPtr>();
}

void bindFileSystemIndexedIO(const char *bindName)
{
	class_< FileSystemIndexedIO, FileSystemIndexedIOPtr, boost::noncopyable, bases<IndexedIOInterface> >(bindName, no_init)
		.def(init<const std::string &, const std::string &, IndexedIO::OpenMode >())
	;

	implicitly_convertible< FileSystemIndexedIOPtr, IndexedIOInterfacePtr >();
}

#ifdef IECORE_WITH_SQLITE
void bindSQLiteIndexedIO(const char *bindName)
{
	class_< SQLiteIndexedIO, SQLiteIndexedIOPtr, boost::noncopyable, bases<IndexedIOInterface> >(bindName, no_init)
		.def(init<const std::string &, const std::string &, IndexedIO::OpenMode >())
	;

	implicitly_convertible< SQLiteIndexedIOPtr, IndexedIOInterfacePtr >();
}
#endif // IECORE_WITH_SQLITE

void bindFileIndexedIO(const char *bindName)
{
	class_< FileIndexedIO, FileIndexedIOPtr, boost::noncopyable, bases<IndexedIOInterface> >(bindName, no_init)
		.def(init<const std::string &, const std::string &, IndexedIO::OpenMode >())
	;

	implicitly_convertible< FileIndexedIOPtr, IndexedIOInterfacePtr >();
}

void bindIndexedIOEntry(const char *bindName)
{
	class_< IndexedIO::Entry>(bindName, no_init)
		.def("id", &IndexedIO::Entry::id)
		.def("entryType", &IndexedIO::Entry::entryType)
		.def("dataType", &IndexedIO::Entry::dataType)
		.def("arrayLength", &IndexedIO::Entry::arrayLength)
		;
}

struct EntryListAccessor
{
	static IndexedIO::Entry get(const IndexedIO::EntryList &x, int i)
	{
		if (i < 0)
			i += x.size();

		if (i >= 0 && i < static_cast<int>(x.size()))
		{
			int idx = 0;

			IndexedIO::EntryList::const_iterator it = x.begin();
			while (idx != i)
				it++, idx++;

			assert(it != x.end());

			return *it;
		}
		else
		{
			throw std::out_of_range("");
		}
	}

	static int len(const IndexedIO::EntryList &x)
	{
		return static_cast<int>(x.size());
	}
};

void bindIndexedIOEntryList(const char *bindName)
{
	class_< IndexedIO::EntryList>(bindName, no_init)
		.def("__getitem__", &EntryListAccessor::get)
		.def("__len__", &EntryListAccessor::len)
	;
}

void bindIndexedIOFilter(const char *bindName)
{
	class_< IndexedIOFilter, boost::noncopyable, IndexedIOFilterPtr>(bindName, no_init)
		.def("add", &IndexedIOFilter::add )
		.def("apply", &IndexedIOFilter::apply )
		.def("filter", &IndexedIOFilter::filter )
	;
}

void bindIndexedIONullFilter(const char *bindName)
{
	class_<IndexedIONullFilter, IndexedIONullFilterPtr, bases<IndexedIOFilter> >(bindName, no_init)
		.def(init<>())
	;

	// Ensure we can upcast from a IndexedIOEntryTypeFilterPtr to a IndexedIOFilterPtr
	implicitly_convertible< IndexedIONullFilterPtr, IndexedIOFilterPtr >();
}

void bindIndexedIOEntryTypeFilter(const char *bindName)
{
	class_<IndexedIOEntryTypeFilter, IndexedIOEntryTypeFilterPtr, bases<IndexedIOFilter> >(bindName, no_init)
		.def(init<IndexedIO::EntryType>())
	;

	// Ensure we can upcast from a IndexedIOEntryTypeFilterPtr to a IndexedIOFilterPtr
	implicitly_convertible< IndexedIOEntryTypeFilterPtr, IndexedIOFilterPtr >();
}

void bindIndexedIORegexFilter(const char *bindName)
{
	class_<IndexedIORegexFilter, IndexedIORegexFilterPtr, bases<IndexedIOFilter> >(bindName, no_init)
		.def(init<const std::string &>())
	;

	// Ensure we can upcast from a IndexedIOEntryTypeFilterPtr to a IndexedIOFilterPtr
	implicitly_convertible< IndexedIORegexFilterPtr, IndexedIOFilterPtr >();
}
<|endoftext|>