blob: 7ba9b7db72e661fb3fc016d0c35ef3418ba166fe [file] [log] [blame]
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jlink.internal;
import java.nio.ByteBuffer;
import java.util.HashMap;
import jdk.internal.jimage.ImageStream;
import jdk.internal.jimage.ImageStrings;
import jdk.internal.jimage.ImageStringsReader;
class ImageStringsWriter implements ImageStrings {
private static final int NOT_FOUND = -1;
static final int EMPTY_OFFSET = 0;
private final HashMap<String, Integer> stringToOffsetMap;
private final ImageStream stream;
ImageStringsWriter() {
this.stringToOffsetMap = new HashMap<>();
this.stream = new ImageStream();
// Reserve 0 offset for empty string.
int offset = addString("");
if (offset != 0) {
throw new InternalError("Empty string not offset zero");
}
// Reserve 1 offset for frequently used ".class".
offset = addString("class");
if (offset != 1) {
throw new InternalError("'class' string not offset one");
}
}
private int addString(final String string) {
int offset = stream.getPosition();
byte[] bytes = ImageStringsReader.mutf8FromString(string);
stream.put(bytes, 0, bytes.length);
stream.put('\0');
stringToOffsetMap.put(string, offset);
return offset;
}
@Override
public int add(final String string) {
int offset = find(string);
return offset == NOT_FOUND ? addString(string) : offset;
}
int find(final String string) {
Integer offset = stringToOffsetMap.get(string);
return offset != null ? offset : NOT_FOUND;
}
@Override
public String get(int offset) {
ByteBuffer buffer = stream.getBuffer();
int capacity = buffer.capacity();
if (offset < 0 || offset >= capacity) {
throw new InternalError("String buffer offset out of range");
}
int zero = NOT_FOUND;
for (int i = offset; i < capacity; i++) {
if (buffer.get(i) == '\0') {
zero = i;
break;
}
}
if (zero == NOT_FOUND) {
throw new InternalError("String zero terminator not found");
}
int length = zero - offset;
byte[] bytes = new byte[length];
int mark = buffer.position();
buffer.position(offset);
buffer.get(bytes);
buffer.position(mark);
return ImageStringsReader.stringFromMUTF8(bytes);
}
ImageStream getStream() {
return stream;
}
int getSize() {
return stream.getSize();
}
int getCount() {
return stringToOffsetMap.size();
}
}