mfbt/Endian.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* Functions for reading and writing integers in various endiannesses. */
     9 /*
    10  * The classes LittleEndian and BigEndian expose static methods for
    11  * reading and writing 16-, 32-, and 64-bit signed and unsigned integers
    12  * in their respective endianness.  The naming scheme is:
    13  *
    14  * {Little,Big}Endian::{read,write}{Uint,Int}<bitsize>
    15  *
    16  * For instance, LittleEndian::readInt32 will read a 32-bit signed
    17  * integer from memory in little endian format.  Similarly,
    18  * BigEndian::writeUint16 will write a 16-bit unsigned integer to memory
    19  * in big-endian format.
    20  *
    21  * The class NativeEndian exposes methods for conversion of existing
    22  * data to and from the native endianness.  These methods are intended
    23  * for cases where data needs to be transferred, serialized, etc.
    24  * swap{To,From}{Little,Big}Endian byteswap a single value if necessary.
    25  * Bulk conversion functions are also provided which optimize the
    26  * no-conversion-needed case:
    27  *
    28  * - copyAndSwap{To,From}{Little,Big}Endian;
    29  * - swap{To,From}{Little,Big}EndianInPlace.
    30  *
    31  * The *From* variants are intended to be used for reading data and the
    32  * *To* variants for writing data.
    33  *
    34  * Methods on NativeEndian work with integer data of any type.
    35  * Floating-point data is not supported.
    36  *
    37  * For clarity in networking code, "Network" may be used as a synonym
    38  * for "Big" in any of the above methods or class names.
    39  *
    40  * As an example, reading a file format header whose fields are stored
    41  * in big-endian format might look like:
    42  *
    43  * class ExampleHeader
    44  * {
    45  *   private:
    46  *     uint32_t magic;
    47  *     uint32_t length;
    48  *     uint32_t totalRecords;
    49  *     uint64_t checksum;
    50  *
    51  *   public:
    52  *     ExampleHeader(const void* data) {
    53  *       const uint8_t* ptr = static_cast<const uint8_t*>(data);
    54  *       magic = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
    55  *       length = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
    56  *       totalRecords = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
    57  *       checksum = BigEndian::readUint64(ptr);
    58  *     }
    59  *     ...
    60  * };
    61  */
    63 #ifndef mozilla_Endian_h
    64 #define mozilla_Endian_h
    66 #include "mozilla/Assertions.h"
    67 #include "mozilla/Attributes.h"
    68 #include "mozilla/Compiler.h"
    69 #include "mozilla/DebugOnly.h"
    70 #include "mozilla/TypeTraits.h"
    72 #include <stdint.h>
    73 #include <string.h>
    75 #if defined(_MSC_VER) && _MSC_VER >= 1300
    76 #  include <stdlib.h>
    77 #  pragma intrinsic(_byteswap_ushort)
    78 #  pragma intrinsic(_byteswap_ulong)
    79 #  pragma intrinsic(_byteswap_uint64)
    80 #endif
    82 #if defined(_WIN64)
    83 #  if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
    84 #    define MOZ_LITTLE_ENDIAN 1
    85 #  else
    86 #    error "CPU type is unknown"
    87 #  endif
    88 #elif defined(_WIN32)
    89 #  if defined(_M_IX86)
    90 #    define MOZ_LITTLE_ENDIAN 1
    91 #  else
    92 #    error "CPU type is unknown"
    93 #  endif
    94 #elif defined(__APPLE__) || defined(__powerpc__) || defined(__ppc__)
    95 #  if __LITTLE_ENDIAN__
    96 #    define MOZ_LITTLE_ENDIAN 1
    97 #  elif __BIG_ENDIAN__
    98 #    define MOZ_BIG_ENDIAN 1
    99 #  endif
   100 #elif defined(__GNUC__) && \
   101       defined(__BYTE_ORDER__) && \
   102       defined(__ORDER_LITTLE_ENDIAN__) && \
   103       defined(__ORDER_BIG_ENDIAN__)
   104    /*
   105     * Some versions of GCC provide architecture-independent macros for
   106     * this.  Yes, there are more than two values for __BYTE_ORDER__.
   107     */
   108 #  if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
   109 #    define MOZ_LITTLE_ENDIAN 1
   110 #  elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
   111 #    define MOZ_BIG_ENDIAN 1
   112 #  else
   113 #    error "Can't handle mixed-endian architectures"
   114 #  endif
   115 /*
   116  * We can't include useful headers like <endian.h> or <sys/isa_defs.h>
   117  * here because they're not present on all platforms.  Instead we have
   118  * this big conditional that ideally will catch all the interesting
   119  * cases.
   120  */
   121 #elif defined(__sparc) || defined(__sparc__) || \
   122       defined(_POWER) || defined(__hppa) || \
   123       defined(_MIPSEB) || defined(__ARMEB__) || \
   124       defined(__s390__) || defined(__AARCH64EB__) || \
   125       (defined(__sh__) && defined(__LITTLE_ENDIAN__)) || \
   126       (defined(__ia64) && defined(__BIG_ENDIAN__))
   127 #  define MOZ_BIG_ENDIAN 1
   128 #elif defined(__i386) || defined(__i386__) || \
   129       defined(__x86_64) || defined(__x86_64__) || \
   130       defined(_MIPSEL) || defined(__ARMEL__) || \
   131       defined(__alpha__) || defined(__AARCH64EL__) || \
   132       (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
   133       (defined(__ia64) && !defined(__BIG_ENDIAN__))
   134 #  define MOZ_LITTLE_ENDIAN 1
   135 #endif
   137 #if MOZ_BIG_ENDIAN
   138 #  define MOZ_LITTLE_ENDIAN 0
   139 #elif MOZ_LITTLE_ENDIAN
   140 #  define MOZ_BIG_ENDIAN 0
   141 #else
   142 #  error "Cannot determine endianness"
   143 #endif
   145 #if defined(__clang__)
   146 #  if __has_builtin(__builtin_bswap16)
   147 #    define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
   148 #  endif
   149 #elif defined(__GNUC__)
   150 #  if MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
   151 #    define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
   152 #  endif
   153 #elif defined(_MSC_VER)
   154 #    define MOZ_HAVE_BUILTIN_BYTESWAP16 _byteswap_ushort
   155 #endif
   157 namespace mozilla {
   159 namespace detail {
   161 /*
   162  * We need wrappers here because free functions with default template
   163  * arguments and/or partial specialization of function templates are not
   164  * supported by all the compilers we use.
   165  */
   166 template<typename T, size_t Size = sizeof(T)>
   167 struct Swapper;
   169 template<typename T>
   170 struct Swapper<T, 2>
   171 {
   172   static T swap(T value)
   173   {
   174 #if defined(MOZ_HAVE_BUILTIN_BYTESWAP16)
   175     return MOZ_HAVE_BUILTIN_BYTESWAP16(value);
   176 #else
   177     return T(((value & 0x00ff) << 8) | ((value & 0xff00) >> 8));
   178 #endif
   179   }
   180 };
   182 template<typename T>
   183 struct Swapper<T, 4>
   184 {
   185   static T swap(T value)
   186   {
   187 #if defined(__clang__) || defined(__GNUC__)
   188     return T(__builtin_bswap32(value));
   189 #elif defined(_MSC_VER)
   190     return T(_byteswap_ulong(value));
   191 #else
   192     return T(((value & 0x000000ffU) << 24) |
   193              ((value & 0x0000ff00U) << 8) |
   194              ((value & 0x00ff0000U) >> 8) |
   195              ((value & 0xff000000U) >> 24));
   196 #endif
   197   }
   198 };
   200 template<typename T>
   201 struct Swapper<T, 8>
   202 {
   203   static inline T swap(T value)
   204   {
   205 #if defined(__clang__) || defined(__GNUC__)
   206     return T(__builtin_bswap64(value));
   207 #elif defined(_MSC_VER)
   208     return T(_byteswap_uint64(value));
   209 #else
   210     return T(((value & 0x00000000000000ffULL) << 56) |
   211              ((value & 0x000000000000ff00ULL) << 40) |
   212              ((value & 0x0000000000ff0000ULL) << 24) |
   213              ((value & 0x00000000ff000000ULL) << 8) |
   214              ((value & 0x000000ff00000000ULL) >> 8) |
   215              ((value & 0x0000ff0000000000ULL) >> 24) |
   216              ((value & 0x00ff000000000000ULL) >> 40) |
   217              ((value & 0xff00000000000000ULL) >> 56));
   218 #endif
   219   }
   220 };
   222 enum Endianness { Little, Big };
   224 #if MOZ_BIG_ENDIAN
   225 #  define MOZ_NATIVE_ENDIANNESS detail::Big
   226 #else
   227 #  define MOZ_NATIVE_ENDIANNESS detail::Little
   228 #endif
   230 class EndianUtils
   231 {
   232     /**
   233      * Assert that the memory regions [dest, dest+count) and [src, src+count]
   234      * do not overlap.  count is given in bytes.
   235      */
   236     static void assertNoOverlap(const void* dest, const void* src, size_t count)
   237     {
   238       DebugOnly<const uint8_t*> byteDestPtr = static_cast<const uint8_t*>(dest);
   239       DebugOnly<const uint8_t*> byteSrcPtr = static_cast<const uint8_t*>(src);
   240       MOZ_ASSERT((byteDestPtr <= byteSrcPtr &&
   241                   byteDestPtr + count <= byteSrcPtr) ||
   242                  (byteSrcPtr <= byteDestPtr &&
   243                   byteSrcPtr + count <= byteDestPtr));
   244     }
   246     template<typename T>
   247     static void assertAligned(T* ptr)
   248     {
   249       MOZ_ASSERT((uintptr_t(ptr) % sizeof(T)) == 0, "Unaligned pointer!");
   250     }
   252   protected:
   253     /**
   254      * Return |value| converted from SourceEndian encoding to DestEndian
   255      * encoding.
   256      */
   257     template<Endianness SourceEndian, Endianness DestEndian, typename T>
   258     static inline T maybeSwap(T value)
   259     {
   260       if (SourceEndian == DestEndian)
   261         return value;
   263       return Swapper<T>::swap(value);
   264     }
   266     /**
   267      * Convert |count| elements at |ptr| from SourceEndian encoding to
   268      * DestEndian encoding.
   269      */
   270     template<Endianness SourceEndian, Endianness DestEndian, typename T>
   271     static inline void maybeSwapInPlace(T* ptr, size_t count)
   272     {
   273       assertAligned(ptr);
   275       if (SourceEndian == DestEndian)
   276         return;
   278       for (size_t i = 0; i < count; i++)
   279         ptr[i] = Swapper<T>::swap(ptr[i]);
   280     }
   282     /**
   283      * Write |count| elements to the unaligned address |dest| in DestEndian
   284      * format, using elements found at |src| in SourceEndian format.
   285      */
   286     template<Endianness SourceEndian, Endianness DestEndian, typename T>
   287     static void copyAndSwapTo(void* dest, const T* src, size_t count)
   288     {
   289       assertNoOverlap(dest, src, count * sizeof(T));
   290       assertAligned(src);
   292       if (SourceEndian == DestEndian) {
   293         memcpy(dest, src, count * sizeof(T));
   294         return;
   295       }
   297       uint8_t* byteDestPtr = static_cast<uint8_t*>(dest);
   298       for (size_t i = 0; i < count; ++i) {
   299         union {
   300           T val;
   301           uint8_t buffer[sizeof(T)];
   302         } u;
   303         u.val = maybeSwap<SourceEndian, DestEndian>(src[i]);
   304         memcpy(byteDestPtr, u.buffer, sizeof(T));
   305         byteDestPtr += sizeof(T);
   306       }
   307     }
   309     /**
   310      * Write |count| elements to |dest| in DestEndian format, using elements
   311      * found at the unaligned address |src| in SourceEndian format.
   312      */
   313     template<Endianness SourceEndian, Endianness DestEndian, typename T>
   314     static void copyAndSwapFrom(T* dest, const void* src, size_t count)
   315     {
   316       assertNoOverlap(dest, src, count * sizeof(T));
   317       assertAligned(dest);
   319       if (SourceEndian == DestEndian) {
   320         memcpy(dest, src, count * sizeof(T));
   321         return;
   322       }
   324       const uint8_t* byteSrcPtr = static_cast<const uint8_t*>(src);
   325       for (size_t i = 0; i < count; ++i) {
   326         union {
   327           T val;
   328           uint8_t buffer[sizeof(T)];
   329         } u;
   330         memcpy(u.buffer, byteSrcPtr, sizeof(T));
   331         dest[i] = maybeSwap<SourceEndian, DestEndian>(u.val);
   332         byteSrcPtr += sizeof(T);
   333       }
   334     }
   335 };
   337 template<Endianness ThisEndian>
   338 class Endian : private EndianUtils
   339 {
   340   protected:
   341     /** Read a uint16_t in ThisEndian endianness from |p| and return it. */
   342     static MOZ_WARN_UNUSED_RESULT uint16_t readUint16(const void* p) {
   343       return read<uint16_t>(p);
   344     }
   346     /** Read a uint32_t in ThisEndian endianness from |p| and return it. */
   347     static MOZ_WARN_UNUSED_RESULT uint32_t readUint32(const void* p) {
   348       return read<uint32_t>(p);
   349     }
   351     /** Read a uint64_t in ThisEndian endianness from |p| and return it. */
   352     static MOZ_WARN_UNUSED_RESULT uint64_t readUint64(const void* p) {
   353       return read<uint64_t>(p);
   354     }
   356     /** Read an int16_t in ThisEndian endianness from |p| and return it. */
   357     static MOZ_WARN_UNUSED_RESULT int16_t readInt16(const void* p) {
   358       return read<int16_t>(p);
   359     }
   361     /** Read an int32_t in ThisEndian endianness from |p| and return it. */
   362     static MOZ_WARN_UNUSED_RESULT int32_t readInt32(const void* p) {
   363       return read<uint32_t>(p);
   364     }
   366     /** Read an int64_t in ThisEndian endianness from |p| and return it. */
   367     static MOZ_WARN_UNUSED_RESULT int64_t readInt64(const void* p) {
   368       return read<int64_t>(p);
   369     }
   371     /** Write |val| to |p| using ThisEndian endianness. */
   372     static void writeUint16(void* p, uint16_t val) {
   373       write(p, val);
   374     }
   375     /** Write |val| to |p| using ThisEndian endianness. */
   376     static void writeUint32(void* p, uint32_t val) {
   377       write(p, val);
   378     }
   379     /** Write |val| to |p| using ThisEndian endianness. */
   380     static void writeUint64(void* p, uint64_t val) {
   381       write(p, val);
   382     }
   384     /** Write |val| to |p| using ThisEndian endianness. */
   385     static void writeInt16(void* p, int16_t val) {
   386       write(p, val);
   387     }
   388     /** Write |val| to |p| using ThisEndian endianness. */
   389     static void writeInt32(void* p, int32_t val) {
   390       write(p, val);
   391     }
   392     /** Write |val| to |p| using ThisEndian endianness. */
   393     static void writeInt64(void* p, int64_t val) {
   394       write(p, val);
   395     }
   397     /*
   398      * Converts a value of type T to little-endian format.
   399      *
   400      * This function is intended for cases where you have data in your
   401      * native-endian format and you need it to appear in little-endian
   402      * format for transmission.
   403      */
   404     template<typename T>
   405     MOZ_WARN_UNUSED_RESULT static T swapToLittleEndian(T value) {
   406       return maybeSwap<ThisEndian, Little>(value);
   407     }
   408     /*
   409      * Copies count values of type T starting at src to dest, converting
   410      * them to little-endian format if ThisEndian is Big.
   411      * As with memcpy, dest and src must not overlap.
   412      */
   413     template<typename T>
   414     static void copyAndSwapToLittleEndian(void* dest, const T* src,
   415                                           size_t count) {
   416       copyAndSwapTo<ThisEndian, Little>(dest, src, count);
   417     }
   418     /*
   419      * Likewise, but converts values in place.
   420      */
   421     template<typename T>
   422     static void swapToLittleEndianInPlace(T* p, size_t count) {
   423       maybeSwapInPlace<ThisEndian, Little>(p, count);
   424     }
   426     /*
   427      * Converts a value of type T to big-endian format.
   428      */
   429     template<typename T>
   430     MOZ_WARN_UNUSED_RESULT static T swapToBigEndian(T value) {
   431       return maybeSwap<ThisEndian, Big>(value);
   432     }
   433     /*
   434      * Copies count values of type T starting at src to dest, converting
   435      * them to big-endian format if ThisEndian is Little.
   436      * As with memcpy, dest and src must not overlap.
   437      */
   438     template<typename T>
   439     static void copyAndSwapToBigEndian(void* dest, const T* src, size_t count) {
   440       copyAndSwapTo<ThisEndian, Big>(dest, src, count);
   441     }
   442     /*
   443      * Likewise, but converts values in place.
   444      */
   445     template<typename T>
   446     static void swapToBigEndianInPlace(T* p, size_t count) {
   447       maybeSwapInPlace<ThisEndian, Big>(p, count);
   448     }
   450     /*
   451      * Synonyms for the big-endian functions, for better readability
   452      * in network code.
   453      */
   454     template<typename T>
   455     MOZ_WARN_UNUSED_RESULT static T swapToNetworkOrder(T value) {
   456       return swapToBigEndian(value);
   457     }
   458     template<typename T>
   459     static void
   460     copyAndSwapToNetworkOrder(void* dest, const T* src, size_t count) {
   461       copyAndSwapToBigEndian(dest, src, count);
   462     }
   463     template<typename T>
   464     static void
   465     swapToNetworkOrderInPlace(T* p, size_t count) {
   466       swapToBigEndianInPlace(p, count);
   467     }
   469     /*
   470      * Converts a value of type T from little-endian format.
   471      */
   472     template<typename T>
   473     MOZ_WARN_UNUSED_RESULT static T swapFromLittleEndian(T value) {
   474       return maybeSwap<Little, ThisEndian>(value);
   475     }
   476     /*
   477      * Copies count values of type T starting at src to dest, converting
   478      * them to little-endian format if ThisEndian is Big.
   479      * As with memcpy, dest and src must not overlap.
   480      */
   481     template<typename T>
   482     static void copyAndSwapFromLittleEndian(T* dest, const void* src,
   483                                             size_t count) {
   484       copyAndSwapFrom<Little, ThisEndian>(dest, src, count);
   485     }
   486     /*
   487      * Likewise, but converts values in place.
   488      */
   489     template<typename T>
   490     static void swapFromLittleEndianInPlace(T* p, size_t count) {
   491       maybeSwapInPlace<Little, ThisEndian>(p, count);
   492     }
   494     /*
   495      * Converts a value of type T from big-endian format.
   496      */
   497     template<typename T>
   498     MOZ_WARN_UNUSED_RESULT static T swapFromBigEndian(T value) {
   499       return maybeSwap<Big, ThisEndian>(value);
   500     }
   501     /*
   502      * Copies count values of type T starting at src to dest, converting
   503      * them to big-endian format if ThisEndian is Little.
   504      * As with memcpy, dest and src must not overlap.
   505      */
   506     template<typename T>
   507     static void copyAndSwapFromBigEndian(T* dest, const void* src,
   508                                          size_t count) {
   509       copyAndSwapFrom<Big, ThisEndian>(dest, src, count);
   510     }
   511     /*
   512      * Likewise, but converts values in place.
   513      */
   514     template<typename T>
   515     static void swapFromBigEndianInPlace(T* p, size_t count) {
   516       maybeSwapInPlace<Big, ThisEndian>(p, count);
   517     }
   519     /*
   520      * Synonyms for the big-endian functions, for better readability
   521      * in network code.
   522      */
   523     template<typename T>
   524     MOZ_WARN_UNUSED_RESULT static T swapFromNetworkOrder(T value) {
   525       return swapFromBigEndian(value);
   526     }
   527     template<typename T>
   528     static void copyAndSwapFromNetworkOrder(T* dest, const void* src,
   529                                             size_t count) {
   530       copyAndSwapFromBigEndian(dest, src, count);
   531     }
   532     template<typename T>
   533     static void swapFromNetworkOrderInPlace(T* p, size_t count) {
   534       swapFromBigEndianInPlace(p, count);
   535     }
   537   private:
   538     /**
   539      * Read a value of type T, encoded in endianness ThisEndian from |p|.
   540      * Return that value encoded in native endianness.
   541      */
   542     template<typename T>
   543     static T read(const void* p) {
   544       union {
   545         T val;
   546         uint8_t buffer[sizeof(T)];
   547       } u;
   548       memcpy(u.buffer, p, sizeof(T));
   549       return maybeSwap<ThisEndian, MOZ_NATIVE_ENDIANNESS>(u.val);
   550     }
   552     /**
   553      * Write a value of type T, in native endianness, to |p|, in ThisEndian
   554      * endianness.
   555      */
   556     template<typename T>
   557     static void write(void* p, T value) {
   558       T tmp = maybeSwap<MOZ_NATIVE_ENDIANNESS, ThisEndian>(value);
   559       memcpy(p, &tmp, sizeof(T));
   560     }
   562     Endian() MOZ_DELETE;
   563     Endian(const Endian& other) MOZ_DELETE;
   564     void operator=(const Endian& other) MOZ_DELETE;
   565 };
   567 template<Endianness ThisEndian>
   568 class EndianReadWrite : public Endian<ThisEndian>
   569 {
   570   private:
   571     typedef Endian<ThisEndian> super;
   573   public:
   574     using super::readUint16;
   575     using super::readUint32;
   576     using super::readUint64;
   577     using super::readInt16;
   578     using super::readInt32;
   579     using super::readInt64;
   580     using super::writeUint16;
   581     using super::writeUint32;
   582     using super::writeUint64;
   583     using super::writeInt16;
   584     using super::writeInt32;
   585     using super::writeInt64;
   586 };
   588 } /* namespace detail */
   590 class LittleEndian MOZ_FINAL : public detail::EndianReadWrite<detail::Little>
   591 {};
   593 class BigEndian MOZ_FINAL : public detail::EndianReadWrite<detail::Big>
   594 {};
   596 typedef BigEndian NetworkEndian;
   598 class NativeEndian MOZ_FINAL : public detail::Endian<MOZ_NATIVE_ENDIANNESS>
   599 {
   600   private:
   601     typedef detail::Endian<MOZ_NATIVE_ENDIANNESS> super;
   603   public:
   604     /*
   605      * These functions are intended for cases where you have data in your
   606      * native-endian format and you need the data to appear in the appropriate
   607      * endianness for transmission, serialization, etc.
   608      */
   609     using super::swapToLittleEndian;
   610     using super::copyAndSwapToLittleEndian;
   611     using super::swapToLittleEndianInPlace;
   612     using super::swapToBigEndian;
   613     using super::copyAndSwapToBigEndian;
   614     using super::swapToBigEndianInPlace;
   615     using super::swapToNetworkOrder;
   616     using super::copyAndSwapToNetworkOrder;
   617     using super::swapToNetworkOrderInPlace;
   619     /*
   620      * These functions are intended for cases where you have data in the
   621      * given endianness (e.g. reading from disk or a file-format) and you
   622      * need the data to appear in native-endian format for processing.
   623      */
   624     using super::swapFromLittleEndian;
   625     using super::copyAndSwapFromLittleEndian;
   626     using super::swapFromLittleEndianInPlace;
   627     using super::swapFromBigEndian;
   628     using super::copyAndSwapFromBigEndian;
   629     using super::swapFromBigEndianInPlace;
   630     using super::swapFromNetworkOrder;
   631     using super::copyAndSwapFromNetworkOrder;
   632     using super::swapFromNetworkOrderInPlace;
   633 };
   635 #undef MOZ_NATIVE_ENDIANNESS
   637 } /* namespace mozilla */
   639 #endif /* mozilla_Endian_h */

mercurial