[aravis/dom] genicam: ArvGcRegister is now an interface, implemented by ArvGcRegisterNode and ArvGcStructEntryNod



commit d7f432cdaa25ef0163d916f186b726858e6b8f52
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Sun Mar 4 23:37:37 2012 +0100

    genicam: ArvGcRegister is now an interface, implemented by ArvGcRegisterNode and ArvGcStructEntryNode.

 docs/reference/aravis/aravis-docs.xml     |    3 +-
 docs/reference/aravis/aravis-sections.txt |   65 ++-
 docs/reference/aravis/aravis.types        |    2 +-
 src/Makefile.am                           |    6 +-
 src/arv.h                                 |    3 +-
 src/arvfakecamera.c                       |    2 +-
 src/arvgc.c                               |   12 +-
 src/arvgcregister.c                       |  704 +--------------------------
 src/arvgcregister.h                       |   93 +---
 src/arvgcregisternode.c                   |  771 +++++++++++++++++++++++++++++
 src/arvgcregisternode.h                   |  116 +++++
 src/arvgcstructentrynode.c                |   61 +++-
 src/arvtypes.h                            |    3 +-
 tests/fake.c                              |   11 +
 14 files changed, 1038 insertions(+), 814 deletions(-)
---
diff --git a/docs/reference/aravis/aravis-docs.xml b/docs/reference/aravis/aravis-docs.xml
index ae949ee..4a723c8 100644
--- a/docs/reference/aravis/aravis-docs.xml
+++ b/docs/reference/aravis/aravis-docs.xml
@@ -56,6 +56,7 @@
 			<xi:include href="xml/arvgcfeaturenode.xml"/>
 			<xi:include href="xml/arvgcregisterdescriptionnode.xml"/>
 			<xi:include href="xml/arvgcgroupnode.xml"/>
+			<xi:include href="xml/arvgcregister.xml"/>
 			<xi:include href="xml/arvgcinteger.xml"/>
 			<xi:include href="xml/arvgcfloat.xml"/>
 			<xi:include href="xml/arvgcstring.xml"/>
@@ -64,7 +65,7 @@
 			<xi:include href="xml/arvgcboolean.xml"/>
 			<xi:include href="xml/arvgcintegernode.xml"/>
 			<xi:include href="xml/arvgcfloatnode.xml"/>
-			<xi:include href="xml/arvgcregister.xml"/>
+			<xi:include href="xml/arvgcregisternode.xml"/>
 			<xi:include href="xml/arvgcstructentrynode.xml"/>
 			<xi:include href="xml/arvgcenumeration.xml"/>
 			<xi:include href="xml/arvgcenumentry.xml"/>
diff --git a/docs/reference/aravis/aravis-sections.txt b/docs/reference/aravis/aravis-sections.txt
index 13de108..39cc854 100644
--- a/docs/reference/aravis/aravis-sections.txt
+++ b/docs/reference/aravis/aravis-sections.txt
@@ -455,6 +455,25 @@ ArvGcIntegerInterface
 </SECTION>
 
 <SECTION>
+<FILE>arvgcregister</FILE>
+<TITLE>ArvGcRegister</TITLE>
+arv_gc_register_get
+arv_gc_register_get_address
+arv_gc_register_get_length
+arv_gc_register_get_type
+arv_gc_register_set
+<SUBSECTION Standard>
+ARV_GC_REGISTER
+ARV_GC_REGISTER_GET_CLASS
+ARV_GC_REGISTER_GET_INTERFACE
+ARV_IS_GC_REGISTER
+ARV_TYPE_GC_REGISTER
+ArvGcRegister
+ArvGcRegisterInterface
+ArvGcRegisterType
+</SECTION>
+
+<SECTION>
 <FILE>arvgcconverter</FILE>
 <TITLE>ArvGcConverter</TITLE>
 ArvGcConverter
@@ -776,33 +795,29 @@ ArvFakeCameraFillPattern
 </SECTION>
 
 <SECTION>
-<FILE>arvgcregister</FILE>
-<TITLE>ArvGcRegister</TITLE>
+<FILE>arvgcregisternode</FILE>
+<TITLE>ArvGcRegisterNode</TITLE>
 ArvGcSign
-ArvGcRegisterType
-ArvGcRegister
-arv_gc_register_new
-arv_gc_register_new_integer
-arv_gc_register_new_masked_integer
-arv_gc_register_new_float
-arv_gc_register_new_string
-arv_gc_register_new_struct_register
-arv_gc_register_get
-arv_gc_register_set
-arv_gc_register_get_address
-arv_gc_register_get_length
-arv_gc_register_get_masked_integer_value
-arv_gc_register_set_masked_integer_value
+ArvGcRegisterNode
+ArvGcRegisterNodeType
+arv_gc_register_node_new
+arv_gc_register_node_new_integer
+arv_gc_register_node_new_masked_integer
+arv_gc_register_node_new_float
+arv_gc_register_node_new_string
+arv_gc_register_node_new_struct_register
+arv_gc_register_node_get_masked_integer_value
+arv_gc_register_node_set_masked_integer_value
 <SUBSECTION Standard>
-ARV_GC_REGISTER
-ARV_IS_GC_REGISTER
-ARV_TYPE_GC_REGISTER
-arv_gc_register_get_type
-ARV_GC_REGISTER_CLASS
-ARV_IS_GC_REGISTER_CLASS
-ARV_GC_REGISTER_GET_CLASS
+ARV_GC_REGISTER_NODE
+ARV_IS_GC_REGISTER_NODE
+ARV_TYPE_GC_REGISTER_NODE
+arv_gc_register_node_get_type
+ARV_GC_REGISTER_NODE_CLASS
+ARV_IS_GC_REGISTER_NODE_CLASS
+ARV_GC_REGISTER_NODE_GET_CLASS
 <SUBSECTION Private>
-ArvGcRegisterClass
+ArvGcRegisterNodeClass
 </SECTION>
 
 <SECTION>
diff --git a/docs/reference/aravis/aravis.types b/docs/reference/aravis/aravis.types
index aafbed8..73b849c 100644
--- a/docs/reference/aravis/aravis.types
+++ b/docs/reference/aravis/aravis.types
@@ -19,7 +19,7 @@ arv_gc_integer_get_type
 arv_gc_integer_node_get_type
 arv_gc_feature_node_get_type
 arv_gc_port_get_type
-arv_gc_register_get_type
+arv_gc_register_node_get_type
 arv_gc_string_get_type
 arv_gc_swiss_knife_get_type
 arv_gv_device_get_type
diff --git a/src/Makefile.am b/src/Makefile.am
index b9e077e..44691ca 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,12 +59,13 @@ ARAVIS_SRCS =					\
 	arvgcenumentry.c			\
 	arvgcintegernode.c			\
 	arvgcfloatnode.c			\
-	arvgcregister.c				\
+	arvgcregisternode.c			\
 	arvgcstructentrynode.c			\
 	arvgccommand.c				\
 	arvgcswissknife.c			\
 	arvgcconverter.c			\
 	arvgcport.c				\
+	arvgcregister.c				\
 	arvgcinteger.c				\
 	arvgcstring.c				\
 	arvgcfloat.c				\
@@ -120,12 +121,13 @@ ARAVIS_HDRS = 					\
 	arvgcenumentry.h			\
 	arvgcintegernode.h			\
 	arvgcfloatnode.h			\
-	arvgcregister.h				\
+	arvgcregisternode.h			\
 	arvgcstructentrynode.h			\
 	arvgccommand.h				\
 	arvgcswissknife.h			\
 	arvgcconverter.h			\
 	arvgcport.h				\
+	arvgcregister.h				\
 	arvgcinteger.h				\
 	arvgcstring.h				\
 	arvgcfloat.h				\
diff --git a/src/arv.h b/src/arv.h
index e4d2f3f..5e6eaf0 100644
--- a/src/arv.h
+++ b/src/arv.h
@@ -49,11 +49,12 @@
 #include <arvgcenumentry.h>
 #include <arvgcintegernode.h>
 #include <arvgcfloatnode.h>
-#include <arvgcregister.h>
+#include <arvgcregisternode.h>
 #include <arvgccommand.h>
 #include <arvgcswissknife.h>
 #include <arvgcconverter.h>
 #include <arvgcport.h>
+#include <arvgcregister.h>
 #include <arvgcinteger.h>
 #include <arvgcfloat.h>
 #include <arvgcstring.h>
diff --git a/src/arvfakecamera.c b/src/arvfakecamera.c
index e9397d0..fbad89a 100644
--- a/src/arvfakecamera.c
+++ b/src/arvfakecamera.c
@@ -32,7 +32,7 @@
 
 #include <arvfakecamera.h>
 #include <arvgc.h>
-#include <arvgcregister.h>
+#include <arvgcregisternode.h>
 #include <arvgvcp.h>
 #include <arvbuffer.h>
 #include <arvdebug.h>
diff --git a/src/arvgc.c b/src/arvgc.c
index 90e9e9e..8d929c8 100644
--- a/src/arvgc.c
+++ b/src/arvgc.c
@@ -42,7 +42,7 @@
 #include <arvgcenumentry.h>
 #include <arvgcintegernode.h>
 #include <arvgcfloatnode.h>
-#include <arvgcregister.h>
+#include <arvgcregisternode.h>
 #include <arvgcstructentrynode.h>
 #include <arvgccommand.h>
 #include <arvgcinteger.h>
@@ -81,15 +81,15 @@ arv_gc_create_element (ArvDomDocument *document, const char *tag_name)
 	else if (strcmp (tag_name, "IntConverter") == 0)
 		node = arv_gc_converter_new_integer ();
 	else if (strcmp (tag_name, "IntReg") == 0)
-		node = arv_gc_register_new_integer ();
+		node = arv_gc_register_node_new_integer ();
 	else if (strcmp (tag_name, "MaskedIntReg") == 0)
-		node = arv_gc_register_new_masked_integer ();
+		node = arv_gc_register_node_new_masked_integer ();
 	else if (strcmp (tag_name, "FloatReg") == 0)
-		node = arv_gc_register_new_float ();
+		node = arv_gc_register_node_new_float ();
 	else if (strcmp (tag_name, "StringReg") == 0)
-		node = arv_gc_register_new_string ();
+		node = arv_gc_register_node_new_string ();
 	else if (strcmp (tag_name, "StructReg") == 0)
