1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.internal.jimage; 27 28 public class ImageLocationBase { 29 final static int ATTRIBUTE_END = 0; 30 final static int ATTRIBUTE_MODULE = 1; 31 final static int ATTRIBUTE_PARENT = 2; 32 final static int ATTRIBUTE_BASE = 3; 33 final static int ATTRIBUTE_EXTENSION = 4; 34 final static int ATTRIBUTE_OFFSET = 5; 35 final static int ATTRIBUTE_COMPRESSED = 6; 36 final static int ATTRIBUTE_UNCOMPRESSED = 7; 37 final static int ATTRIBUTE_COUNT = 8; 38 39 protected final long[] attributes; 40 41 protected final ImageStrings strings; 42 43 protected ImageLocationBase(long[] attributes, ImageStrings strings) { 44 this.attributes = attributes; 45 this.strings = strings; 46 } 47 48 ImageStrings getStrings() { 49 return strings; 50 } 51 52 private static int attributeLength(int data) { 53 return (data & 0x7) + 1; 54 } 55 56 private static int attributeKind(int data) { 57 return data >>> 3; 58 } 59 60 static long[] decompress(byte[] bytes) { 61 return decompress(bytes, 0); 62 } 63 64 static long[] decompress(byte[] bytes, int offset) { 65 long[] attributes = new long[ATTRIBUTE_COUNT]; 66 67 if (bytes != null) { 68 for (int i = offset; i < bytes.length; ) { 69 int data = bytes[i++] & 0xFF; 70 int kind = attributeKind(data); 71 72 if (kind == ATTRIBUTE_END) { 73 break; 74 } 75 76 assert ATTRIBUTE_END < kind && 77 kind < ATTRIBUTE_COUNT : "Invalid attribute kind"; 78 int length = attributeLength(data); 79 long value = 0; 80 81 for (int j = 0; j < length; j++) { 82 value <<= 8; 83 value |= bytes[i++] & 0xFF; 84 } 85 86 attributes[kind] = value; 87 } 88 } 89 90 return attributes; 91 } 92 93 static byte[] compress(long[] attributes) { 94 ImageStream stream = new ImageStream(16); 95 96 for (int kind = ATTRIBUTE_END + 1; kind < ATTRIBUTE_COUNT; kind++) { 97 long value = attributes[kind]; 98 99 if (value != 0) { 100 int n = (63 - Long.numberOfLeadingZeros(value)) >> 3; 101 stream.put((kind << 3) | n); 102 103 for (int i = n; i >= 0; i--) { 104 stream.put((int)(value >> (i << 3))); 105 } 106 } 107 } 108 109 stream.put(ATTRIBUTE_END << 3); 110 111 return stream.toArray(); 112 } 113 114 public boolean verify(UTF8String name) { 115 return UTF8String.equals(getFullName(), name); 116 } 117 118 protected long getAttribute(int kind) { 119 assert ATTRIBUTE_END < kind && 120 kind < ATTRIBUTE_COUNT : "Invalid attribute kind"; 121 122 return attributes[kind]; 123 } 124 125 protected UTF8String getAttributeUTF8String(int kind) { 126 assert ATTRIBUTE_END < kind && 127 kind < ATTRIBUTE_COUNT : "Invalid attribute kind"; 128 129 return getStrings().get((int)attributes[kind]); 130 } 131 132 protected String getAttributeString(int kind) { 133 return getAttributeUTF8String(kind).toString(); 134 } 135 136 UTF8String getModule() { 137 return getAttributeUTF8String(ATTRIBUTE_MODULE); 138 } 139 140 public String getModuleString() { 141 return getModule().toString(); 142 } 143 144 int getModuleOffset() { 145 return (int)getAttribute(ATTRIBUTE_MODULE); 146 } 147 148 UTF8String getBase() { 149 return getAttributeUTF8String(ATTRIBUTE_BASE); 150 } 151 152 public String getBaseString() { 153 return getBase().toString(); 154 } 155 156 int getBaseOffset() { 157 return (int)getAttribute(ATTRIBUTE_BASE); 158 } 159 160 UTF8String getParent() { 161 return getAttributeUTF8String(ATTRIBUTE_PARENT); 162 } 163 164 public String getParentString() { 165 return getParent().toString(); 166 } 167 168 int getParentOffset() { 169 return (int)getAttribute(ATTRIBUTE_PARENT); 170 } 171 172 UTF8String getExtension() { 173 return getAttributeUTF8String(ATTRIBUTE_EXTENSION); 174 } 175 176 public String getExtensionString() { 177 return getExtension().toString(); 178 } 179 180 int getExtensionOffset() { 181 return (int)getAttribute(ATTRIBUTE_EXTENSION); 182 } 183 184 UTF8String getFullName() { 185 return getFullName(false); 186 } 187 188 UTF8String getFullName(boolean modulesPrefix) { 189 // Note: Consider a UTF8StringBuilder. 190 UTF8String fullName = UTF8String.EMPTY_STRING; 191 192 if (getModuleOffset() != 0) { 193 fullName = fullName.concat( 194 // TODO The use of UTF8String.MODULES_STRING does not belong here. 195 modulesPrefix? UTF8String.MODULES_STRING : 196 UTF8String.EMPTY_STRING, 197 UTF8String.SLASH_STRING, 198 getModule(), 199 UTF8String.SLASH_STRING); 200 } 201 202 if (getParentOffset() != 0) { 203 fullName = fullName.concat(getParent(), 204 UTF8String.SLASH_STRING); 205 } 206 207 fullName = fullName.concat(getBase()); 208 209 if (getExtensionOffset() != 0) { 210 fullName = fullName.concat(UTF8String.DOT_STRING, 211 getExtension()); 212 } 213 214 return fullName; 215 } 216 217 UTF8String buildName(boolean includeModule, boolean includeParent, 218 boolean includeName) { 219 // Note: Consider a UTF8StringBuilder. 220 UTF8String name = UTF8String.EMPTY_STRING; 221 222 if (includeModule && getModuleOffset() != 0) { 223 name = name.concat(UTF8String.MODULES_STRING, 224 UTF8String.SLASH_STRING, 225 getModule()); 226 } 227 228 if (includeParent && getParentOffset() != 0) { 229 name = name.concat(UTF8String.SLASH_STRING, 230 getParent()); 231 } 232 233 if (includeName) { 234 if (includeModule || includeParent) { 235 name = name.concat(UTF8String.SLASH_STRING); 236 } 237 238 name = name.concat(getBase()); 239 240 if (getExtensionOffset() != 0) { 241 name = name.concat(UTF8String.DOT_STRING, 242 getExtension()); 243 } 244 } 245 246 return name; 247 } 248 249 String getFullNameString() { 250 return getFullName().toString(); 251 } 252 253 public long getContentOffset() { 254 return getAttribute(ATTRIBUTE_OFFSET); 255 } 256 257 public long getCompressedSize() { 258 return getAttribute(ATTRIBUTE_COMPRESSED); 259 } 260 261 public long getUncompressedSize() { 262 return getAttribute(ATTRIBUTE_UNCOMPRESSED); 263 } 264 }