summaryrefslogtreecommitdiffstats
path: root/o3d/import/cross/memory_stream.cc
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/import/cross/memory_stream.cc')
-rw-r--r--o3d/import/cross/memory_stream.cc401
1 files changed, 401 insertions, 0 deletions
diff --git a/o3d/import/cross/memory_stream.cc b/o3d/import/cross/memory_stream.cc
new file mode 100644
index 0000000..9a4d6c5
--- /dev/null
+++ b/o3d/import/cross/memory_stream.cc
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// MemoryReadStream and MemoryWriteStream are simple stream wrappers around
+// memory buffers.
+
+#include "import/cross/memory_stream.h"
+#include "core/cross/types.h"
+
+#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
+#error "IS_LITTLE_ENDIAN or IS_BIG_ENDIAN must be defined!"
+#endif
+
+namespace o3d {
+
+namespace {
+union Int16Union {
+ uint8 c[2];
+ int16 i;
+};
+
+union UInt16Union {
+ uint8 c[2];
+ uint16 i;
+};
+
+union Int32Union {
+ uint8 c[4];
+ int32 i;
+};
+
+union UInt32Union {
+ uint8 c[4];
+ uint32 i;
+};
+
+union Int32FloatUnion {
+ int32 i;
+ float f;
+};
+
+union UInt32FloatUnion {
+ uint32 i;
+ float f;
+};
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static int16 SwapInt16(const int16 *value) {
+ // endian-swap two bytes
+ uint8 p[2];
+ const char *q = reinterpret_cast<const char*>(value);
+ p[0] = q[1];
+ p[1] = q[0];
+
+ return *reinterpret_cast<int16*>(p);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static uint16 SwapUInt16(const uint16 *value) {
+ // endian-swap two bytes
+ uint8 p[2];
+ const char *q = reinterpret_cast<const char*>(value);
+ p[0] = q[1];
+ p[1] = q[0];
+
+ return *reinterpret_cast<const uint16*>(p);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static int32 SwapInt32(const int32 *value) {
+ // endian-swap four bytes
+ char p[4];
+ const char *q = reinterpret_cast<const char*>(value);
+ p[0] = q[3];
+ p[1] = q[2];
+ p[2] = q[1];
+ p[3] = q[0];
+
+ return *reinterpret_cast<const int32*>(p);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static uint32 SwapUInt32(const uint32 *value) {
+ // endian-swap four bytes
+ char p[4];
+ const char *q = reinterpret_cast<const char*>(value);
+ p[0] = q[3];
+ p[1] = q[2];
+ p[2] = q[1];
+ p[3] = q[0];
+
+ return *reinterpret_cast<const uint32*>(p);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+int16 MemoryReadStream::ReadLittleEndianInt16() {
+ Int16Union u;
+ Read(u.c, 2);
+
+#ifdef IS_BIG_ENDIAN
+ return SwapInt16(&u.i);
+#else
+ return u.i;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+uint16 MemoryReadStream::ReadLittleEndianUInt16() {
+ UInt16Union u;
+ Read(u.c, 2);
+
+#ifdef IS_BIG_ENDIAN
+ return SwapUint16(&u.i);
+#else
+ return u.i;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+int16 MemoryReadStream::ReadBigEndianInt16() {
+ Int16Union u;
+ Read(u.c, 2);
+
+#ifdef IS_LITTLE_ENDIAN
+ return SwapInt16(&u.i);
+#else
+ return u.i;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+uint16 MemoryReadStream::ReadBigEndianUInt16() {
+ UInt16Union u;
+ Read(u.c, 2);
+
+#ifdef IS_LITTLE_ENDIAN
+ return SwapUInt16(&u.i);
+#else
+ return u.i;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+int32 MemoryReadStream::ReadLittleEndianInt32() {
+ Int32Union u;
+ Read(u.c, 4);
+
+#ifdef IS_BIG_ENDIAN
+ return SwapInt32(&u.i);
+#else
+ return u.i;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+uint32 MemoryReadStream::ReadLittleEndianUInt32() {
+ UInt32Union u;
+ Read(u.c, 4);
+
+#ifdef IS_BIG_ENDIAN
+ return SwapUInt32(&u.i);
+#else
+ return u.i;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+int32 MemoryReadStream::ReadBigEndianInt32() {
+ Int32Union u;
+ Read(u.c, 4);
+
+#ifdef IS_LITTLE_ENDIAN
+ return SwapInt32(&u.i);
+#else
+ return u.i;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+uint32 MemoryReadStream::ReadBigEndianUInt32() {
+ UInt32Union u;
+ Read(u.c, 4);
+
+#ifdef IS_LITTLE_ENDIAN
+ return SwapUInt32(&u.i);
+#else
+ return u.i;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+float MemoryReadStream::ReadLittleEndianFloat32() {
+ // Read in as int32 then interpret as float32
+ Int32FloatUnion u;
+ u.i = ReadLittleEndianInt32();
+ return u.f;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+float MemoryReadStream::ReadBigEndianFloat32() {
+ // Read in as int32 then interpret as float32
+ Int32FloatUnion u;
+ u.i = ReadBigEndianInt32();
+ return u.f;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteLittleEndianInt16(int16 i) {
+ Int16Union u;
+
+#ifdef IS_BIG_ENDIAN
+ u.i = SwapInt16(&i);
+#else
+ u.i = i;
+#endif
+
+ Write(u.c, 2);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteLittleEndianUInt16(uint16 i) {
+ UInt16Union u;
+
+#ifdef IS_BIG_ENDIAN
+ u.i = SwapUInt16(&i);
+#else
+ u.i = i;
+#endif
+
+ Write(u.c, 2);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteBigEndianInt16(int16 i) {
+ Int16Union u;
+
+#ifdef IS_LITTLE_ENDIAN
+ u.i = SwapInt16(&i);
+#else
+ u.i = i;
+#endif
+
+ Write(u.c, 2);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteBigEndianUInt16(uint16 i) {
+ UInt16Union u;
+
+#ifdef IS_LITTLE_ENDIAN
+ u.i = SwapUInt16(&i);
+#else
+ u.i = i;
+#endif
+
+ Write(u.c, 2);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteLittleEndianInt32(int32 i) {
+ Int32Union u;
+
+#ifdef IS_BIG_ENDIAN
+ u.i = SwapInt32(&i);
+#else
+ u.i = i;
+#endif
+
+ Write(u.c, 4);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteLittleEndianUInt32(uint32 i) {
+ UInt32Union u;
+
+#ifdef IS_BIG_ENDIAN
+ u.i = SwapUInt32(&i);
+#else
+ u.i = i;
+#endif
+
+ Write(u.c, 4);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteBigEndianInt32(int32 i) {
+ Int32Union u;
+
+#ifdef IS_LITTLE_ENDIAN
+ u.i = SwapInt32(&i);
+#else
+ u.i = i;
+#endif
+
+ Write(u.c, 4);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteBigEndianUInt32(uint32 i) {
+ UInt32Union u;
+
+#ifdef IS_LITTLE_ENDIAN
+ u.i = SwapUInt32(&i);
+#else
+ u.i = i;
+#endif
+
+ Write(u.c, 4);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteLittleEndianFloat32(float f) {
+ // Interpret byte-pattern of f as int32 and write out
+ Int32FloatUnion u;
+ u.f = f;
+ WriteLittleEndianInt32(u.i);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void MemoryWriteStream::WriteBigEndianFloat32(float f) {
+ // Interpret byte-pattern of f as int32 and write out
+ Int32FloatUnion u;
+ u.f = f;
+ WriteBigEndianInt32(u.i);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// A couple of useful utility functions
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Returns the bytes pointed to by |value| as little-endian 16
+int16 MemoryReadStream::GetLittleEndianInt16(const int16 *value) {
+#ifdef IS_BIG_ENDIAN
+ return SwapInt16(value);
+#else
+ return *value;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Returns the bytes pointed to by |value| as little-endian 16
+uint16 MemoryReadStream::GetLittleEndianUInt16(const uint16 *value) {
+#ifdef IS_BIG_ENDIAN
+ return SwapUInt16(value);
+#else
+ return *value;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Returns the bytes pointed to by |value| as little-endian 32
+int32 MemoryReadStream::GetLittleEndianInt32(const int32 *value) {
+#ifdef IS_BIG_ENDIAN
+ return SwapInt32(value);
+#else
+ return *value;
+#endif
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Returns the bytes pointed to by |value| as little-endian 32
+uint32 MemoryReadStream::GetLittleEndianUInt32(const uint32 *value) {
+#ifdef IS_BIG_ENDIAN
+ return SwapUint32(value);
+#else
+ return *value;
+#endif
+}
+
+} // namespace o3d