-		node = arv_gc_register_new_struct_register ();
+		node = arv_gc_register_node_new_struct_register ();
 	else if (strcmp (tag_name, "StructEntry") == 0)
 		node = arv_gc_struct_entry_node_new ();
 	else if (strcmp (tag_name, "Integer") == 0)
diff --git a/src/arvgcregister.c b/src/arvgcregister.c
index bbf78c8..d4e6d80 100644
--- a/src/arvgcregister.c
+++ b/src/arvgcregister.c
@@ -22,372 +22,45 @@
 
 /**
  * SECTION: arvgcregister
- * @short_description: Class for Register, IntReg, MaskedIntReg, FloatReg and StringReg nodes
+ * @short_description: Register interface
  */
 
 #include <arvgcregister.h>
-#include <arvgcindexnode.h>
-#include <arvgcinvalidatornode.h>
-#include <arvgcinteger.h>
-#include <arvgcfloat.h>
-#include <arvgcstring.h>
-#include <arvgcport.h>
-#include <arvgc.h>
 #include <arvmisc.h>
-#include <arvdebug.h>
-#include <stdlib.h>
-#include <string.h>
-
-static GObjectClass *parent_class = NULL;
-
-/* ArvDomNode implementation */
-
-static const char *
-arv_gc_register_get_node_name (ArvDomNode *node)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (node);
-
-	switch (gc_register->type) {
-		case ARV_GC_REGISTER_TYPE_REGISTER:
-			return "Register";
-		case ARV_GC_REGISTER_TYPE_INTEGER:
-			return "IntReg";
-		case ARV_GC_REGISTER_TYPE_MASKED_INTEGER:
-			return "MaskedIntReg";
-		case ARV_GC_REGISTER_TYPE_FLOAT:
-			return "FloatReg";
-		case ARV_GC_REGISTER_TYPE_STRING:
-			return "StringReg";
-		case ARV_GC_REGISTER_TYPE_STRUCT_REGISTER:
-			return "StuctReg";
-	}
-
-	return NULL;
-}
-
-static void
-arv_gc_register_post_new_child (ArvDomNode *self, ArvDomNode *child)
-{
-	ArvGcRegister *node = ARV_GC_REGISTER (self);
-
-	if (ARV_IS_GC_PROPERTY_NODE (child)) {
-		ArvGcPropertyNode *property_node = ARV_GC_PROPERTY_NODE (child);
-
-		switch (arv_gc_property_node_get_node_type (property_node)) {
-			case ARV_GC_PROPERTY_NODE_TYPE_ADDRESS:
-			case ARV_GC_PROPERTY_NODE_TYPE_P_ADDRESS:
-				node->addresses = g_slist_prepend (node->addresses, child);
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_P_INDEX:
-				node->index = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_LENGTH:
-			case ARV_GC_PROPERTY_NODE_TYPE_P_LENGTH:
-				node->length = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_P_PORT:
-				node->port = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_ACCESS_MODE:
-				/* TODO */
-				node->access_mode = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_CACHABLE:
-				node->cachable = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_POLLING_TIME:
-				/* TODO */
-				node->polling_time = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_ENDIANESS:
-				node->endianess = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_SIGN:
-				/* TODO */
-				node->sign = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_LSB:
-				node->lsb = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_MSB:
-				node->msb = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_BIT:
-				node->msb = property_node;
-				node->lsb = property_node;
-				break;
-			case ARV_GC_PROPERTY_NODE_TYPE_P_INVALIDATOR:
-				node->invalidators = g_slist_prepend (node->invalidators, property_node);
-				break;
-			default:
-				ARV_DOM_NODE_CLASS (parent_class)->post_new_child (self, child);
-				break;
-		}
-	}
-}
-
-static void
-arv_gc_register_pre_remove_child (ArvDomNode *self, ArvDomNode *child)
-{
-	g_assert_not_reached ();
-}
-
-/* ArvGcFeatureNode implementation */
-
-static GType
-arv_gc_register_get_value_type (ArvGcFeatureNode *node)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (node);
-
-	return gc_register->value_type;
-}
-
-static void
-arv_gc_register_set_value_from_string (ArvGcFeatureNode *node, const char *string)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (node);
-
-	switch (gc_register->value_type) {
-		case G_TYPE_INT64:
-			arv_gc_integer_set_value (ARV_GC_INTEGER (node), g_ascii_strtoll (string, NULL, 0));
-			break;
-		case G_TYPE_DOUBLE:
-			arv_gc_float_set_value (ARV_GC_FLOAT (node), g_ascii_strtod (string, NULL));
-			break;
-		case G_TYPE_STRING:
-			arv_gc_string_set_value (ARV_GC_STRING (node), string);
-			break;
-		default:
-			break;
-	}
-}
-
-static const char *
-arv_gc_register_get_value_as_string (ArvGcFeatureNode *node)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (node);
-
-	switch (gc_register->value_type) {
-		case G_TYPE_INT64:
-			g_snprintf (gc_register->v_string, G_ASCII_DTOSTR_BUF_SIZE,
-				    "0x%08" G_GINT64_MODIFIER "x", arv_gc_integer_get_value (ARV_GC_INTEGER (node)));
-			return gc_register->v_string;
-		case G_TYPE_DOUBLE:
-			g_ascii_dtostr (gc_register->v_string, G_ASCII_DTOSTR_BUF_SIZE,
-					arv_gc_float_get_value (ARV_GC_FLOAT (node)));
-			return gc_register->v_string;
-		case G_TYPE_STRING:
-			return arv_gc_string_get_value (ARV_GC_STRING (node));
-		default:
-			break;
-	}
-
-	return NULL;
-}
-
-/* ArvGcRegister implementation */
-
-gboolean
-_get_cache_validity (ArvGcRegister *gc_register)
-{
-	GSList *iter;
-	gint modification_count;
-	gint feature_modification_count;
-	gboolean is_cache_valid = gc_register->is_cache_valid;
-
-	for (iter = gc_register->invalidators; iter != NULL; iter = iter->next) {
-		ArvGcInvalidatorNode *invalidator = iter->data;
-		ArvGcNode *node;
-
-		modification_count = arv_gc_invalidator_node_get_modification_count (invalidator);
-		node = arv_gc_property_node_get_linked_node (ARV_GC_PROPERTY_NODE (invalidator));
-		feature_modification_count = arv_gc_feature_node_get_modification_count (ARV_GC_FEATURE_NODE (node));
-		arv_gc_invalidator_node_set_modification_count (invalidator, feature_modification_count);
-		if (modification_count != feature_modification_count)
-			is_cache_valid = FALSE;
-	}
-
-	return is_cache_valid;
-}
-
-static gint64
-_get_length (ArvGcRegister *gc_register)
-{
-	if (gc_register->length == NULL)
-		return 4;
-
-	return arv_gc_property_node_get_int64 (gc_register->length);
-}
 
 static void
-_update_cache_size (ArvGcRegister *gc_register)
+arv_gc_register_default_init (ArvGcRegisterInterface *gc_register_iface)
 {
-	gint64 length;
-
-	length = _get_length (gc_register);
-	if (length != gc_register->cache_size) {
-		g_free (gc_register->cache);
-		gc_register->cache = g_malloc (length);
-		gc_register->cache_size = length;
-	}
-
-}
-
-static ArvGcCachable
-_get_cachable (ArvGcRegister *gc_register)
-{
-	const char *cachable;
-
-	if (gc_register->cachable == NULL)
-		return ARV_GC_CACHABLE_NO_CACHE;
-
-	cachable = arv_gc_property_node_get_string (gc_register->cachable);
-	if (g_strcmp0 (cachable, "WriteThrough") == 0)
-		return ARV_GC_CACHABLE_WRITE_TRHOUGH;
-	else if (strcmp (cachable, "WriteAround") == 0)
-		return ARV_GC_CACHABLE_WRITE_AROUND;
-
-	return ARV_GC_CACHABLE_NO_CACHE;
 }
 
