[aravis] zip: fix issue on platform not supporting unaligned memory access.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [aravis] zip: fix issue on platform not supporting unaligned memory access.
- Date: Sun, 15 Jul 2012 16:01:10 +0000 (UTC)
commit cb6dd5193295dd439f76041733df555f4c940501
Author: Nial Peters <nonbiostudent hotmail com>
Date: Sun Jul 15 18:00:14 2012 +0200
zip: fix issue on platform not supporting unaligned memory access.
docs/reference/aravis/aravis-sections.txt | 4 ++
src/arvzip.c | 35 +++++++--------
src/arvzip.h | 68 +++++++++++++++++++++++++++++
tests/.gitignore | 1 +
tests/Makefile.am | 5 ++-
tests/misc.c | 56 +++++++++++++++++++++++
6 files changed, 149 insertions(+), 20 deletions(-)
---
diff --git a/docs/reference/aravis/aravis-sections.txt b/docs/reference/aravis/aravis-sections.txt
index caeeb3b..54e67ec 100644
--- a/docs/reference/aravis/aravis-sections.txt
+++ b/docs/reference/aravis/aravis-sections.txt
@@ -1443,6 +1443,10 @@ arv_zip_get_file
arv_zip_get_file_list
arv_zip_file_get_name
arv_zip_file_get_uncompressed_size
+ARV_GUINT16_FROM_LE_PTR
+ARV_GUINT32_FROM_LE_PTR
+arv_guint16_from_unaligned_le_ptr
+arv_guint32_from_unaligned_le_ptr
<SUBSECTION Private>
ArvZipFile
</SECTION>
diff --git a/src/arvzip.c b/src/arvzip.c
index 39e7267..891b1a0 100644
--- a/src/arvzip.c
+++ b/src/arvzip.c
@@ -35,9 +35,6 @@
#include <string.h>
#include <zlib.h>
-#define GUINT32_FROM_LE_PTR(ptr) GUINT32_FROM_LE(*((guint32 *)(ptr)))
-#define GUINT16_FROM_LE_PTR(ptr) GUINT16_FROM_LE(*((guint16 *)(ptr)))
-
struct _ArvZipFile {
char *name;
@@ -87,27 +84,27 @@ arv_zip_build_file_list (ArvZip *zip)
for (i = 0; i < zip->n_files; i++) {
ptr = zip->buffer + zip->header_size + offset;
- if (GUINT32_FROM_LE_PTR (ptr) != 0x02014b50) {
+ if (ARV_GUINT32_FROM_LE_PTR (ptr) != 0x02014b50) {
arv_debug_misc ("[Zip::build_file_list] Magic number of central directory not found (0x02014b50)");
arv_debug_misc ("[Zip::build_file_list] Expected at 0x%08x - found 0x%08x instead",
- zip->header_size + offset, GUINT32_FROM_LE_PTR (ptr));
+ zip->header_size + offset, ARV_GUINT32_FROM_LE_PTR (ptr));
return;
}
zip_file = g_new0 (ArvZipFile, 1);
- zip_file->compressed_size = GUINT32_FROM_LE_PTR (ptr + 20);
- zip_file->uncompressed_size = GUINT32_FROM_LE_PTR (ptr + 24);
- zip_file->offset = GUINT32_FROM_LE_PTR (ptr + 42);
- zip_file->name = g_strndup ((char *) (ptr + 46), GUINT16_FROM_LE_PTR (ptr + 28));
+ zip_file->compressed_size = ARV_GUINT32_FROM_LE_PTR (ptr + 20);
+ zip_file->uncompressed_size = ARV_GUINT32_FROM_LE_PTR (ptr + 24);
+ zip_file->offset = ARV_GUINT32_FROM_LE_PTR (ptr + 42);
+ zip_file->name = g_strndup ((char *) (ptr + 46), ARV_GUINT16_FROM_LE_PTR (ptr + 28));
arv_log_misc ("[Zip::list_files] %s", zip_file->name);
zip->files = g_slist_prepend (zip->files, zip_file);
offset += 0x2e +
- GUINT16_FROM_LE_PTR (ptr + 28) + /* filename size */
- GUINT16_FROM_LE_PTR (ptr + 30) + /* extra field */
- GUINT16_FROM_LE_PTR (ptr + 32); /* file comment */
+ ARV_GUINT16_FROM_LE_PTR (ptr + 28) + /* filename size */
+ ARV_GUINT16_FROM_LE_PTR (ptr + 30) + /* extra field */
+ ARV_GUINT16_FROM_LE_PTR (ptr + 32); /* file comment */
}
}
@@ -133,14 +130,14 @@ arv_zip_get_file_data (ArvZip *zip, ArvZipFile *zip_file)
ptr = zip->buffer + zip_file->offset + zip->header_size;
- if (GUINT32_FROM_LE_PTR (ptr) != 0x04034b50) {
+ if (ARV_GUINT32_FROM_LE_PTR (ptr) != 0x04034b50) {
arv_debug_misc ("[Zip::get_file_data] Magic number for file header not found (0x04034b50)");
return -1;
}
return zip_file->offset + zip->header_size +
- GUINT16_FROM_LE_PTR (ptr + 26) +
- GUINT16_FROM_LE_PTR (ptr + 28) + 30;
+ ARV_GUINT16_FROM_LE_PTR (ptr + 26) +
+ ARV_GUINT16_FROM_LE_PTR (ptr + 28) + 30;
}
/**
@@ -182,15 +179,15 @@ arv_zip_new (const void *buffer, size_t size)
}
ptr = zip->buffer + zip->directory_position;
- zip->n_files = GUINT16_FROM_LE_PTR (ptr + 10);
- if (GUINT16_FROM_LE_PTR (ptr + 8) != zip->n_files) {
+ zip->n_files = ARV_GUINT16_FROM_LE_PTR (ptr + 10);
+ if (ARV_GUINT16_FROM_LE_PTR (ptr + 8) != zip->n_files) {
arv_debug_misc ("[Zip::new] Mismatch in number of files");
zip->n_files = 0;
return zip;
}
- zip->directory_size = GUINT32_FROM_LE_PTR (ptr + 12);
- zip->directory_offset = GUINT32_FROM_LE_PTR (ptr + 16);
+ zip->directory_size = ARV_GUINT32_FROM_LE_PTR (ptr + 12);
+ zip->directory_offset = ARV_GUINT32_FROM_LE_PTR (ptr + 16);
zip->header_size = zip->directory_position - (zip->directory_offset + zip->directory_size);
arv_log_misc ("[Zip::new] number of files = %d", zip->n_files);
diff --git a/src/arvzip.h b/src/arvzip.h
index 2ea5c4d..bcb9e07 100644
--- a/src/arvzip.h
+++ b/src/arvzip.h
@@ -35,6 +35,74 @@ const GSList * arv_zip_get_file_list (ArvZip *zip);
const char * arv_zip_file_get_name (ArvZipFile *zip_file);
size_t arv_zip_file_get_uncompressed_size (ArvZipFile *zip_file);
+#define ARV_GUINT32_FROM_LE_PTR(ptr) arv_guint32_from_unaligned_le_ptr (ptr)
+#define ARV_GUINT16_FROM_LE_PTR(ptr) arv_guint16_from_unaligned_le_ptr (ptr)
+
+/**
+ * arv_guint32_from_unaligned_le_ptr:
+ * @ptr: pointer to a little endian 32 bit usigned integer
+ *
+ * Here's an excerpt of the ARM documentation:
+ *
+ * "Unaligned data access in C and C++ code
+ *
+ * It can be necessary to access unaligned data in memory, for example,
+ * when porting legacy code from a CISC architecture where instructions are
+ * available to directly access unaligned data in memory.
+ *
+ * On ARMv4 and ARMv5 architectures, and on the ARMv6 architecture
+ * depending on how it is configured, care is required when accessing
+ * unaligned data in memory, to avoid unexpected results. For example, when
+ * a conventional pointer is used to read a word in C or C++ source code,
+ * the ARM compiler generates assembly language code that reads the word
+ * using an LDR instruction. This works as expected when the address is a
+ * multiple of four, for example if it lies on a word boundary. However, if
+ * the address is not a multiple of four, the LDR instruction returns a
+ * rotated result rather than performing a true unaligned word load.
+ * Generally, this rotation is not what the programmer expects.
+ *
+ * On ARMv6 and later architectures, unaligned access is fully supported."
+ *
+ * Returns: a guint32 in machine endianess
+ */
+
+static inline guint32
+arv_guint32_from_unaligned_le_ptr (const void *ptr)
+{
+ guint32 val;
+
+ g_return_val_if_fail (ptr != NULL, 0);
+
+ *((char*)(&val)) = *((char*)ptr);
+ *(((char*)(&val))+1) = *(((char*)ptr)+1);
+ *(((char*)(&val))+2) = *(((char*)ptr)+2);
+ *(((char*)(&val))+3) = *(((char*)ptr)+3);
+
+ return GUINT32_FROM_LE (val);
+}
+
+/**
+ * arv_guint16_from_unaligned_le_ptr:
+ * @ptr: pointer to a little endian 16 bit usigned integer
+ *
+ * See @arv_guint32_from_unaligned_le_ptr.
+ *
+ * Returns: a guint16 in machine endianess
+ */
+
+static inline guint16
+arv_guint16_from_unaligned_le_ptr (const void *ptr)
+{
+ guint16 val;
+
+ g_return_val_if_fail (ptr != NULL, 0);
+
+ *((char*)(&val)) = *((char*)ptr);
+ *(((char*)(&val))+1) = *(((char*)ptr)+1);
+
+ return GUINT16_FROM_LE (val);
+}
+
G_END_DECLS
#endif
diff --git a/tests/.gitignore b/tests/.gitignore
index 120d415..21574dd 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,6 +1,7 @@
evaluator
genicam
buffer
+misc
fake
cpp
arv-test
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ca721cb..5d58ee2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -26,7 +26,7 @@ arv_camera_test_LDADD = $(test_progs_ldadd)
arv_heartbeat_test_SOURCES = arvheartbeattest.c
arv_heartbeat_test_LDADD = $(test_progs_ldadd)
-TEST_PROGS += evaluator buffer fake genicam
+TEST_PROGS += evaluator buffer misc fake genicam
if ARAVIS_BUILD_CPP_TEST
TEST_PROGS += cpp
endif
@@ -39,6 +39,9 @@ evaluator_LDADD = $(test_progs_ldadd)
buffer_SOURCES = buffer.c
buffer_LDADD = $(test_progs_ldadd)
+misc_SOURCES = misc.c
+misc_LDADD = $(test_progs_ldadd)
+
fake_SOURCES = fake.c
fake_CFLAGS = -DGENICAM_FILENAME="\"$(top_srcdir)/src/arv-fake-camera.xml\""
fake_LDADD = $(test_progs_ldadd)
diff --git a/tests/misc.c b/tests/misc.c
new file mode 100644
index 0000000..6ec846d
--- /dev/null
+++ b/tests/misc.c
@@ -0,0 +1,56 @@
+#include <glib.h>
+#include <arv.h>
+#include <string.h>
+
+static void
+unaligned_from_le_ptr_test (void)
+{
+ char test[]= {'\x11', '\x22', '\x33', '\x44','\x55', '\x66', '\x77', '\x88', '\x99', '\xaa', '\xbb', '\xcc'};
+ guint32 v_uint32;
+ guint16 v_uint16;
+
+ v_uint32 = ARV_GUINT32_FROM_LE_PTR (&test[0]);
+ g_assert_cmpuint (v_uint32, ==, 0x44332211);
+
+ v_uint32 = ARV_GUINT32_FROM_LE_PTR (&test[1]);
+ g_assert_cmpuint (v_uint32, ==, 0x55443322);
+
+ v_uint32 = ARV_GUINT32_FROM_LE_PTR (&test[2]);
+ g_assert_cmpuint (v_uint32, ==, 0x66554433);
+
+ v_uint32 = ARV_GUINT32_FROM_LE_PTR (&test[3]);
+ g_assert_cmpuint (v_uint32, ==, 0x77665544);
+
+ v_uint16 = ARV_GUINT16_FROM_LE_PTR (&test[0]);
+ g_assert_cmpuint (v_uint16, ==, 0x2211);
+
+ v_uint16 = ARV_GUINT16_FROM_LE_PTR (&test[1]);
+ g_assert_cmpuint (v_uint16, ==, 0x3322);
+
+ v_uint16 = ARV_GUINT16_FROM_LE_PTR (&test[2]);
+ g_assert_cmpuint (v_uint16, ==, 0x4433);
+
+ v_uint16 = ARV_GUINT16_FROM_LE_PTR (&test[3]);
+ g_assert_cmpuint (v_uint16, ==, 0x5544);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int result;
+ int i;
+
+ g_test_init (&argc, &argv, NULL);
+
+ g_type_init ();
+
+ g_test_add_func ("/buffer/unaligned-from-le", unaligned_from_le_ptr_test);
+
+ result = g_test_run();
+
+ arv_shutdown ();
+
+ return result;
+}
+
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]