/* connection.c generated by valac 0.24.0, the Vala compiler
 * generated from connection.vala, do not modify */

/* 
 * SmartSim - Digital Logic Circuit Designer and Simulator
 *   
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *   
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *   
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *   
 *   Filename: connection.vala
 *   
 *   Copyright Ashley Newson 2013
 */

#include <glib.h>
#include <glib-object.h>
#include <gobject/gvaluecollector.h>


#define TYPE_CONNECTION (connection_get_type ())
#define CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CONNECTION, Connection))
#define CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CONNECTION, ConnectionClass))
#define IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CONNECTION))
#define IS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CONNECTION))
#define CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CONNECTION, ConnectionClass))

typedef struct _Connection Connection;
typedef struct _ConnectionClass ConnectionClass;
typedef struct _ConnectionPrivate ConnectionPrivate;

#define TYPE_WIRE_STATE (wire_state_get_type ())
#define WIRE_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_WIRE_STATE, WireState))
#define WIRE_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_WIRE_STATE, WireStateClass))
#define IS_WIRE_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_WIRE_STATE))
#define IS_WIRE_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_WIRE_STATE))
#define WIRE_STATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_WIRE_STATE, WireStateClass))

typedef struct _WireState WireState;
typedef struct _WireStateClass WireStateClass;
typedef struct _WireStatePrivate WireStatePrivate;

#define TYPE_COMPILED_CIRCUIT (compiled_circuit_get_type ())
#define COMPILED_CIRCUIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_COMPILED_CIRCUIT, CompiledCircuit))
#define COMPILED_CIRCUIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_COMPILED_CIRCUIT, CompiledCircuitClass))
#define IS_COMPILED_CIRCUIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_COMPILED_CIRCUIT))
#define IS_COMPILED_CIRCUIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_COMPILED_CIRCUIT))
#define COMPILED_CIRCUIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_COMPILED_CIRCUIT, CompiledCircuitClass))

typedef struct _CompiledCircuit CompiledCircuit;
typedef struct _CompiledCircuitClass CompiledCircuitClass;

#define TYPE_COMPONENT_INST (component_inst_get_type ())
#define COMPONENT_INST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_COMPONENT_INST, ComponentInst))
#define COMPONENT_INST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_COMPONENT_INST, ComponentInstClass))
#define IS_COMPONENT_INST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_COMPONENT_INST))
#define IS_COMPONENT_INST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_COMPONENT_INST))
#define COMPONENT_INST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_COMPONENT_INST, ComponentInstClass))

typedef struct _ComponentInst ComponentInst;
typedef struct _ComponentInstClass ComponentInstClass;

#define TYPE_WIRE_INST (wire_inst_get_type ())
#define WIRE_INST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_WIRE_INST, WireInst))
#define WIRE_INST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_WIRE_INST, WireInstClass))
#define IS_WIRE_INST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_WIRE_INST))
#define IS_WIRE_INST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_WIRE_INST))
#define WIRE_INST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_WIRE_INST, WireInstClass))

typedef struct _WireInst WireInst;
typedef struct _WireInstClass WireInstClass;

#define TYPE_COMPONENT_STATE (component_state_get_type ())
#define COMPONENT_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_COMPONENT_STATE, ComponentState))
#define COMPONENT_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_COMPONENT_STATE, ComponentStateClass))
#define IS_COMPONENT_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_COMPONENT_STATE))
#define IS_COMPONENT_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_COMPONENT_STATE))
#define COMPONENT_STATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_COMPONENT_STATE, ComponentStateClass))

typedef struct _ComponentState ComponentState;
typedef struct _ComponentStateClass ComponentStateClass;
typedef struct _ParamSpecConnection ParamSpecConnection;

struct _Connection {
	GTypeInstance parent_instance;
	volatile int ref_count;
	ConnectionPrivate * priv;
	WireState* wireState;
	gboolean invert;
	gboolean isFake;
	gboolean active;
};