-/* Set default to read only 32 bits little endian integer register */
-
-static ArvGcCachable
-_get_endianess (ArvGcRegister *gc_register)
-{
-	const char *endianess;
-
-	if (gc_register->endianess == NULL)
-		return G_LITTLE_ENDIAN;
-
-	endianess = arv_gc_property_node_get_string (gc_register->endianess);
-	if (g_strcmp0 (endianess, "BigEndian") == 0)
-		return G_BIG_ENDIAN;
-
-	return G_LITTLE_ENDIAN;
-}
-
-static ArvGcCachable
-_get_lsb (ArvGcRegister *gc_register)
-{
-	if (gc_register->lsb == NULL)
-		return 0;
-
-	return arv_gc_property_node_get_int64 (gc_register->lsb);
-}
-
-static ArvGcCachable
-_get_msb (ArvGcRegister *gc_register)
-{
-	if (gc_register->msb == NULL)
-		return 31;
-
-	return arv_gc_property_node_get_int64 (gc_register->msb);
-}
-
-static void
-_read_cache (ArvGcRegister *gc_register)
-{
-	ArvGcNode *port;
-
-	if (gc_register->is_cache_valid == TRUE) {
-		arv_log_genicam ("[GcRegister::read_cache] Cache is valid");
-		return;
-	}
-
-	port = arv_gc_property_node_get_linked_node (gc_register->port);
-	if (!ARV_IS_GC_PORT (port))
-		return;
-
-	_update_cache_size (gc_register);
-
-	arv_gc_port_read (ARV_GC_PORT (port),
-			  gc_register->cache,
-			  arv_gc_register_get_address (gc_register),
-			  gc_register->cache_size);
-
-	if (_get_cachable (gc_register) != ARV_GC_CACHABLE_NO_CACHE)
-		gc_register->is_cache_valid = TRUE;
-	else
-		gc_register->is_cache_valid = FALSE;
-}
-
-static void
-_write_cache (ArvGcRegister *gc_register)
-{
-	ArvGcNode *port;
-
-	arv_gc_feature_node_inc_modification_count (ARV_GC_FEATURE_NODE (gc_register));
-
-	port = arv_gc_property_node_get_linked_node (gc_register->port);
-	if (!ARV_IS_GC_PORT (port))
-		return;
-
-	_update_cache_size (gc_register);
-
-	arv_gc_port_write (ARV_GC_PORT (port),
-			   gc_register->cache,
-			   arv_gc_register_get_address (gc_register),
-			   gc_register->cache_size);
-
-	if (_get_cachable (gc_register) == ARV_GC_CACHABLE_WRITE_TRHOUGH)
-		gc_register->is_cache_valid = TRUE;
-	else
-		gc_register->is_cache_valid = FALSE;
-}
+G_DEFINE_INTERFACE (ArvGcRegister, arv_gc_register, G_TYPE_OBJECT)
 
 void
 arv_gc_register_get (ArvGcRegister *gc_register, void *buffer, guint64 length)
 {
 	g_return_if_fail (ARV_IS_GC_REGISTER (gc_register));
+	g_return_if_fail (buffer != NULL);
+	g_return_if_fail (length > 0);
 
-	_read_cache (gc_register);
-
-	if (length > gc_register->cache_size) {
-		memcpy (buffer, gc_register->cache, gc_register->cache_size);
-		memset (buffer + gc_register->cache_size, 0, length - gc_register->cache_size);
-	} else
-		memcpy (buffer, gc_register->cache, length);
-
-	arv_log_genicam ("[GcRegister::get] 0x%Lx,%Ld",
-			 arv_gc_register_get_address (gc_register), length);
+	ARV_GC_REGISTER_GET_INTERFACE (gc_register)->get (gc_register, buffer, length);
 }
 
 void
 arv_gc_register_set (ArvGcRegister *gc_register, void *buffer, guint64 length)
 {
 	g_return_if_fail (ARV_IS_GC_REGISTER (gc_register));
+	g_return_if_fail (buffer != NULL);
+	g_return_if_fail (length > 0);
 
-	if (gc_register->cache_size > length) {
-		memcpy (gc_register->cache, buffer, length);
-		memset (gc_register->cache + length, 0, gc_register->cache_size - length);
-	} else
-		memcpy (gc_register->cache, buffer, gc_register->cache_size);
-
-	_write_cache (gc_register);
-
-	arv_log_genicam ("[GcRegister::set] 0x%Lx,%Ld", arv_gc_register_get_address (gc_register), length);
+	ARV_GC_REGISTER_GET_INTERFACE (gc_register)->set (gc_register, buffer, length);
 }
 
 guint64
 arv_gc_register_get_address (ArvGcRegister *gc_register)
 {
-	ArvGc *genicam;
-	GSList *iter;
-	guint64 value = 0;
-
 	g_return_val_if_fail (ARV_IS_GC_REGISTER (gc_register), 0);
-	genicam = arv_gc_node_get_genicam (ARV_GC_NODE (gc_register));
-	g_return_val_if_fail (ARV_IS_GC (genicam), 0);
-
-	for (iter = gc_register->addresses; iter != NULL; iter = iter->next)
-		value += arv_gc_property_node_get_int64 (iter->data);
 
-	if (gc_register->index != NULL)
-		value += arv_gc_index_node_get_index (ARV_GC_INDEX_NODE (gc_register->index),
-						      arv_gc_register_get_length (gc_register));
-
-	return value;
+	return ARV_GC_REGISTER_GET_INTERFACE (gc_register)->get_address (gc_register);
 }
 
 guint64
@@ -395,360 +68,5 @@ arv_gc_register_get_length (ArvGcRegister *gc_register)
 {
 	g_return_val_if_fail (ARV_IS_GC_REGISTER (gc_register), 0);
 
-	return _get_length (gc_register);
-}
-
-ArvGcNode *
-arv_gc_register_new (void)
-{
-	ArvGcRegister *gc_register;
-
-	gc_register = g_object_new (ARV_TYPE_GC_REGISTER, NULL);
-	gc_register->type = ARV_GC_REGISTER_TYPE_REGISTER;
-	gc_register->value_type = G_TYPE_BYTE_ARRAY;
-
-	return ARV_GC_NODE (gc_register);
-}
-
-ArvGcNode *
-arv_gc_register_new_integer (void)
-{
-	ArvGcRegister *gc_register;
-
-	gc_register = g_object_new (ARV_TYPE_GC_REGISTER, NULL);
-	gc_register->type = ARV_GC_REGISTER_TYPE_INTEGER;
-	gc_register->value_type = G_TYPE_INT64;
-
-	return ARV_GC_NODE (gc_register);
-}
-
-ArvGcNode *
-arv_gc_register_new_masked_integer (void)
-{
-	ArvGcRegister *gc_register;
-
-	gc_register = g_object_new (ARV_TYPE_GC_REGISTER, NULL);
-	gc_register->type = ARV_GC_REGISTER_TYPE_MASKED_INTEGER;
-	gc_register->value_type = G_TYPE_INT64;
-
-	return ARV_GC_NODE (gc_register);
-}
-
-ArvGcNode *
-arv_gc_register_new_float (void)
-{
-	ArvGcRegister *gc_register;
-
-	gc_register = g_object_new (ARV_TYPE_GC_REGISTER, NULL);
-	gc_register->type = ARV_GC_REGISTER_TYPE_FLOAT;
-	gc_register->value_type = G_TYPE_DOUBLE;
-
-	return ARV_GC_NODE (gc_register);
-}
-
-ArvGcNode *
-arv_gc_register_new_string (void)
-{
-	ArvGcRegister *gc_register;
-
-	gc_register = g_object_new (ARV_TYPE_GC_REGISTER, NULL);
-	gc_register->type = ARV_GC_REGISTER_TYPE_STRING;
-	gc_register->value_type = G_TYPE_STRING;
-
-	return ARV_GC_NODE (gc_register);
+	return ARV_GC_REGISTER_GET_INTERFACE (gc_register)->get_length (gc_register);
 }
