| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /* |
| * Modifications Copyright 2017 Google Inc. All Rights Reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef NB_BIT_CAST_H_ |
| #define NB_BIT_CAST_H_ |
| |
| #include "starboard/configuration.h" |
| #include "starboard/memory.h" |
| |
| namespace nb { |
| |
| // bit_cast<Dest,Source> is a template function that implements the |
| // equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in |
| // very low-level functions like hashing pod data, where the pod data is |
| // reinterpreted to a const char*. |
| // |
| // The classical address-casting method is: |
| // |
| // // WRONG |
| // float f = 3.14159265358979; // WRONG |
| // int i = * reinterpret_cast<int*>(&f); // WRONG |
| // |
| // The address-casting method actually produces undefined behavior |
| // according to ISO C++ specification section 3.10 -15 -. Roughly, this |
| // section says: if an object in memory has one type, and a program |
| // accesses it with a different type, then the result is undefined |
| // behavior for most values of "different type". |
| // |
| // This is true for any cast syntax, either *(int*)&f or |
| // *reinterpret_cast<int*>(&f). And it is particularly true for |
| // conversions between integral lvalues and floating-point lvalues. |
| // |
| // The purpose of 3.10 -15- is to allow optimizing compilers to assume |
| // that expressions with different types refer to different memory. gcc |
| // 4.0.1 has an optimizer that takes advantage of this. So a |
| // non-conforming program quietly produces wildly incorrect output. |
| // |
| // The problem is not the use of reinterpret_cast. The problem is type |
| // punning: holding an object in memory of one type and reading its bits |
| // back using a different type. |
| // |
| // The C++ standard is more subtle and complex than this, but that |
| // is the basic idea. |
| // |
| // Anyways ... |
| // |
| // bit_cast<> calls memcpy() which is blessed by the standard, |
| // especially by the example in section 3.9 . Also, of course, |
| // bit_cast<> wraps up the nasty logic in one place. |
| template <class Dest, class Source> |
| inline Dest bit_cast(const Source& source) { |
| SB_COMPILE_ASSERT(sizeof(Dest) == sizeof(source), |
| Source_and_destination_types_should_have_equal_sizes); |
| Dest dest; |
| memcpy(&dest, &source, sizeof(dest)); |
| return dest; |
| } |
| |
| } // namespace nb |
| |
| #endif // NB_CONCURRENT_MAP_H_ |