blob: 80f6bfc8ed0f5468ef4bf1fd19647e28bf39f5b7 [file] [log] [blame]
/*
* Copyright (c) 2017, 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.
*
* 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.experimental.bytecode;
/**
* Base builder for attribute containing class file entities.
*
* @param <S> the type of the symbol representation
* @param <T> the type of type descriptors representation
* @param <E> the type of pool entries
* @param <D> the type of this builder
*/
public class AttributeBuilder<S, T, E, D extends AttributeBuilder<S, T, E, D>>
extends AbstractBuilder<S, T, E, D> {
/**
* The number of attributes.
*/
protected int nattrs;
/**
* The attributes represented as bytes.
*/
protected GrowableByteBuffer attributes = new GrowableByteBuffer();
/**
* Create an attribute builder.
*
* @param poolHelper the helper to build the constant pool
* @param typeHelper the helper to use to manipulate type descriptors
*/
public AttributeBuilder(PoolHelper<S, T, E> poolHelper, TypeHelper<S, T> typeHelper) {
super(poolHelper, typeHelper);
}
/**
* Add a class file Attribute. Defined as:
* <pre>
* {@code attribute_info {
* u2 attribute_name_index;
* u4 attribute_length;
* u1 info[attribute_length];
* }}
* </pre>
*
* @param name the attribute name
* @param bytes the bytes of the attribute info
* @return this builder, for chained calls
*/
public D withAttribute(CharSequence name, byte[] bytes) {
attributes.writeChar(poolHelper.putUtf8(name));
attributes.writeInt(bytes.length);
attributes.writeBytes(bytes);
nattrs++;
return thisBuilder();
}
/**
* Add a class file Attribute, using a writer. Defined as:
* <pre>
* {@code attribute_info {
* u2 attribute_name_index;
* u4 attribute_length;
* u1 info[attribute_length];
* }}
* </pre>
*
* @param <Z> the type of the object representing the attribute
* @param name the attribute name
* @param attr the representation of the attribute
* @param attrWriter the writer which transform the attribute representation into bytes
* @return this builder, for chained calls
*/
public <Z> D withAttribute(CharSequence name, Z attr, AttributeWriter<S, T, E, Z> attrWriter) {
attributes.writeChar(poolHelper.putUtf8(name));
int offset = attributes.offset;
attributes.writeInt(0);
attrWriter.write(attr, poolHelper, attributes);
int len = attributes.offset - offset - 4;
attributes.withOffset(offset, buf -> buf.writeInt(len));
nattrs++;
return thisBuilder();
}
/**
* Writer for transforming attribute representations to bytes
*
* @param <S> the type of symbol representation
* @param <T> the type of type descriptors representation
* @param <E> the type of pool entries
* @param <A> the type of the object representing the attribute
*/
public interface AttributeWriter<S, T, E, A> {
/**
* Write an attribute representation into a byte buffer.
*
* @param attr the representation of the attribute
* @param poolHelper the constant pool helper
* @param buf the buffer to collect the bytes
*/
void write(A attr, PoolHelper<S, T, E> poolHelper, GrowableByteBuffer buf);
}
}