-
-ArvGcNode *
-arv_gc_register_new_struct_register (void)
-{
-	ArvGcRegister *gc_register;
-
-	gc_register = g_object_new (ARV_TYPE_GC_REGISTER, NULL);
-	gc_register->type = ARV_GC_REGISTER_TYPE_STRUCT_REGISTER;
-	gc_register->value_type = G_TYPE_INT64;
-
-	return ARV_GC_NODE (gc_register);
-}
-
-static void
-arv_gc_register_init (ArvGcRegister *gc_register)
-{
-	gc_register->cache = g_malloc0(4);
-	gc_register->cache_size = 4;
-	gc_register->is_cache_valid = FALSE;
-}
-
-static void
-arv_gc_register_finalize (GObject *object)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (object);
-
-	g_slist_free (gc_register->addresses);
-	g_free (gc_register->cache);
-	g_slist_free (gc_register->invalidators);
-
-	parent_class->finalize (object);
-}
-
-static void
-arv_gc_register_class_init (ArvGcRegisterClass *this_class)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (this_class);
-	ArvDomNodeClass *dom_node_class = ARV_DOM_NODE_CLASS (this_class);
-	ArvGcFeatureNodeClass *gc_feature_node_class = ARV_GC_FEATURE_NODE_CLASS (this_class);
-
-	parent_class = g_type_class_peek_parent (this_class);
-
-	object_class->finalize = arv_gc_register_finalize;
-	dom_node_class->get_node_name = arv_gc_register_get_node_name;
-	dom_node_class->post_new_child = arv_gc_register_post_new_child;
-	dom_node_class->pre_remove_child = arv_gc_register_pre_remove_child;
-	gc_feature_node_class->get_value_type = arv_gc_register_get_value_type;
-	gc_feature_node_class->set_value_from_string = arv_gc_register_set_value_from_string;
-	gc_feature_node_class->get_value_as_string = arv_gc_register_get_value_as_string;
-}
-
-/* ArvGcInteger interface implementation */
-
-static gint64
-_get_integer_value (ArvGcRegister *gc_register, guint register_lsb, guint register_msb)
-{
-	gint64 value;
-	guint lsb;
-	guint msb;
-	guint endianess;
-
-	endianess = _get_endianess (gc_register);
-
-	_read_cache (gc_register);
-
-	arv_copy_memory_with_endianess (&value, sizeof (value), G_BYTE_ORDER,
-					gc_register->cache, gc_register->cache_size, endianess);
-
-	if (gc_register->type == ARV_GC_REGISTER_TYPE_MASKED_INTEGER ||
-	    gc_register->type == ARV_GC_REGISTER_TYPE_STRUCT_REGISTER) {
-		guint64 mask;
-
-		if (endianess == G_BYTE_ORDER) {
-			msb = register_msb;
-			lsb = register_lsb;
-		} else {
-			lsb = 8 * gc_register->cache_size - register_lsb - 1;
-			msb = 8 * gc_register->cache_size - register_msb - 1;
-		}
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-		if (msb - lsb < 63)
-			mask = ((((guint64) 1) << (msb - lsb + 1)) - 1) << lsb;
-		else
-			mask = G_MAXUINT64;
-
-		value = (value & mask) >> lsb;
-#else
-		g_assert_not_reached ();
-#endif
-	}
-
-	arv_log_genicam ("[GcRegister::_get_integer_value] address = 0x%Lx, value = 0x%Lx",
-			 arv_gc_register_get_address (gc_register),
-			 value);
-
-	return value;
-}
-
-gint64
-arv_gc_register_get_masked_integer_value (ArvGcRegister *gc_register, guint lsb, guint msb)
-{
-	g_return_val_if_fail (ARV_IS_GC_REGISTER (gc_register), 0);
-
-	return _get_integer_value (gc_register, lsb, msb);
-}
-
-static gint64
-arv_gc_register_get_integer_value (ArvGcInteger *gc_integer)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (gc_integer);
-
-	return _get_integer_value (gc_register, _get_lsb (gc_register), _get_msb (gc_register));
-}
-
-static void
-_set_integer_value (ArvGcRegister *gc_register, guint register_lsb, guint register_msb, gint64 value)
-{
-	guint lsb;
-	guint msb;
-	guint endianess;
-
-	endianess = _get_endianess (gc_register);
-
-	if (gc_register->type == ARV_GC_REGISTER_TYPE_MASKED_INTEGER ||
-	    gc_register->type == ARV_GC_REGISTER_TYPE_STRUCT_REGISTER) {
-		gint64 current_value;
-		guint64 mask;
-
-		_read_cache (gc_register);
-
-		arv_copy_memory_with_endianess (&current_value, sizeof (current_value), G_BYTE_ORDER,
-						gc_register->cache, gc_register->cache_size, endianess);
-
-		if (endianess == G_BYTE_ORDER) {
-			msb = register_msb;
-			lsb = register_lsb;
-		} else {
-			lsb = 8 * gc_register->cache_size - register_lsb - 1;
-			msb = 8 * gc_register->cache_size - register_msb - 1;
-		}
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-		if (msb - lsb < 63)
-			mask = ((((guint64) 1) << (msb - lsb + 1)) - 1) << lsb;
-		else
-			mask = G_MAXUINT64;
-
-		value = ((value << lsb) & mask) | (current_value & ~mask);
-#else
-		g_assert_not_reached ();
-#endif
-	}
-
-	arv_log_genicam ("[GcRegister::_set_integer_value] address = 0x%Lx, value = 0x%Lx",
-			 arv_gc_register_get_address (gc_register),
-			 value);
-
-	arv_copy_memory_with_endianess (gc_register->cache, gc_register->cache_size, endianess,
-					&value, sizeof (value), G_BYTE_ORDER);
-
-	_write_cache (gc_register);
-}
-
-void
-arv_gc_register_set_masked_integer_value (ArvGcRegister *gc_register, guint lsb, guint msb, gint64 value)
-{
-	g_return_if_fail (ARV_IS_GC_REGISTER (gc_register));
-
-	_set_integer_value (gc_register, lsb, msb, value);
-}
-
-static void
-arv_gc_register_set_integer_value (ArvGcInteger *gc_integer, gint64 value)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (gc_integer);
-
-	_set_integer_value (gc_register, _get_lsb (gc_register), _get_msb (gc_register), value);
-}
-
-static void
-arv_gc_register_integer_interface_init (ArvGcIntegerInterface *interface)
-{
-	interface->get_value = arv_gc_register_get_integer_value;
-	interface->set_value = arv_gc_register_set_integer_value;
-}
-
-static double
-arv_gc_register_get_float_value (ArvGcFloat *gc_float)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (gc_float);
-	guint endianess;
-
-	endianess = _get_endianess (gc_register);
-
-	_read_cache (gc_register);
-
-	if (gc_register->cache_size == 4) {
-		float v_float;
-		arv_copy_memory_with_endianess (&v_float, sizeof (v_float), G_BYTE_ORDER,
-						gc_register->cache, gc_register->cache_size, endianess);
-
-		return v_float;
-	} else if (gc_register->cache_size == 8) {
-		double v_double;
-		arv_copy_memory_with_endianess (&v_double, sizeof (v_double), G_BYTE_ORDER,
-						gc_register->cache, gc_register->cache_size, endianess);
-
-		return v_double;
-	} else {
-		arv_warning_genicam ("[GcFloatReg::get_value] Invalid register size");
-		return 0.0;
-	}
-}
-
-static void
-arv_gc_register_set_float_value (ArvGcFloat *gc_float, double v_double)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (gc_float);
-	guint endianess;
-
-	endianess = _get_endianess (gc_register);
-
-	_update_cache_size (gc_register);
-
-	if (gc_register->cache_size == 4) {
-		float v_float = v_double;
-		arv_copy_memory_with_endianess (gc_register->cache, gc_register->cache_size, endianess,
-						&v_float, sizeof (v_float), G_BYTE_ORDER);
-	} else if (gc_register->cache_size == 8) {
-		arv_copy_memory_with_endianess (gc_register->cache, gc_register->cache_size, endianess,
-						&v_double, sizeof (v_double), G_BYTE_ORDER);
-	} else {
-		arv_warning_genicam ("[GcFloatReg::set_value] Invalid register size");
-		return;
-	}
-
-	_write_cache (gc_register);
-}
-
-static void
-arv_gc_register_float_interface_init (ArvGcFloatInterface *interface)
-{
-	interface->get_value = arv_gc_register_get_float_value;
-	interface->set_value = arv_gc_register_set_float_value;
-}
-
-static const char *
-arv_gc_register_get_string_value (ArvGcString *gc_string)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (gc_string);
-
-	_read_cache (gc_register);
-
-	if (gc_register->cache_size > 0)
-		((char *) gc_register->cache)[gc_register->cache_size - 1] = '\0';
-
-	return gc_register->cache;
-}
-
-static void
-arv_gc_register_set_string_value (ArvGcString *gc_string, const char *value)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (gc_string);
-
-	_update_cache_size (gc_register);
-
-	if (gc_register->cache_size > 0) {
-		strncpy (gc_register->cache, value, gc_register->cache_size);
-		((char *) gc_register->cache)[gc_register->cache_size - 1] = '\0';
-
-		_write_cache (gc_register);
-	}
-}
-
-static gint64
-arv_gc_register_get_max_string_length (ArvGcString *gc_string)
-{
-	ArvGcRegister *gc_register = ARV_GC_REGISTER (gc_string);
-
-	return arv_gc_register_get_length (gc_register);
-}
-
-static void
-arv_gc_register_string_interface_init (ArvGcStringInterface *interface)
-{
-	interface->get_value = arv_gc_register_get_string_value;
-	interface->set_value = arv_gc_register_set_string_value;
-	interface->get_max_length = arv_gc_register_get_max_string_length;
-}
-
-G_DEFINE_TYPE_WITH_CODE (ArvGcRegister, arv_gc_register, ARV_TYPE_GC_FEATURE_NODE,
-			 G_IMPLEMENT_INTERFACE (ARV_TYPE_GC_INTEGER, arv_gc_register_integer_interface_init)
-			 G_IMPLEMENT_INTERFACE (ARV_TYPE_GC_FLOAT, arv_gc_register_float_interface_init)
-			 G_IMPLEMENT_INTERFACE (ARV_TYPE_GC_STRING, arv_gc_register_string_interface_init))
diff --git a/src/arvgcregister.h b/src/arvgcregister.h
index 930aa3c..b49bcf4 100644
--- a/src/arvgcregister.h
+++ b/src/arvgcregister.h
@@ -24,97 +24,32 @@
 #define ARV_GC_REGISTER_H
 
 #include <arvtypes.h>
-#include <arvgcfeaturenode.h>
-#include <arvgcpropertynode.h>
 
 G_BEGIN_DECLS
 
-/**
- * ArvGcSign:
- * @ARV_GC_SIGN_SIGNED: signed integer
- * @ARV_GC_SIGN_UNSIGNED: unsigned integer
- */
-
-typedef enum
-{
-	ARV_GC_SIGN_SIGNED,
-	ARV_GC_SIGN_UNSIGNED
-} ArvGcSign;
-
-/**
- * ArvGcRegisterType:
- * @ARV_GC_REGISTER_TYPE_REGISTER: Register node
- * @ARV_GC_REGISTER_TYPE_INTEGER: IntReg node
- * @ARV_GC_REGISTER_TYPE_MASKED_INTEGER: MaskedIntReg node
- * @ARV_GC_REGISTER_TYPE_FLOAT: FloatReg node
- * @ARV_GC_REGISTER_TYPE_STRING: StringReg node
- * @ARV_GC_REGISTER_TYPE_STRUCT_REGISTER: StructReg node
- */
-
-typedef enum {
-       ARV_GC_REGISTER_TYPE_REGISTER,
-       ARV_GC_REGISTER_TYPE_INTEGER,
-       ARV_GC_REGISTER_TYPE_MASKED_INTEGER,
-       ARV_GC_REGISTER_TYPE_FLOAT,
-       ARV_GC_REGISTER_TYPE_STRING,
-       ARV_GC_REGISTER_TYPE_STRUCT_REGISTER
-} ArvGcRegisterType;
-
-#define ARV_TYPE_GC_REGISTER             (arv_gc_register_get_type ())
-#define ARV_GC_REGISTER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), ARV_TYPE_GC_REGISTER, ArvGcRegister))
-#define ARV_GC_REGISTER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), ARV_TYPE_GC_REGISTER, ArvGcRegisterClass))
-#define ARV_IS_GC_REGISTER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ARV_TYPE_GC_REGISTER))
-#define ARV_IS_GC_REGISTER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), ARV_TYPE_GC_REGISTER))
-#define ARV_GC_REGISTER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), ARV_TYPE_GC_REGISTER, ArvGcRegisterClass))
+#define ARV_TYPE_GC_REGISTER             	(arv_gc_register_get_type ())
+#define ARV_GC_REGISTER(obj)             	(G_TYPE_CHECK_INSTANCE_CAST ((obj), ARV_TYPE_GC_REGISTER, ArvGcRegister))
+#define ARV_IS_GC_REGISTER(obj)          	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), ARV_TYPE_GC_REGISTER))
+#define ARV_GC_REGISTER_GET_INTERFACE(obj)   	(G_TYPE_INSTANCE_GET_INTERFACE((obj), ARV_TYPE_GC_REGISTER, ArvGcRegisterInterface))
 
-typedef struct _ArvGcRegisterClass ArvGcRegisterClass;
+typedef struct _ArvGcRegisterInterface ArvGcRegisterInterface;
 
