Bug 798179 - Implement To BitwiseCast<To>(From), abstracting the treatment of a value's bits as being of another type. r=froydnj
authorJeff Walden <jwalden@mit.edu>
Thu, 06 Jun 2013 18:47:51 -0700
changeset 147013 57c346bd9ec3e19b545f17848fa3c4f6d28cef37
parent 147012 3f3ab64fea609645aafa1dce55ba2a6c842a4d93
child 147014 e4473d563e0f290a838efcd2a21c348774ec558b
push id368
push userbbajaj@mozilla.com
push dateMon, 09 Sep 2013 22:57:58 +0000
treeherdermozilla-release@5a4f47ae1217 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs798179
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 798179 - Implement To BitwiseCast<To>(From), abstracting the treatment of a value's bits as being of another type. r=froydnj
mfbt/Casting.h
mfbt/tests/TestCasting.cpp
--- a/mfbt/Casting.h
+++ b/mfbt/Casting.h
@@ -10,16 +10,37 @@
 
 #include "mozilla/Assertions.h"
 #include "mozilla/TypeTraits.h"
 
 #include <limits.h>
 
 namespace mozilla {
 
+/**
+ * Return a value of type |To|, containing the underlying bit pattern of |from|.
+ *
+ * |To| and |From| must be types of the same size; be careful of cross-platform
+ * size differences, or this might fail to compile on some but not all
+ * platforms.
+ */
+template<typename To, typename From>
+inline To
+BitwiseCast(const From from)
+{
+  MOZ_STATIC_ASSERT(sizeof(From) == sizeof(To),
+                    "To and From must have the same size");
+  union {
+    From from;
+    To to;
+  } u;
+  u.from = from;
+  return u.to;
+}
+
 namespace detail {
 
 enum ToSignedness { ToIsSigned, ToIsUnsigned };
 enum FromSignedness { FromIsSigned, FromIsUnsigned };
 
 template<typename From,
          typename To,
          FromSignedness = IsSigned<From>::value ? FromIsSigned : FromIsUnsigned,
--- a/mfbt/tests/TestCasting.cpp
+++ b/mfbt/tests/TestCasting.cpp
@@ -1,18 +1,43 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Casting.h"
 #include "mozilla/StandardInteger.h"
 
+using mozilla::BitwiseCast;
 using mozilla::detail::IsInBounds;
 
+template<typename Uint, typename Ulong, bool = (sizeof(Uint) == sizeof(Ulong))>
+struct UintUlongBitwiseCast;
+
+template<typename Uint, typename Ulong>
+struct UintUlongBitwiseCast<Uint, Ulong, true>
+{
+    static void test() {
+      MOZ_ASSERT(BitwiseCast<Ulong>(Uint(8675309)) == Ulong(8675309));
+    }
+};
+
+template<typename Uint, typename Ulong>
+struct UintUlongBitwiseCast<Uint, Ulong, false>
+{
+    static void test() { }
+};
+
+static void
+TestBitwiseCast()
+{
+  MOZ_ASSERT(BitwiseCast<int>(int(8675309)) == int(8675309));
+  UintUlongBitwiseCast<unsigned int, unsigned long>::test();
+}
+
 static void
 TestSameSize()
 {
   MOZ_ASSERT((IsInBounds<int16_t, int16_t>(int16_t(0))));
   MOZ_ASSERT((IsInBounds<int16_t, int16_t>(int16_t(INT16_MIN))));
   MOZ_ASSERT((IsInBounds<int16_t, int16_t>(int16_t(INT16_MAX))));
   MOZ_ASSERT((IsInBounds<uint16_t, uint16_t>(uint16_t(UINT16_MAX))));
   MOZ_ASSERT((IsInBounds<uint16_t, int16_t>(uint16_t(0))));
@@ -69,12 +94,14 @@ TestToSmallerSize()
   MOZ_ASSERT((IsInBounds<int64_t, uint32_t>(int64_t(UINT32_MAX) - 1)));
   MOZ_ASSERT((IsInBounds<int64_t, uint32_t>(int64_t(UINT32_MAX))));
   MOZ_ASSERT((!IsInBounds<int64_t, uint32_t>(int64_t(UINT32_MAX) + 1)));
 }
 
 int
 main()
 {
+  TestBitwiseCast();
+
   TestSameSize();
   TestToBiggerSize();
   TestToSmallerSize();
 }