1 /*
2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *   - Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *   - Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *   - Neither the name of Oracle nor the names of its
16  *     contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "endian.hpp"
33 #include "inttypes.hpp"
34 
35 // Most modern compilers optimize the bswap routines to native instructions.
bswap_16(u2 x)36 inline static u2 bswap_16(u2 x) {
37     return ((x & 0xFF) << 8) |
38            ((x >> 8) & 0xFF);
39 }
40 
bswap_32(u4 x)41 inline static u4 bswap_32(u4 x) {
42     return ((x & 0xFF) << 24) |
43            ((x & 0xFF00) << 8) |
44            ((x >> 8) & 0xFF00) |
45            ((x >> 24) & 0xFF);
46 }
47 
bswap_64(u8 x)48 inline static u8 bswap_64(u8 x) {
49     return (u8)bswap_32((u4)x) << 32 |
50            (u8)bswap_32((u4)(x >> 32));
51 }
52 
get(u2 x)53 u2 NativeEndian::get(u2 x) { return x; }
get(u4 x)54 u4 NativeEndian::get(u4 x) { return x; }
get(u8 x)55 u8 NativeEndian::get(u8 x) { return x; }
get(s2 x)56 s2 NativeEndian::get(s2 x) { return x; }
get(s4 x)57 s4 NativeEndian::get(s4 x) { return x; }
get(s8 x)58 s8 NativeEndian::get(s8 x) { return x; }
59 
set(u2 & x,u2 y)60 void NativeEndian::set(u2& x, u2 y) { x = y; }
set(u4 & x,u4 y)61 void NativeEndian::set(u4& x, u4 y) { x = y; }
set(u8 & x,u8 y)62 void NativeEndian::set(u8& x, u8 y) { x = y; }
set(s2 & x,s2 y)63 void NativeEndian::set(s2& x, s2 y) { x = y; }
set(s4 & x,s4 y)64 void NativeEndian::set(s4& x, s4 y) { x = y; }
set(s8 & x,s8 y)65 void NativeEndian::set(s8& x, s8 y) { x = y; }
66 
67 NativeEndian NativeEndian::_native;
68 
get(u2 x)69 u2 SwappingEndian::get(u2 x) { return bswap_16(x); }
get(u4 x)70 u4 SwappingEndian::get(u4 x) { return bswap_32(x); }
get(u8 x)71 u8 SwappingEndian::get(u8 x) { return bswap_64(x); }
get(s2 x)72 s2 SwappingEndian::get(s2 x) { return bswap_16(x); }
get(s4 x)73 s4 SwappingEndian::get(s4 x) { return bswap_32(x); }
get(s8 x)74 s8 SwappingEndian::get(s8 x) { return bswap_64(x); }
75 
set(u2 & x,u2 y)76 void SwappingEndian::set(u2& x, u2 y) { x = bswap_16(y); }
set(u4 & x,u4 y)77 void SwappingEndian::set(u4& x, u4 y) { x = bswap_32(y); }
set(u8 & x,u8 y)78 void SwappingEndian::set(u8& x, u8 y) { x = bswap_64(y); }
set(s2 & x,s2 y)79 void SwappingEndian::set(s2& x, s2 y) { x = bswap_16(y); }
set(s4 & x,s4 y)80 void SwappingEndian::set(s4& x, s4 y) { x = bswap_32(y); }
set(s8 & x,s8 y)81 void SwappingEndian::set(s8& x, s8 y) { x = bswap_64(y); }
82 
83 SwappingEndian SwappingEndian::_swapping;
84 
get_handler(bool big_endian)85 Endian* Endian::get_handler(bool big_endian) {
86     // If requesting little endian on a little endian machine or
87     // big endian on a big endian machine use native handler
88     if (big_endian == is_big_endian()) {
89         return NativeEndian::get_native();
90     } else {
91         // Use swapping handler.
92         return SwappingEndian::get_swapping();
93     }
94 }
95 
96 // Return a platform u2 from an array in which Big Endian is applied.
get_java(u1 * x)97 u2 Endian::get_java(u1* x) {
98     return (u2) (x[0]<<8 | x[1]);
99 }
100 
101 // Add a platform u2 to the array as a Big Endian u2
set_java(u1 * p,u2 x)102 void Endian::set_java(u1* p, u2 x) {
103     p[0] = (x >> 8) & 0xff;
104     p[1] = x & 0xff;
105 }
106 
get_native_handler()107 Endian* Endian::get_native_handler() {
108     return NativeEndian::get_native();
109 }
110