-struct _ArvGcRegister {
-	ArvGcFeatureNode	node;
+struct _ArvGcRegisterInterface {
+	GTypeInterface parent;
 
-	ArvGcRegisterType type;
-	GType value_type;
-
-	GSList *addresses;
-	ArvGcPropertyNode *index;
-	ArvGcPropertyNode *length;
-	ArvGcPropertyNode *port;
-	ArvGcPropertyNode *access_mode;
-	ArvGcPropertyNode *cachable;
-	ArvGcPropertyNode *polling_time;
-	ArvGcPropertyNode *endianess;
-	ArvGcPropertyNode *sign;
-	ArvGcPropertyNode *lsb;
-	ArvGcPropertyNode *msb;
-
-	GSList *invalidators;		/* ArvGcPropertyNode list */
-
-	void *cache;
-	size_t cache_size;
-	gboolean is_cache_valid;
-
-	char v_string[G_ASCII_DTOSTR_BUF_SIZE];
+	void 		(*get)			(ArvGcRegister *gc_register, void *buffer, guint64 length);
+	void 		(*set)			(ArvGcRegister *gc_register, void *buffer, guint64 length);
+	guint64		(*get_address) 		(ArvGcRegister *gc_register);
+	guint64 	(*get_length)		(ArvGcRegister *gc_register);
 };
 
-struct _ArvGcRegisterClass {
-	ArvGcFeatureNodeClass parent_class;
-};
+GType arv_gc_register_get_type (void);
 
-GType 		arv_gc_register_get_type 		(void);
-ArvGcNode * 	arv_gc_register_new 			(void);
-ArvGcNode * 	arv_gc_register_new_integer 		(void);
-ArvGcNode * 	arv_gc_register_new_masked_integer 	(void);
-ArvGcNode * 	arv_gc_register_new_float	 	(void);
-ArvGcNode * 	arv_gc_register_new_string 		(void);
-ArvGcNode * 	arv_gc_register_new_struct_register	(void);
-void 		arv_gc_register_get			(ArvGcRegister *gc_register, void *buffer, guint64 Length);
-void 		arv_gc_register_set			(ArvGcRegister *gc_register, void *buffer, guint64 Length);
+void 		arv_gc_register_get			(ArvGcRegister *gc_register, void *buffer, guint64 length);
+void 		arv_gc_register_set			(ArvGcRegister *gc_register, void *buffer, guint64 length);
 guint64 	arv_gc_register_get_address 		(ArvGcRegister *gc_register);
 guint64 	arv_gc_register_get_length		(ArvGcRegister *gc_register);
 
-gint64 		arv_gc_register_get_masked_integer_value 	(ArvGcRegister *gc_register, guint lsb, guint msb);
-void 		arv_gc_register_set_masked_integer_value 	(ArvGcRegister *gc_register, guint lsb, guint msb, gint64 value);
-
 G_END_DECLS
 
 #endif
diff --git a/src/arvgcregisternode.c b/src/arvgcregisternode.c
new file mode 100644
index 0000000..605bdc6
--- /dev/null
+++ b/src/arvgcregisternode.c
@@ -0,0 +1,771 @@
+/* Aravis - Digital camera library
+ *
+ * Copyright  2009-2012 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+/**
+ * SECTION: arvgcregisternode
+ * @short_description: Class for Register, IntReg, MaskedIntReg, FloatReg and StringReg nodes
+ */
+
+#include <arvgcregisternode.h>
+#include <arvgcindexnode.h>
+#include <arvgcinvalidatornode.h>
+#include <arvgcregister.h>
+#include <arvgcinteger.h>
+#include <arvgcfloat.h>
+#include <arvgcstring.h>
+#include <arvgcport.h>
+#include <arvgc.h>
+#include <arvmisc.h>
+#include <arvdebug.h>
+#include <stdlib.h>
+#include <string.h>
+
+static GObjectClass *parent_class = NULL;
+
+/* ArvDomNode implementation */
+
+static const char *
+arv_gc_register_node_get_node_name (ArvDomNode *node)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (node);
+
+	switch (gc_register_node->type) {
+		case ARV_GC_REGISTER_NODE_TYPE_REGISTER:
+			return "Register";
+		case ARV_GC_REGISTER_NODE_TYPE_INTEGER:
+			return "IntReg";
+		case ARV_GC_REGISTER_NODE_TYPE_MASKED_INTEGER:
+			return "MaskedIntReg";
+		case ARV_GC_REGISTER_NODE_TYPE_FLOAT:
+			return "FloatReg";
+		case ARV_GC_REGISTER_NODE_TYPE_STRING:
+			return "StringReg";
+		case ARV_GC_REGISTER_NODE_TYPE_STRUCT_REGISTER:
+			return "StuctReg";
+	}
+
+	return NULL;
+}
+
+static void
+arv_gc_register_node_post_new_child (ArvDomNode *self, ArvDomNode *child)
+{
+	ArvGcRegisterNode *node = ARV_GC_REGISTER_NODE (self);
+
+	if (ARV_IS_GC_PROPERTY_NODE (child)) {
+		ArvGcPropertyNode *property_node = ARV_GC_PROPERTY_NODE (child);
+
+		switch (arv_gc_property_node_get_node_type (property_node)) {
+			case ARV_GC_PROPERTY_NODE_TYPE_ADDRESS:
+			case ARV_GC_PROPERTY_NODE_TYPE_P_ADDRESS:
+				node->addresses = g_slist_prepend (node->addresses, child);
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_P_INDEX:
+				node->index = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_LENGTH:
+			case ARV_GC_PROPERTY_NODE_TYPE_P_LENGTH:
+				node->length = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_P_PORT:
+				node->port = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_ACCESS_MODE:
+				/* TODO */
+				node->access_mode = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_CACHABLE:
+				node->cachable = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_POLLING_TIME:
+				/* TODO */
+				node->polling_time = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_ENDIANESS:
+				node->endianess = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_SIGN:
+				/* TODO */
+				node->sign = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_LSB:
+				node->lsb = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_MSB:
+				node->msb = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_BIT:
+				node->msb = property_node;
+				node->lsb = property_node;
+				break;
+			case ARV_GC_PROPERTY_NODE_TYPE_P_INVALIDATOR:
+				node->invalidators = g_slist_prepend (node->invalidators, property_node);
+				break;
+			default:
+				ARV_DOM_NODE_CLASS (parent_class)->post_new_child (self, child);
+				break;
+		}
+	}
+}
+
+static void
+arv_gc_register_node_pre_remove_child (ArvDomNode *self, ArvDomNode *child)
+{
+	g_assert_not_reached ();
+}
+
+/* ArvGcFeatureNode implementation */
+
+static GType
+arv_gc_register_node_get_value_type (ArvGcFeatureNode *node)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (node);
+
+	return gc_register_node->value_type;
+}
+
+static void
+arv_gc_register_node_set_value_from_string (ArvGcFeatureNode *node, const char *string)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (node);
+
+	switch (gc_register_node->value_type) {
+		case G_TYPE_INT64:
+			arv_gc_integer_set_value (ARV_GC_INTEGER (node), g_ascii_strtoll (string, NULL, 0));
+			break;
+		case G_TYPE_DOUBLE:
+			arv_gc_float_set_value (ARV_GC_FLOAT (node), g_ascii_strtod (string, NULL));
+			break;
+		case G_TYPE_STRING:
+			arv_gc_string_set_value (ARV_GC_STRING (node), string);
+			break;
+		default:
+			break;
+	}
+}
+
+static const char *
+arv_gc_register_node_get_value_as_string (ArvGcFeatureNode *node)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (node);
+
+	switch (gc_register_node->value_type) {
+		case G_TYPE_INT64:
+			g_snprintf (gc_register_node->v_string, G_ASCII_DTOSTR_BUF_SIZE,
+				    "0x%08" G_GINT64_MODIFIER "x", arv_gc_integer_get_value (ARV_GC_INTEGER (node)));
+			return gc_register_node->v_string;
+		case G_TYPE_DOUBLE:
+			g_ascii_dtostr (gc_register_node->v_string, G_ASCII_DTOSTR_BUF_SIZE,
+					arv_gc_float_get_value (ARV_GC_FLOAT (node)));
+			return gc_register_node->v_string;
+		case G_TYPE_STRING:
+			return arv_gc_string_get_value (ARV_GC_STRING (node));
+		default:
+			break;
+	}
+
+	return NULL;
+}
+
+/* ArvGcRegisterNode implementation */
+
+gboolean
+_get_cache_validity (ArvGcRegisterNode *gc_register_node)
+{
+	GSList *iter;
+	gint modification_count;
+	gint feature_modification_count;
+	gboolean is_cache_valid = gc_register_node->is_cache_valid;
+
+	for (iter = gc_register_node->invalidators; iter != NULL; iter = iter->next) {
+		ArvGcInvalidatorNode *invalidator = iter->data;
+		ArvGcNode *node;
+
+		modification_count = arv_gc_invalidator_node_get_modification_count (invalidator);
+		node = arv_gc_property_node_get_linked_node (ARV_GC_PROPERTY_NODE (invalidator));
+		feature_modification_count = arv_gc_feature_node_get_modification_count (ARV_GC_FEATURE_NODE (node));
+		arv_gc_invalidator_node_set_modification_count (invalidator, feature_modification_count);
+		if (modification_count != feature_modification_count)
+			is_cache_valid = FALSE;
+	}
+
+	return is_cache_valid;
+}
+
+static gint64
+_get_length (ArvGcRegisterNode *gc_register_node)
+{
+	if (gc_register_node->length == NULL)
+		return 4;
+
+	return arv_gc_property_node_get_int64 (gc_register_node->length);
+}
+
+static guint64
+_get_address (ArvGcRegisterNode *gc_register_node)
+{
+	ArvGc *genicam;
+	GSList *iter;
+	guint64 value = 0;
+
+	genicam = arv_gc_node_get_genicam (ARV_GC_NODE (gc_register_node));
+	g_return_val_if_fail (ARV_IS_GC (genicam), 0);
+
+	for (iter = gc_register_node->addresses; iter != NULL; iter = iter->next)
+		value += arv_gc_property_node_get_int64 (iter->data);
+
+	if (gc_register_node->index != NULL)
+		value += arv_gc_index_node_get_index (ARV_GC_INDEX_NODE (gc_register_node->index),
+						      _get_length (gc_register_node));
+
+	return value;
+}
+
+static void
+_update_cache_size (ArvGcRegisterNode *gc_register_node)
+{
+	gint64 length;
+
+	length = _get_length (gc_register_node);
+	if (length != gc_register_node->cache_size) {
+		g_free (gc_register_node->cache);
+		gc_register_node->cache = g_malloc (length);
+		gc_register_node->cache_size = length;
+	}
+
+}
+
+static ArvGcCachable
+_get_cachable (ArvGcRegisterNode *gc_register_node)
+{
+	const char *cachable;
+
+	if (gc_register_node->cachable == NULL)
+		return ARV_GC_CACHABLE_NO_CACHE;
+
+	cachable = arv_gc_property_node_get_string (gc_register_node->cachable);
+	if (g_strcmp0 (cachable, "WriteThrough") == 0)
+		return ARV_GC_CACHABLE_WRITE_TRHOUGH;
+	else if (strcmp (cachable, "WriteAround") == 0)
+		return ARV_GC_CACHABLE_WRITE_AROUND;
+
+	return ARV_GC_CACHABLE_NO_CACHE;
+}
+
+/* Set default to read only 32 bits little endian integer register */
+
+static ArvGcCachable
+_get_endianess (ArvGcRegisterNode *gc_register_node)
+{
+	const char *endianess;
+
+	if (gc_register_node->endianess == NULL)
+		return G_LITTLE_ENDIAN;
+
+	endianess = arv_gc_property_node_get_string (gc_register_node->endianess);
+	if (g_strcmp0 (endianess, "BigEndian") == 0)
+		return G_BIG_ENDIAN;
+
+	return G_LITTLE_ENDIAN;
+}
+
+static ArvGcCachable
+_get_lsb (ArvGcRegisterNode *gc_register_node)
+{
+	if (gc_register_node->lsb == NULL)
+		return 0;
+
+	return arv_gc_property_node_get_int64 (gc_register_node->lsb);
+}
+
+static ArvGcCachable
+_get_msb (ArvGcRegisterNode *gc_register_node)
+{
+	if (gc_register_node->msb == NULL)
+		return 31;
+
+	return arv_gc_property_node_get_int64 (gc_register_node->msb);
+}
+
+static void
+_read_cache (ArvGcRegisterNode *gc_register_node)
+{
+	ArvGcNode *port;
+
+	if (gc_register_node->is_cache_valid == TRUE) {
+		arv_log_genicam ("[GcRegisterNode::read_cache] Cache is valid");
+		return;
+	}
+
+	port = arv_gc_property_node_get_linked_node (gc_register_node->port);
+	if (!ARV_IS_GC_PORT (port))
+		return;
+
+	_update_cache_size (gc_register_node);
+
+	arv_gc_port_read (ARV_GC_PORT (port),
+			  gc_register_node->cache,
+			  _get_address (gc_register_node),
+			  gc_register_node->cache_size);
+
+	if (_get_cachable (gc_register_node) != ARV_GC_CACHABLE_NO_CACHE)
+		gc_register_node->is_cache_valid = TRUE;
+	else
+		gc_register_node->is_cache_valid = FALSE;
+}
+
+static void
+_write_cache (ArvGcRegisterNode *gc_register_node)
+{
+	ArvGcNode *port;
+
+	arv_gc_feature_node_inc_modification_count (ARV_GC_FEATURE_NODE (gc_register_node));
+
+	port = arv_gc_property_node_get_linked_node (gc_register_node->port);
+	if (!ARV_IS_GC_PORT (port))
+		return;
+
+	_update_cache_size (gc_register_node);
+
+	arv_gc_port_write (ARV_GC_PORT (port),
+			   gc_register_node->cache,
+			   _get_address (gc_register_node),
+			   gc_register_node->cache_size);
+
+	if (_get_cachable (gc_register_node) == ARV_GC_CACHABLE_WRITE_TRHOUGH)
+		gc_register_node->is_cache_valid = TRUE;
+	else
+		gc_register_node->is_cache_valid = FALSE;
+}
+
+ArvGcNode *
+arv_gc_register_node_new (void)
+{
+	ArvGcRegisterNode *gc_register_node;
+
+	gc_register_node = g_object_new (ARV_TYPE_GC_REGISTER_NODE, NULL);
+	gc_register_node->type = ARV_GC_REGISTER_NODE_TYPE_REGISTER;
+	gc_register_node->value_type = G_TYPE_BYTE_ARRAY;
+
+	return ARV_GC_NODE (gc_register_node);
+}
+
+ArvGcNode *
+arv_gc_register_node_new_integer (void)
+{
+	ArvGcRegisterNode *gc_register_node;
+
+	gc_register_node = g_object_new (ARV_TYPE_GC_REGISTER_NODE, NULL);
+	gc_register_node->type = ARV_GC_REGISTER_NODE_TYPE_INTEGER;
+	gc_register_node->value_type = G_TYPE_INT64;
+
+	return ARV_GC_NODE (gc_register_node);
+}
+
+ArvGcNode *
+arv_gc_register_node_new_masked_integer (void)
+{
+	ArvGcRegisterNode *gc_register_node;
+
+	gc_register_node = g_object_new (ARV_TYPE_GC_REGISTER_NODE, NULL);
+	gc_register_node->type = ARV_GC_REGISTER_NODE_TYPE_MASKED_INTEGER;
+	gc_register_node->value_type = G_TYPE_INT64;
+
+	return ARV_GC_NODE (gc_register_node);
+}
+
+ArvGcNode *
+arv_gc_register_node_new_float (void)
+{
+	ArvGcRegisterNode *gc_register_node;
+
+	gc_register_node = g_object_new (ARV_TYPE_GC_REGISTER_NODE, NULL);
+	gc_register_node->type = ARV_GC_REGISTER_NODE_TYPE_FLOAT;
+	gc_register_node->value_type = G_TYPE_DOUBLE;
+
+	return ARV_GC_NODE (gc_register_node);
+}
+
+ArvGcNode *
+arv_gc_register_node_new_string (void)
+{
+	ArvGcRegisterNode *gc_register_node;
+
+	gc_register_node = g_object_new (ARV_TYPE_GC_REGISTER_NODE, NULL);
+	gc_register_node->type = ARV_GC_REGISTER_NODE_TYPE_STRING;
+	gc_register_node->value_type = G_TYPE_STRING;
+
+	return ARV_GC_NODE (gc_register_node);
+}
+
+ArvGcNode *
+arv_gc_register_node_new_struct_register (void)
+{
+	ArvGcRegisterNode *gc_register_node;
+
+	gc_register_node = g_object_new (ARV_TYPE_GC_REGISTER_NODE, NULL);
+	gc_register_node->type = ARV_GC_REGISTER_NODE_TYPE_STRUCT_REGISTER;
+	gc_register_node->value_type = G_TYPE_INT64;
+
+	return ARV_GC_NODE (gc_register_node);
+}
+
+static void
+arv_gc_register_node_init (ArvGcRegisterNode *gc_register_node)
+{
+	gc_register_node->cache = g_malloc0(4);
+	gc_register_node->cache_size = 4;
+	gc_register_node->is_cache_valid = FALSE;
+}
+
+static void
+arv_gc_register_node_finalize (GObject *object)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (object);
+
+	g_slist_free (gc_register_node->addresses);
+	g_free (gc_register_node->cache);
+	g_slist_free (gc_register_node->invalidators);
+
+	parent_class->finalize (object);
+}
+
+static void
+arv_gc_register_node_class_init (ArvGcRegisterNodeClass *this_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (this_class);
+	ArvDomNodeClass *dom_node_class = ARV_DOM_NODE_CLASS (this_class);
+	ArvGcFeatureNodeClass *gc_feature_node_class = ARV_GC_FEATURE_NODE_CLASS (this_class);
+
+	parent_class = g_type_class_peek_parent (this_class);
+
+	object_class->finalize = arv_gc_register_node_finalize;
+	dom_node_class->get_node_name = arv_gc_register_node_get_node_name;
+	dom_node_class->post_new_child = arv_gc_register_node_post_new_child;
+	dom_node_class->pre_remove_child = arv_gc_register_node_pre_remove_child;
+	gc_feature_node_class->get_value_type = arv_gc_register_node_get_value_type;
+	gc_feature_node_class->set_value_from_string = arv_gc_register_node_set_value_from_string;
+	gc_feature_node_class->get_value_as_string = arv_gc_register_node_get_value_as_string;
+}
+
+/* ArvGcRegister interface implementation */
+
+static void
+arv_gc_register_node_get (ArvGcRegister *gc_register, void *buffer, guint64 length)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_register);
+
+	_read_cache (gc_register_node);
+
+	if (length > gc_register_node->cache_size) {
+		memcpy (buffer, gc_register_node->cache, gc_register_node->cache_size);
+		memset (buffer + gc_register_node->cache_size, 0, length - gc_register_node->cache_size);
+	} else
+		memcpy (buffer, gc_register_node->cache, length);
+
+	arv_log_genicam ("[GcRegisterNode::get] 0x%Lx,%Ld", _get_address (gc_register_node), length);
+}
+
+static void
+arv_gc_register_node_set (ArvGcRegister *gc_register, void *buffer, guint64 length)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_register);
+
+	if (gc_register_node->cache_size > length) {
+		memcpy (gc_register_node->cache, buffer, length);
+		memset (gc_register_node->cache + length, 0, gc_register_node->cache_size - length);
+	} else
+		memcpy (gc_register_node->cache, buffer, gc_register_node->cache_size);
+
+	_write_cache (gc_register_node);
+
+	arv_log_genicam ("[GcRegisterNode::set] 0x%Lx,%Ld", _get_address (gc_register_node), length);
+}
+
+static guint64
+arv_gc_register_node_get_address (ArvGcRegister *gc_register)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_register);
+
+	return _get_address (gc_register_node);
+}
+
+static guint64
+arv_gc_register_node_get_length (ArvGcRegister *gc_register)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_register);
+
+	return _get_length (gc_register_node);
+}
+
+static void
+arv_gc_register_node_register_interface_init (ArvGcRegisterInterface *interface)
+{
+	interface->get = arv_gc_register_node_get;
+	interface->set = arv_gc_register_node_set;
+	interface->get_address = arv_gc_register_node_get_address;
+	interface->get_length = arv_gc_register_node_get_length;
+}
+
+/* ArvGcInteger interface implementation */
+
+static gint64
+_get_integer_value (ArvGcRegisterNode *gc_register_node, guint register_lsb, guint register_msb)
+{
+	gint64 value;
+	guint lsb;
+	guint msb;
+	guint endianess;
+
+	endianess = _get_endianess (gc_register_node);
+
+	_read_cache (gc_register_node);
+
+	arv_copy_memory_with_endianess (&value, sizeof (value), G_BYTE_ORDER,
+					gc_register_node->cache, gc_register_node->cache_size, endianess);
+
+	if (gc_register_node->type == ARV_GC_REGISTER_NODE_TYPE_MASKED_INTEGER ||
+	    gc_register_node->type == ARV_GC_REGISTER_NODE_TYPE_STRUCT_REGISTER) {
+		guint64 mask;
+
+		if (endianess == G_BYTE_ORDER) {
+			msb = register_msb;
+			lsb = register_lsb;
+		} else {
+			lsb = 8 * gc_register_node->cache_size - register_lsb - 1;
+			msb = 8 * gc_register_node->cache_size - register_msb - 1;
+		}
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+		if (msb - lsb < 63)
+			mask = ((((guint64) 1) << (msb - lsb + 1)) - 1) << lsb;
+		else
+			mask = G_MAXUINT64;
+
+		value = (value & mask) >> lsb;
+#else
+		g_assert_not_reached ();
+#endif
+	}
+
+	arv_log_genicam ("[GcRegisterNode::_get_integer_value] address = 0x%Lx, value = 0x%Lx",
+			 _get_address (gc_register_node), value);
+
+	return value;
+}
+
+gint64
+arv_gc_register_node_get_masked_integer_value (ArvGcRegisterNode *gc_register_node, guint lsb, guint msb)
+{
+	g_return_val_if_fail (ARV_IS_GC_REGISTER_NODE (gc_register_node), 0);
+
+	return _get_integer_value (gc_register_node, lsb, msb);
+}
+
+static gint64
+arv_gc_register_node_get_integer_value (ArvGcInteger *gc_integer)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_integer);
+
+	return _get_integer_value (gc_register_node, _get_lsb (gc_register_node), _get_msb (gc_register_node));
+}
+
+static void
+_set_integer_value (ArvGcRegisterNode *gc_register_node, guint register_lsb, guint register_msb, gint64 value)
+{
+	guint lsb;
+	guint msb;
+	guint endianess;
+
+	endianess = _get_endianess (gc_register_node);
+
+	if (gc_register_node->type == ARV_GC_REGISTER_NODE_TYPE_MASKED_INTEGER ||
+	    gc_register_node->type == ARV_GC_REGISTER_NODE_TYPE_STRUCT_REGISTER) {
+		gint64 current_value;
+		guint64 mask;
+
+		_read_cache (gc_register_node);
+
+		arv_copy_memory_with_endianess (&current_value, sizeof (current_value), G_BYTE_ORDER,
+						gc_register_node->cache, gc_register_node->cache_size, endianess);
+
+		if (endianess == G_BYTE_ORDER) {
+			msb = register_msb;
+			lsb = register_lsb;
+		} else {
+			lsb = 8 * gc_register_node->cache_size - register_lsb - 1;
+			msb = 8 * gc_register_node->cache_size - register_msb - 1;
+		}
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+		if (msb - lsb < 63)
+			mask = ((((guint64) 1) << (msb - lsb + 1)) - 1) << lsb;
+		else
+			mask = G_MAXUINT64;
+
+		value = ((value << lsb) & mask) | (current_value & ~mask);
+#else
+		g_assert_not_reached ();
+#endif
+	}
+
+	arv_log_genicam ("[GcRegisterNode::_set_integer_value] address = 0x%Lx, value = 0x%Lx",
+			 _get_address (gc_register_node), value);
+
+	arv_copy_memory_with_endianess (gc_register_node->cache, gc_register_node->cache_size, endianess,
+					&value, sizeof (value), G_BYTE_ORDER);
+
+	_write_cache (gc_register_node);
+}
+
+void
+arv_gc_register_node_set_masked_integer_value (ArvGcRegisterNode *gc_register_node, guint lsb, guint msb, gint64 value)
+{
+	g_return_if_fail (ARV_IS_GC_REGISTER_NODE (gc_register_node));
+
+	_set_integer_value (gc_register_node, lsb, msb, value);
+}
+
+static void
+arv_gc_register_node_set_integer_value (ArvGcInteger *gc_integer, gint64 value)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_integer);
+
+	_set_integer_value (gc_register_node, _get_lsb (gc_register_node), _get_msb (gc_register_node), value);
+}
+
+static void
+arv_gc_register_node_integer_interface_init (ArvGcIntegerInterface *interface)
+{
+	interface->get_value = arv_gc_register_node_get_integer_value;
+	interface->set_value = arv_gc_register_node_set_integer_value;
+}
+
+static double
+arv_gc_register_node_get_float_value (ArvGcFloat *gc_float)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_float);
+	guint endianess;
+
+	endianess = _get_endianess (gc_register_node);
+
+	_read_cache (gc_register_node);
+
+	if (gc_register_node->cache_size == 4) {
+		float v_float;
+		arv_copy_memory_with_endianess (&v_float, sizeof (v_float), G_BYTE_ORDER,
+						gc_register_node->cache, gc_register_node->cache_size, endianess);
+
+		return v_float;
+	} else if (gc_register_node->cache_size == 8) {
+		double v_double;
+		arv_copy_memory_with_endianess (&v_double, sizeof (v_double), G_BYTE_ORDER,
+						gc_register_node->cache, gc_register_node->cache_size, endianess);
+
+		return v_double;
+	} else {
+		arv_warning_genicam ("[GcFloatReg::get_value] Invalid register size");
+		return 0.0;
+	}
+}
+
+static void
+arv_gc_register_node_set_float_value (ArvGcFloat *gc_float, double v_double)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_float);
+	guint endianess;
+
+	endianess = _get_endianess (gc_register_node);
+
+	_update_cache_size (gc_register_node);
+
+	if (gc_register_node->cache_size == 4) {
+		float v_float = v_double;
+		arv_copy_memory_with_endianess (gc_register_node->cache, gc_register_node->cache_size, endianess,
+						&v_float, sizeof (v_float), G_BYTE_ORDER);
+	} else if (gc_register_node->cache_size == 8) {
+		arv_copy_memory_with_endianess (gc_register_node->cache, gc_register_node->cache_size, endianess,
+						&v_double, sizeof (v_double), G_BYTE_ORDER);
+	} else {
+		arv_warning_genicam ("[GcFloatReg::set_value] Invalid register size");
+		return;
+	}
+
+	_write_cache (gc_register_node);
+}
+
+static void
+arv_gc_register_node_float_interface_init (ArvGcFloatInterface *interface)
+{
+	interface->get_value = arv_gc_register_node_get_float_value;
+	interface->set_value = arv_gc_register_node_set_float_value;
+}
+
+static const char *
+arv_gc_register_node_get_string_value (ArvGcString *gc_string)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_string);
+
+	_read_cache (gc_register_node);
+
+	if (gc_register_node->cache_size > 0)
+		((char *) gc_register_node->cache)[gc_register_node->cache_size - 1] = '\0';
+
+	return gc_register_node->cache;
+}
+
+static void
+arv_gc_register_node_set_string_value (ArvGcString *gc_string, const char *value)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_string);
+
+	_update_cache_size (gc_register_node);
+
+	if (gc_register_node->cache_size > 0) {
+		strncpy (gc_register_node->cache, value, gc_register_node->cache_size);
+		((char *) gc_register_node->cache)[gc_register_node->cache_size - 1] = '\0';
+
+		_write_cache (gc_register_node);
+	}
+}
+
+static gint64
+arv_gc_register_node_get_max_string_length (ArvGcString *gc_string)
+{
+	ArvGcRegisterNode *gc_register_node = ARV_GC_REGISTER_NODE (gc_string);
+
+	return _get_length (gc_register_node);
+}
+
+static void
+arv_gc_register_node_string_interface_init (ArvGcStringInterface *interface)
+{
+	interface->get_value = arv_gc_register_node_get_string_value;
+	interface->set_value = arv_gc_register_node_set_string_value;
+	interface->get_max_length = arv_gc_register_node_get_max_string_length;
+}
+
+G_DEFINE_TYPE_WITH_CODE (ArvGcRegisterNode, arv_gc_register_node, ARV_TYPE_GC_FEATURE_NODE,
+			 G_IMPLEMENT_INTERFACE (ARV_TYPE_GC_REGISTER, arv_gc_register_node_register_interface_init)
+			 G_IMPLEMENT_INTERFACE (ARV_TYPE_GC_INTEGER, arv_gc_register_node_integer_interface_init)
+			 G_IMPLEMENT_INTERFACE (ARV_TYPE_GC_FLOAT, arv_gc_register_node_float_interface_init)
+			 G_IMPLEMENT_INTERFACE (ARV_TYPE_GC_STRING, arv_gc_register_node_string_interface_init))
diff --git a/src/arvgcregisternode.h b/src/arvgcregisternode.h
new file mode 100644
index 0000000..c73d2e8
--- /dev/null
+++ b/src/arvgcregisternode.h
@@ -0,0 +1,116 @@
+/* Aravis - Digital camera library
+ *
+ * Copyright  2009-2012 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef ARV_GC_REGISTER_NODE_H
+#define ARV_GC_REGISTER_NODE_H
+
+#include <arvtypes.h>
+#include <arvgcfeaturenode.h>
+#include <arvgcpropertynode.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ArvGcSign:
+ * @ARV_GC_SIGN_SIGNED: signed integer
+ * @ARV_GC_SIGN_UNSIGNED: unsigned integer
+ */
+
+typedef enum
+{
+	ARV_GC_SIGN_SIGNED,
+	ARV_GC_SIGN_UNSIGNED
+} ArvGcSign;
+
+/**
+ * ArvGcRegisterNodeType:
+ * @ARV_GC_REGISTER_NODE_TYPE_REGISTER: Register node
+ * @ARV_GC_REGISTER_NODE_TYPE_INTEGER: IntReg node
+ * @ARV_GC_REGISTER_NODE_TYPE_MASKED_INTEGER: MaskedIntReg node
+ * @ARV_GC_REGISTER_NODE_TYPE_FLOAT: FloatReg node
+ * @ARV_GC_REGISTER_NODE_TYPE_STRING: StringReg node
+ * @ARV_GC_REGISTER_NODE_TYPE_STRUCT_REGISTER: StructReg node
+ */
+
+typedef enum {
+       ARV_GC_REGISTER_NODE_TYPE_REGISTER,
+       ARV_GC_REGISTER_NODE_TYPE_INTEGER,
+       ARV_GC_REGISTER_NODE_TYPE_MASKED_INTEGER,
+       ARV_GC_REGISTER_NODE_TYPE_FLOAT,
+       ARV_GC_REGISTER_NODE_TYPE_STRING,
+       ARV_GC_REGISTER_NODE_TYPE_STRUCT_REGISTER
+} ArvGcRegisterNodeType;
+
+#define ARV_TYPE_GC_REGISTER_NODE             (arv_gc_register_node_get_type ())
+#define ARV_GC_REGISTER_NODE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), ARV_TYPE_GC_REGISTER_NODE, ArvGcRegisterNode))
+#define ARV_GC_REGISTER_NODE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), ARV_TYPE_GC_REGISTER_NODE, ArvGcRegisterNodeClass))
+#define ARV_IS_GC_REGISTER_NODE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ARV_TYPE_GC_REGISTER_NODE))
+#define ARV_IS_GC_REGISTER_NODE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), ARV_TYPE_GC_REGISTER_NODE))
+#define ARV_GC_REGISTER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), ARV_TYPE_GC_REGISTER_NODE, ArvGcRegisterNodeClass))
+
+typedef struct _ArvGcRegisterNodeClass ArvGcRegisterNodeClass;
+
+struct _ArvGcRegisterNode {
+	ArvGcFeatureNode	node;
+
+	ArvGcRegisterNodeType type;
+	GType value_type;
+
+	GSList *addresses;
+	ArvGcPropertyNode *index;
+	ArvGcPropertyNode *length;
+	ArvGcPropertyNode *port;
+	ArvGcPropertyNode *access_mode;
+	ArvGcPropertyNode *cachable;
+	ArvGcPropertyNode *polling_time;
+	ArvGcPropertyNode *endianess;
+	ArvGcPropertyNode *sign;
+	ArvGcPropertyNode *lsb;
+	ArvGcPropertyNode *msb;
+
+	GSList *invalidators;		/* ArvGcPropertyNode list */
+
+	void *cache;
+	size_t cache_size;
+	gboolean is_cache_valid;
+
+	char v_string[G_ASCII_DTOSTR_BUF_SIZE];
+};
+
+struct _ArvGcRegisterNodeClass {
+	ArvGcFeatureNodeClass parent_class;
+};
+
+GType 		arv_gc_register_node_get_type 			(void);
+ArvGcNode * 	arv_gc_register_node_new 			(void);
+ArvGcNode * 	arv_gc_register_node_new_integer 		(void);
+ArvGcNode * 	arv_gc_register_node_new_masked_integer 	(void);
+ArvGcNode * 	arv_gc_register_node_new_float	 		(void);
+ArvGcNode * 	arv_gc_register_node_new_string 		(void);
+ArvGcNode * 	arv_gc_register_node_new_struct_register	(void);
+
+gint64 		arv_gc_register_node_get_masked_integer_value 	(ArvGcRegisterNode *gc_register_node, guint lsb, guint msb);
+void 		arv_gc_register_node_set_masked_integer_value 	(ArvGcRegisterNode *gc_register_node, guint lsb, guint msb, gint64 value);
+
+G_END_DECLS
+
+#endif
diff --git a/src/arvgcstructentrynode.c b/src/arvgcstructentrynode.c
index 909c0b2..3dc5c3c 100644
--- a/src/arvgcstructentrynode.c
+++ b/src/arvgcstructentrynode.c
@@ -26,6 +26,7 @@
  */
 
 #include <arvgcstructentrynode.h>