struct _ConnectionClass {
	GTypeClass parent_class;
	void (*finalize) (Connection *self);
};

struct _WireState {
	GTypeInstance parent_instance;
	volatile int ref_count;
	WireStatePrivate * priv;
	gint renderQueueID;
	gint processQueueID;
	CompiledCircuit* compiledCircuit;
	ComponentInst** ancestry;
	gint ancestry_length1;
	gboolean display;
	gboolean errorMark;
	WireInst* wireInst;
	gint users;
	gint previousUsers;
};

struct _WireStateClass {
	GTypeClass parent_class;
	void (*finalize) (WireState *self);
};

struct _ParamSpecConnection {
	GParamSpec parent_instance;
};


static gpointer connection_parent_class = NULL;

gpointer connection_ref (gpointer instance);
void connection_unref (gpointer instance);
GParamSpec* param_spec_connection (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_connection (GValue* value, gpointer v_object);
void value_take_connection (GValue* value, gpointer v_object);
gpointer value_get_connection (const GValue* value);
GType connection_get_type (void) G_GNUC_CONST;
gpointer wire_state_ref (gpointer instance);
void wire_state_unref (gpointer instance);
GParamSpec* param_spec_wire_state (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_wire_state (GValue* value, gpointer v_object);
void value_take_wire_state (GValue* value, gpointer v_object);
gpointer value_get_wire_state (const GValue* value);
GType wire_state_get_type (void) G_GNUC_CONST;
enum  {
	CONNECTION_DUMMY_PROPERTY
};
Connection* connection_new (WireState* wireState, gboolean invert);
Connection* connection_construct (GType object_type, WireState* wireState, gboolean invert);
Connection* connection_new_fake (void);
Connection* connection_construct_fake (GType object_type);
void connection_disable_signal (Connection* self);
gpointer compiled_circuit_ref (gpointer instance);
void compiled_circuit_unref (gpointer instance);
GParamSpec* param_spec_compiled_circuit (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_compiled_circuit (GValue* value, gpointer v_object);
void value_take_compiled_circuit (GValue* value, gpointer v_object);
gpointer value_get_compiled_circuit (const GValue* value);
GType compiled_circuit_get_type (void) G_GNUC_CONST;
gpointer component_inst_ref (gpointer instance);
void component_inst_unref (gpointer instance);
GParamSpec* param_spec_component_inst (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_component_inst (GValue* value, gpointer v_object);
void value_take_component_inst (GValue* value, gpointer v_object);
gpointer value_get_component_inst (const GValue* value);
GType component_inst_get_type (void) G_GNUC_CONST;
gpointer wire_inst_ref (gpointer instance);
void wire_inst_unref (gpointer instance);
GParamSpec* param_spec_wire_inst (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_wire_inst (GValue* value, gpointer v_object);
void value_take_wire_inst (GValue* value, gpointer v_object);
gpointer value_get_wire_inst (const GValue* value);
GType wire_inst_get_type (void) G_GNUC_CONST;
void wire_state_update_interfaces (WireState* self, WireState* updater);
gpointer component_state_ref (gpointer instance);
void component_state_unref (gpointer instance);
GParamSpec* param_spec_component_state (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_component_state (GValue* value, gpointer v_object);
void value_take_component_state (GValue* value, gpointer v_object);
gpointer value_get_component_state (const GValue* value);
GType component_state_get_type (void) G_GNUC_CONST;
void connection_set_affects (Connection* self, ComponentState* componentState);
void wire_state_add_affected (WireState* self, ComponentState* componentState);
WireInst* connection_get_wireInst (Connection* self);
gboolean connection_get_signalState (Connection* self);
gboolean wire_state_get_signalState (WireState* self);
void connection_set_signalState (Connection* self, gboolean value);
void wire_state_set_signalState (WireState* self, gboolean value);
gint connection_get_users (Connection* self);
static void connection_finalize (Connection* obj);


/**
 * Create a real connection to //wireState//.
 */
Connection* connection_construct (GType object_type, WireState* wireState, gboolean invert) {
	Connection* self = NULL;
	WireState* _tmp0_ = NULL;
	gboolean _tmp1_ = FALSE;
	g_return_val_if_fail (wireState != NULL, NULL);
	self = (Connection*) g_type_create_instance (object_type);
	_tmp0_ = wireState;
	self->wireState = _tmp0_;
	_tmp1_ = invert;
	self->invert = _tmp1_;
	return self;
}


Connection* connection_new (WireState* wireState, gboolean invert) {
	return connection_construct (TYPE_CONNECTION, wireState, invert);
}


/**
 * Creates a fake connection which goes nowhere.
 */
Connection* connection_construct_fake (GType object_type) {
	Connection* self = NULL;
	self = (Connection*) g_type_create_instance (object_type);
	self->wireState = NULL;
	self->isFake = TRUE;
	return self;
}


Connection* connection_new_fake (void) {
	return connection_construct_fake (TYPE_CONNECTION);
}


void connection_disable_signal (Connection* self) {
	gboolean _tmp0_ = FALSE;
	WireState* _tmp3_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->active;
	if (_tmp0_) {
		WireState* _tmp1_ = NULL;
		gint _tmp2_ = 0;
		_tmp1_ = self->wireState;
		_tmp2_ = _tmp1_->users;
		_tmp1_->users = _tmp2_ - 1;
		self->active = FALSE;
	}
	_tmp3_ = self->wireState;
	wire_state_update_interfaces (_tmp3_, NULL);
}


void connection_set_affects (Connection* self, ComponentState* componentState) {
	gboolean _tmp0_ = FALSE;
	g_return_if_fail (self != NULL);
	g_return_if_fail (componentState != NULL);
	_tmp0_ = self->isFake;
	if (!_tmp0_) {
		WireState* _tmp1_ = NULL;
		ComponentState* _tmp2_ = NULL;
		_tmp1_ = self->wireState;
		_tmp2_ = componentState;
		wire_state_add_affected (_tmp1_, _tmp2_);
	}
}


WireInst* connection_get_wireInst (Connection* self) {
	WireInst* result;
	WireState* _tmp0_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->wireState;
	if (_tmp0_ == NULL) {
		result = NULL;
		return result;
	} else {
		WireState* _tmp1_ = NULL;
		WireInst* _tmp2_ = NULL;
		_tmp1_ = self->wireState;
		_tmp2_ = _tmp1_->wireInst;
		result = _tmp2_;
		return result;
	}
}


gboolean connection_get_signalState (Connection* self) {
	gboolean result;
	WireState* _tmp0_ = NULL;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->wireState;
	if (_tmp0_ == NULL) {
		result = FALSE;
		return result;
	} else {
		WireState* _tmp1_ = NULL;
		gboolean _tmp2_ = FALSE;
		gboolean _tmp3_ = FALSE;
		gboolean _tmp4_ = FALSE;
		_tmp1_ = self->wireState;
		_tmp2_ = wire_state_get_signalState (_tmp1_);
		_tmp3_ = _tmp2_;
		_tmp4_ = self->invert;
		result = _tmp3_ != _tmp4_;
		return result;
	}
}


void connection_set_signalState (Connection* self, gboolean value) {
	WireState* _tmp0_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->wireState;
	if (_tmp0_ != NULL) {
		WireState* _tmp1_ = NULL;
		gboolean _tmp2_ = FALSE;
		gboolean _tmp3_ = FALSE;
		gboolean _tmp4_ = FALSE;
		WireState* _tmp7_ = NULL;
		_tmp1_ = self->wireState;
		_tmp2_ = value;
		_tmp3_ = self->invert;
		wire_state_set_signalState (_tmp1_, _tmp2_ != _tmp3_);
		_tmp4_ = self->active;
		if (!_tmp4_) {
			WireState* _tmp5_ = NULL;
			gint _tmp6_ = 0;
			_tmp5_ = self->wireState;
			_tmp6_ = _tmp5_->users;
			_tmp5_->users = _tmp6_ + 1;
			self->active = TRUE;
		}
		_tmp7_ = self->wireState;
		wire_state_update_interfaces (_tmp7_, NULL);
	}
}


gint connection_get_users (Connection* self) {
	gint result;
	WireState* _tmp0_ = NULL;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = self->wireState;
	if (_tmp0_ == NULL) {
		result = 0;
		return result;
	} else {
		WireState* _tmp1_ = NULL;
		gint _tmp2_ = 0;
		_tmp1_ = self->wireState;
		_tmp2_ = _tmp1_->previousUsers;
		result = _tmp2_;
		return result;
	}
}


static void value_connection_init (GValue* value) {
	value->data[0].v_pointer = NULL;
}


static void value_connection_free_value (GValue* value) {
	if (value->data[0].v_pointer) {
		connection_unref (value->data[0].v_pointer);
	}
}


static void value_connection_copy_value (const GValue* src_value, GValue* dest_value) {
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = connection_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}


static gpointer value_connection_peek_pointer (const GValue* value) {
	return value->data[0].v_pointer;
}


static gchar* value_connection_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
	if (collect_values[0].v_pointer) {
		Connection* object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = connection_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}


static gchar* value_connection_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
	Connection** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = connection_ref (value->data[0].v_pointer);
	}
	return NULL;
}


GParamSpec* param_spec_connection (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
	ParamSpecConnection* spec;
	g_return_val_if_fail (g_type_is_a (object_type, TYPE_CONNECTION), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}


gpointer value_get_connection (const GValue* value) {
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_CONNECTION), NULL);
	return value->data[0].v_pointer;
}


void value_set_connection (GValue* value, gpointer v_object) {
	Connection* old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_CONNECTION));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_CONNECTION));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		connection_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		connection_unref (old);
	}
}


