001/* 002 * Copyright 2013 Alex Kasko (alexkasko.com) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.alexkasko.unsafe.bytearray; 018 019/** 020 * Front-end class for operations over byte arrays. Default implementation uses {@code sun.misc.Unsafe} 021 * with {@code assert} boundary checks. To enable boundary check use {@code -ea} java switch, 022 * without boundary checks invalid input will crash (segfault) JVM. 023 * Fallback implementation uses standard byte array access and bit shifting. 024 * Unsafe implementation uses native endianness (LE on most platforms). Fallback implementation uses Little Endian byte order. 025 * 026 * @author alexkasko 027 * Date: 12/11/12 028 */ 029public abstract class ByteArrayTool { 030 031 /** 032 * Instantiates unsafe tool, if proper {@code sun.misc.Unsafe} implementation is available. 033 * Otherwise instantiates fallback (bitshift) implementation. 034 * 035 * @return tool instance 036 */ 037 public static ByteArrayTool get() { 038 try { 039 return unsafe(); 040 } catch (Exception e) { 041 return bitshift(); 042 } 043 } 044 045 /** 046 * Instantiates unsafe tool 047 * 048 * @return unsafe tool instance 049 * @throws Exception if proper {@code sun.misc.Unsafe} implementation is not available 050 */ 051 public static ByteArrayTool unsafe() throws Exception { 052 try { 053 Class<? extends ByteArrayTool> unsafeBaaClass = ByteArrayTool.class 054 .getClassLoader() 055 .loadClass(ByteArrayTool.class.getPackage().getName() + ".UnsafeByteArrayTool") 056 .asSubclass(ByteArrayTool.class); 057 return unsafeBaaClass.newInstance(); 058 } catch (Throwable t) { 059 throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); 060 } 061 } 062 063 /** 064 * Instantiates bitshift tool 065 * 066 * @return bitshift tool instance 067 */ 068 public static ByteArrayTool bitshift() { 069 return new BitShiftLittleEndianByteArrayTool(); 070 } 071 072 /** 073 * Whether current tool instance uses {@code sun.misc.Unsafe} 074 * 075 * @return whether unsafe 076 */ 077 public abstract boolean isUnsafe(); 078 079 /** 080 * Gets byte 081 * 082 * @param data byte array 083 * @param offset byte array index 084 * @return byte 085 */ 086 public abstract byte getByte(byte[] data, int offset); 087 088 /** 089 * Puts byte 090 * 091 * @param data byte array 092 * @param offset byte array index 093 * @param value value 094 */ 095 public abstract void putByte(byte[] data, int offset, byte value); 096 097 /** 098 * Gets one byte (stored as one signed byte), converts it to unsigned 099 * and returns it as short 100 * 101 * @param data byte array 102 * @param offset byte array index 103 * @return unsigned byte as short 104 */ 105 public abstract short getUnsignedByte(byte[] data, int offset); 106 107 /** 108 * Puts short with value from 0 to 255 inclusive into byte array as one 109 * signed byte 110 * 111 * @param data byte array 112 * @param offset byte array index 113 * @param value unsigned byte 114 */ 115 public abstract void putUnsignedByte(byte[] data, int offset, short value); 116 117 /** 118 * Gets two bytes as short 119 * 120 * @param data byte array 121 * @param offset byte array offset 122 * @return short value 123 */ 124 public abstract short getShort(byte[] data, int offset); 125 126 /** 127 * Puts short as two bytes 128 * 129 * @param data byte array 130 * @param offset byte array offset 131 * @param value short value 132 */ 133 public abstract void putShort(byte[] data, int offset, short value); 134 135 /** 136 * Gets unsigned short (stored as two bytes) and returns it as int 137 * 138 * @param data byte array 139 * @param offset byte array offset 140 * @return unsigned short as int 141 */ 142 public abstract int getUnsignedShort(byte[] data, int offset); 143 144 /** 145 * Puts int with value from 0 to 65535 inclusive as two bytes 146 * 147 * @param data byte array 148 * @param offset byte array offset 149 * @param value unsigned short as int 150 */ 151 public abstract void putUnsignedShort(byte[] data, int offset, int value); 152 153 /** 154 * Gets four bytes as int 155 * 156 * @param data byte array 157 * @param offset byte array offset 158 * @return int value 159 */ 160 public abstract int getInt(byte[] data, int offset); 161 162 /** 163 * Puts int as four bytes 164 * 165 * @param data byte array 166 * @param offset byte array offset 167 * @param value int value 168 */ 169 public abstract void putInt(byte[] data, int offset, int value); 170 171 /** 172 * Gets unsigned int (stored as 4 bytes) and returns it as long 173 * 174 * @param data byte array 175 * @param offset byte array offset 176 * @return unsigned int as long 177 */ 178 public abstract long getUnsignedInt(byte[] data, int offset); 179 180 /** 181 * Puts long value from 0 to 4294967295 inclusive as four bytes 182 * 183 * @param data byte array 184 * @param offset byte array offset 185 * @param value unsigned int as long 186 */ 187 public abstract void putUnsignedInt(byte[] data, int offset, long value); 188 189 /** 190 * Gets long 191 * 192 * @param data byte array 193 * @param offset byte array offset 194 * @return long value 195 */ 196 public abstract long getLong(byte[] data, int offset); 197 198 /** 199 * Puts long as eight bytes 200 * 201 * @param data byte array 202 * @param offset byte array offset 203 * @param value long value 204 */ 205 public abstract void putLong(byte[] data, int offset, long value); 206 207 /** 208 * Copies part of one array into another. Unsafe implementation has less 209 * bounds checks (if assertions are disabled in runtime) then {@link System#arraycopy(Object, int, Object, int, int)} 210 * that is used by fallback implementation uses 211 * 212 * @param src source array 213 * @param srcPos source array position 214 * @param dest destination array 215 * @param destPos destination array position 216 * @param length length to copy 217 */ 218 public abstract void copy(byte[] src, int srcPos, byte[] dest, int destPos, int length); 219}