+#include <arvgcregisternode.h>
 #include <arvgcregister.h>
 #include <arvgcinteger.h>
 #include <arvgcport.h>
@@ -174,6 +175,57 @@ arv_gc_struct_entry_node_class_init (ArvGcStructEntryNodeClass *this_class)
 	gc_feature_node_class->get_value_as_string = arv_gc_struct_entry_node_get_value_as_string;
 }
 
+/* ArvGcRegister interface implementation */
+
+static void
+arv_gc_struct_entry_node_get (ArvGcRegister *gc_register, void *buffer, guint64 length)
+{
+	ArvDomNode *struct_register = arv_dom_node_get_parent_node (ARV_DOM_NODE (gc_register));
+
+	if (ARV_IS_GC_REGISTER (struct_register))
+		arv_gc_register_get (ARV_GC_REGISTER (struct_register), buffer, length);
+}
+
+static void
+arv_gc_struct_entry_node_set (ArvGcRegister *gc_register, void *buffer, guint64 length)
+{
+	ArvDomNode *struct_register = arv_dom_node_get_parent_node (ARV_DOM_NODE (gc_register));
+
+	if (ARV_IS_GC_REGISTER (struct_register))
+		return arv_gc_register_set (ARV_GC_REGISTER (struct_register), buffer, length);
+}
+
+static guint64
+arv_gc_struct_entry_node_get_address (ArvGcRegister *gc_register)
+{
+	ArvDomNode *struct_register = arv_dom_node_get_parent_node (ARV_DOM_NODE (gc_register));
+
+	if (ARV_IS_GC_REGISTER (struct_register))
+		return arv_gc_register_get_address (ARV_GC_REGISTER (struct_register));
+
+	return 0;
+}
+
+static guint64
+arv_gc_struct_entry_node_get_length (ArvGcRegister *gc_register)
+{
+	ArvDomNode *struct_register = arv_dom_node_get_parent_node (ARV_DOM_NODE (gc_register));
+
+	if (ARV_IS_GC_REGISTER (struct_register))
+		return arv_gc_register_get_length (ARV_GC_REGISTER (struct_register));
+
+	return 0;
+}
+
+static void
+arv_gc_struct_entry_node_register_interface_init (ArvGcRegisterInterface *interface)
+{
+	interface->get = arv_gc_struct_entry_node_get;
+	interface->set = arv_gc_struct_entry_node_set;
+	interface->get_address = arv_gc_struct_entry_node_get_address;
+	interface->get_length = arv_gc_struct_entry_node_get_length;
+}
+
 /* ArvGcInteger interface implementation */
 
 static gint64