void value_take_connection (GValue* value, gpointer v_object) {
	Connection* old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_CONNECTION));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_CONNECTION));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		connection_unref (old);
	}
}


static void connection_class_init (ConnectionClass * klass) {
	connection_parent_class = g_type_class_peek_parent (klass);
	CONNECTION_CLASS (klass)->finalize = connection_finalize;
}


static void connection_instance_init (Connection * self) {
	self->isFake = FALSE;
	self->active = FALSE;
	self->ref_count = 1;
}


static void connection_finalize (Connection* obj) {
	Connection * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_CONNECTION, Connection);
}


/**
 * Used to handle a connection to a wire in a compiled circuit.
 * 
 * Connections automatically handle inversions, update
 * interfaces, user counts.
 * They can also act as a stub when there is no real wire to connect -
 * known as a fake connection.
 */
GType connection_get_type (void) {
	static volatile gsize connection_type_id__volatile = 0;
	if (g_once_init_enter (&connection_type_id__volatile)) {
		static const GTypeValueTable g_define_type_value_table = { value_connection_init, value_connection_free_value, value_connection_copy_value, value_connection_peek_pointer, "p", value_connection_collect_value, "p", value_connection_lcopy_value };
		static const GTypeInfo g_define_type_info = { sizeof (ConnectionClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) connection_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Connection), 0, (GInstanceInitFunc) connection_instance_init, &g_define_type_value_table };
		static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
		GType connection_type_id;
		connection_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Connection", &g_define_type_info, &g_define_type_fundamental_info, 0);
		g_once_init_leave (&connection_type_id__volatile, connection_type_id);
	}
	return connection_type_id__volatile;
}


gpointer connection_ref (gpointer instance) {
	Connection* self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}


void connection_unref (gpointer instance) {
	Connection* self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		CONNECTION_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}



