2025-01-15 02:04:01 +00:00

214 lines
7.6 KiB
Java

/*
* Copyright (c) 2022, 2025, 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 java.lang.classfile;
import java.lang.classfile.constantpool.ConstantPool;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.PoolEntry;
import java.nio.ByteOrder;
import jdk.internal.classfile.impl.BufWriterImpl;
/**
* Advanced {@code class} file writing support for {@link AttributeMapper}s.
* Supports writing portions of a {@code class} file to a growable buffer, such
* as writing various numerical types (e.g., {@code u2}, {@code u4}), to the end
* of the buffer, as well as to create constant pool entries.
* <p>
* All numeric values in the {@code class} file format are {@linkplain
* ByteOrder#BIG_ENDIAN big endian}. Writing larger numeric values to smaller
* numeric values are always done with truncation, that the least significant
* bytes are kept and the other bytes are silently dropped. As a result,
* numeric value writing methods can write both signed and unsigned values, and
* users should validate their values before writing if silent dropping of most
* significant bytes is not the intended behavior.
*
* @see AttributeMapper#writeAttribute(BufWriter, Attribute)
* @since 24
*/
public sealed interface BufWriter
permits BufWriterImpl {
/**
* {@return the constant pool builder associated with this buffer}
*
* @see ClassFileBuilder#constantPool()
*/
ConstantPoolBuilder constantPool();
/**
* {@return whether the provided constant pool is index-compatible with the
* constant pool of this buffer}
* <p>
* This is a shortcut for {@code constantPool().canWriteDirect(other)}.
*
* @param other the other constant pool
* @see ConstantPoolBuilder#canWriteDirect(ConstantPool)
*/
boolean canWriteDirect(ConstantPool other);
/**
* Ensures that the buffer has at least {@code freeBytes} bytes of free space
* in the end of the buffer.
* <p>
* The writing result is the same without calls to this method, but the
* writing process may be slower.
*
* @apiNote
* This is a hint that changes no visible state of the buffer; it helps to
* reduce reallocation of the underlying storage by allocating sufficient
* space at once.
*
* @param freeBytes the number of bytes to reserve
*/
void reserveSpace(int freeBytes);
/**
* Writes a byte to the buffer. {@code x} is truncated to a byte and
* written.
*
* @param x the value to truncate to a byte
*/
void writeU1(int x);
/**
* Writes 2 bytes, or a short, to the buffer. {@code x} is truncated to two
* bytes and written.
*
* @param x the value to truncate to a short
*/
void writeU2(int x);
/**
* Writes 4 bytes, or an int, to the buffer.
*
* @param x the int value
*/
void writeInt(int x);
/**
* Writes a float value, of 4 bytes, to the buffer.
* <p>
* In the conversions, all NaN values of the {@code float} may or may not be
* collapsed into a single {@linkplain Float#NaN "canonical" NaN value}.
*
* @param x the float value
*/
void writeFloat(float x);
/**
* Writes 8 bytes, or a long, to the buffer.
*
* @param x the long value
*/
void writeLong(long x);
/**
* Writes a double value, of 8 bytes, to the buffer.
* <p>
* In the conversions, all NaN values of the {@code double} may or may not
* be collapsed into a single {@linkplain Double#NaN "canonical" NaN value}.
*
* @param x the double value
*/
void writeDouble(double x);
/**
* Writes the contents of a byte array to the buffer.
*
* @param arr the byte array
*/
void writeBytes(byte[] arr);
/**
* Writes a range of a byte array to the buffer.
*
* @param arr the byte array
* @param start the start offset of the range within the byte array
* @param length the length of the range
* @throws IndexOutOfBoundsException if range is outside the array bounds
*/
void writeBytes(byte[] arr, int start, int length);
/**
* Patches a previously written integer value. {@code value} is truncated
* to the given {@code size} number of bytes and written at the given {@code
* offset}. The end of this buffer stays unchanged.
*
* @apiNote
* The {@code offset} can be obtained by calling {@link #size()} before
* writing the previous integer value.
*
* @param offset the offset in this buffer at which to patch
* @param size the size of the integer value being written, in bytes
* @param value the integer value to be truncated
* @throws IndexOutOfBoundsException if patched int is outside of bounds
* @see #size()
*/
void patchInt(int offset, int size, int value);
/**
* Writes a multibyte value to the buffer. {@code intValue} is truncated
* to the given {@code intSize} number of bytes and written.
*
* @param intSize the size of the integer value being written, in bytes
* @param intValue the value to be truncated
*/
void writeIntBytes(int intSize, long intValue);
/**
* Writes the index of the specified constant pool entry as a {@link
* #writeU2 u2}. If the {@code entry} does not belong to the {@linkplain
* #constantPool() constant pool} of this buffer, it will be {@linkplain
* ConstantPoolBuilder##alien converted}, and the index of the converted
* pool entry is written instead.
*
* @param entry the constant pool entry
* @throws IllegalArgumentException if the entry has invalid index
*/
void writeIndex(PoolEntry entry);
/**
* Writes the index of the specified constant pool entry, or the value
* {@code 0} if the specified entry is {@code null}, as a {@link #writeU2
* u2}. If the {@code entry} does not belong to the {@linkplain
* #constantPool() constant pool} of this buffer, it will be {@linkplain
* ConstantPoolBuilder##alien converted}, and the index of the converted
* pool entry is written instead.
*
* @param entry the constant pool entry, may be {@code null}
* @throws IllegalArgumentException if the entry is not {@code null} and has
* invalid index
*/
void writeIndexOrZero(PoolEntry entry);
/**
* {@return the number of bytes that have been written to the buffer}
*
* @see #patchInt(int, int, int)
*/
int size();
}