@@ -185,13 +237,13 @@ arv_gc_struct_entry_node_get_integer_value (ArvGcInteger *gc_integer)
 	guint msb;
 
 	struct_register = arv_dom_node_get_parent_node (ARV_DOM_NODE (gc_integer));
-	if (!ARV_IS_GC_REGISTER (struct_register))
+	if (!ARV_IS_GC_REGISTER_NODE (struct_register))
 		return 0;
 
 	lsb = _get_lsb (struct_entry);
 	msb = _get_msb (struct_entry);
 
-	return arv_gc_register_get_masked_integer_value (ARV_GC_REGISTER (struct_register), lsb, msb);
+	return arv_gc_register_node_get_masked_integer_value (ARV_GC_REGISTER_NODE (struct_register), lsb, msb);
 }
 
 static void
@@ -203,13 +255,13 @@ arv_gc_struct_entry_node_set_integer_value (ArvGcInteger *gc_integer, gint64 val
 	guint msb;
 
 	struct_register = arv_dom_node_get_parent_node (ARV_DOM_NODE (gc_integer));
-	if (!ARV_IS_GC_REGISTER (struct_register))
+	if (!ARV_IS_GC_REGISTER_NODE (struct_register))
 		return;
 
 	lsb = _get_lsb (struct_entry);
 	msb = _get_msb (struct_entry);
 
-	arv_gc_register_set_masked_integer_value (ARV_GC_REGISTER (struct_register), lsb, msb, value);
+	arv_gc_register_node_set_masked_integer_value (ARV_GC_REGISTER_NODE (struct_register), lsb, msb, value);
 }
 
 static void
