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 134659 57c346bd9ec3e19b545f17848fa3c4f6d28cef37
parent 134658 3f3ab64fea609645aafa1dce55ba2a6c842a4d93
child 134660 e4473d563e0f290a838efcd2a21c348774ec558b
push id1728
push userryanvm@gmail.com
push dateWed, 12 Jun 2013 01:05:13 +0000
treeherderfx-team@cc35f8929768 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs798179
milestone24.0a1
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();
 }