@@ -220,4 +272,5 @@ arv_gc_struct_entry_node_integer_interface_init (ArvGcIntegerInterface *interfac
 }
 
 G_DEFINE_TYPE_WITH_CODE (ArvGcStructEntryNode, arv_gc_struct_entry_node, ARV_TYPE_GC_FEATURE_NODE,
+			 G_IMPLEMENT_INTERFACE (ARV_TYPE_GC_REGISTER, arv_gc_struct_entry_node_register_interface_init)
 			 G_IMPLEMENT_INTERFACE (ARV_TYPE_GC_INTEGER, arv_gc_struct_entry_node_integer_interface_init))
diff --git a/src/arvtypes.h b/src/arvtypes.h
index 0b503ea..b7da15d 100644
--- a/src/arvtypes.h
+++ b/src/arvtypes.h
@@ -56,13 +56,14 @@ typedef struct _ArvGcEnumeration		ArvGcEnumeration;
 typedef struct _ArvGcEnumEntry			ArvGcEnumEntry;
 typedef struct _ArvGcIntegerNode		ArvGcIntegerNode;
 typedef struct _ArvGcFloatNode			ArvGcFloatNode;
-typedef struct _ArvGcRegister 			ArvGcRegister;
+typedef struct _ArvGcRegisterNode 		ArvGcRegisterNode;
 typedef struct _ArvGcStructEntryNode		ArvGcStructEntryNode;
 typedef struct _ArvGcCommand			ArvGcCommand;
 typedef struct _ArvGcSwissKnife			ArvGcSwissKnife;
 typedef struct _ArvGcConverter			ArvGcConverter;
 typedef struct _ArvGcPort			ArvGcPort;
 
+typedef struct _ArvGcRegister		ArvGcRegister;
 typedef struct _ArvGcInteger		ArvGcInteger;
 typedef struct _ArvGcFloat		ArvGcFloat;
 typedef struct _ArvGcString		ArvGcString;
diff --git a/tests/fake.c b/tests/fake.c
index 1c84a0c..4865ec6 100644
--- a/tests/fake.c
+++ b/tests/fake.c
@@ -62,6 +62,7 @@ registers_test (void)
 	ArvGcNode *node_b;
 	ArvGcNode *node_c;
 	gint64 value;
+	gint64 address;
 
 	device = arv_fake_device_new ("TEST0");
 	g_assert (ARV_IS_FAKE_DEVICE (device));
@@ -72,6 +73,9 @@ registers_test (void)
 	node = arv_gc_get_node (genicam, "TestRegister");
 	g_assert (ARV_IS_GC_NODE (node));
 
+	address = arv_gc_register_get_address (ARV_GC_REGISTER (node));
+	g_assert_cmpint (address, ==, 0x1f0);
+
 	arv_gc_integer_set_value (ARV_GC_INTEGER (node), 0x12345678);
 	value = arv_gc_integer_get_value (ARV_GC_INTEGER (node));
 	g_assert_cmpint (value, ==, 0x12345678);
@@ -83,6 +87,13 @@ registers_test (void)
 	node_c = arv_gc_get_node (genicam, "StructEntry_16");
 	g_assert (ARV_IS_GC_NODE (node_c));
 
+	value = arv_gc_register_get_address (ARV_GC_REGISTER (node_a));
+	g_assert_cmpint (value, ==, address);
+	value = arv_gc_register_get_address (ARV_GC_REGISTER (node_b));
+	g_assert_cmpint (value, ==, address);
+	value = arv_gc_register_get_address (ARV_GC_REGISTER (node_c));
+	g_assert_cmpint (value, ==, address);
+
 	value = arv_gc_integer_get_value (ARV_GC_INTEGER (node_a));
 	g_assert_cmpint (value, ==, 0x5678);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]