Interface CLinker.VaList

All Superinterfaces:
Addressable, AutoCloseable
Enclosing interface:
CLinker

public static interface CLinker.VaList extends Addressable, AutoCloseable
An interface that models a C va_list.

A va list is a stateful cursor used to iterate over a set of variadic arguments.

Per the C specification (see C standard 6.5.2.2 Function calls - item 6), arguments to variadic calls are erased by way of 'default argument promotions', which erases integral types by way of integer promotion (see C standard 6.3.1.1 - item 2), and which erases all float arguments to double.

As such, this interface only supports reading int, double, and any other type that fits into a long.

Unless otherwise specified, passing a null argument, or an array argument containing one or more null elements to a method in this class causes a NullPointerException to be thrown.

API Note:
In the future, if the Java language permits, CLinker.VaList may become a sealed interface, which would prohibit subclassing except by explicitly permitted types.
  • Method Details

    • vargAsInt

      int vargAsInt(MemoryLayout layout)
      Reads the next value as an int and advances this va list's position.
      Parameters:
      layout - the layout of the value
      Returns:
      the value read as an int
      Throws:
      IllegalStateException - if the C va_list associated with this instance is no longer valid (see close()).
      IllegalArgumentException - if the given memory layout is not compatible with int
    • vargAsLong

      long vargAsLong(MemoryLayout layout)
      Reads the next value as a long and advances this va list's position.
      Parameters:
      layout - the layout of the value
      Returns:
      the value read as an long
      Throws:
      IllegalStateException - if the C va_list associated with this instance is no longer valid (see close()).
      IllegalArgumentException - if the given memory layout is not compatible with long
    • vargAsDouble

      double vargAsDouble(MemoryLayout layout)
      Reads the next value as a double and advances this va list's position.
      Parameters:
      layout - the layout of the value
      Returns:
      the value read as an double
      Throws:
      IllegalStateException - if the C va_list associated with this instance is no longer valid (see close()).
      IllegalArgumentException - if the given memory layout is not compatible with double
    • vargAsAddress

      MemoryAddress vargAsAddress(MemoryLayout layout)
      Reads the next value as a MemoryAddress and advances this va list's position.
      Parameters:
      layout - the layout of the value
      Returns:
      the value read as an MemoryAddress
      Throws:
      IllegalStateException - if the C va_list associated with this instance is no longer valid (see close()).
      IllegalArgumentException - if the given memory layout is not compatible with MemoryAddress
    • vargAsSegment

      MemorySegment vargAsSegment(MemoryLayout layout)
      Reads the next value as a MemorySegment, and advances this va list's position.

      The memory segment returned by this method will be allocated using MemorySegment.allocateNative(long, long), and will have to be closed separately.

      Parameters:
      layout - the layout of the value
      Returns:
      the value read as an MemorySegment
      Throws:
      IllegalStateException - if the C va_list associated with this instance is no longer valid (see close()).
      IllegalArgumentException - if the given memory layout is not compatible with MemorySegment
    • vargAsSegment

      MemorySegment vargAsSegment(MemoryLayout layout, NativeScope scope)
      Reads the next value as a MemorySegment, and advances this va list's position.

      The memory segment returned by this method will be allocated using the given NativeScope.

      Parameters:
      layout - the layout of the value
      scope - the scope to allocate the segment in
      Returns:
      the value read as an MemorySegment
      Throws:
      IllegalStateException - if the C va_list associated with this instance is no longer valid (see close()).
      IllegalArgumentException - if the given memory layout is not compatible with MemorySegment
    • skip

      void skip(MemoryLayout... layouts)
      Skips a number of elements with the given memory layouts, and advances this va list's position.
      Parameters:
      layouts - the layout of the value
      Throws:
      IllegalStateException - if the C va_list associated with this instance is no longer valid (see close()).
    • isAlive

      boolean isAlive()
      A predicate used to check if the memory associated with the C va_list modelled by this instance is still valid to use.
      Returns:
      true, if the memory associated with the C va_list modelled by this instance is still valid
      See Also:
      close()
    • close

      void close()
      Releases the underlying C va_list modelled by this instance, and any native memory that is attached to this va list that holds its elements (see make(Consumer)).

      After calling this method, isAlive() will return false and further attempts to read values from this va list will result in an exception.

      Specified by:
      close in interface AutoCloseable
      See Also:
      isAlive()
    • copy

      Copies this C va_list at its current position. Copying is useful to traverse the va list's elements starting from the current position, without affecting the state of the original va list, essentially allowing the elements to be traversed multiple times.

      If this method needs to allocate native memory for the copy, it will use MemorySegment.allocateNative(long, long) to do so. close() will have to be called on the returned va list instance to release the allocated memory.

      This method only copies the va list cursor itself and not the memory that may be attached to the va list which holds its elements. That means that if this va list was created with the make(Consumer) method, closing this va list will also release the native memory that holds its elements, making the copy unusable.

      Returns:
      a copy of this C va_list.
      Throws:
      IllegalStateException - if the C va_list associated with this instance is no longer valid (see close()).
    • copy

      CLinker.VaList copy(NativeScope scope)
      Copies this C va_list at its current position. Copying is useful to traverse the va list's elements starting from the current position, without affecting the state of the original va list, essentially allowing the elements to be traversed multiple times.

      If this method needs to allocate native memory for the copy, it will use the given NativeScope to do so.

      This method only copies the va list cursor itself and not the memory that may be attached to the va list which holds its elements. That means that if this va list was created with the make(Consumer) method, closing this va list will also release the native memory that holds its elements, making the copy unusable.

      Parameters:
      scope - the scope to allocate the copy in
      Returns:
      a copy of this C va_list.
      Throws:
      IllegalStateException - if the C va_list associated with this instance is no longer valid (see close()).
    • address

      MemoryAddress address()
      Returns the memory address of the C va_list associated with this instance.
      Specified by:
      address in interface Addressable
      Returns:
      the memory address of the C va_list associated with this instance.
    • ofAddressRestricted

      static CLinker.VaList ofAddressRestricted(MemoryAddress address)
      Constructs a new VaList instance out of a memory address pointing to an existing C va_list.

      This method is restricted. Restricted method are unsafe, and, if used incorrectly, their use might crash the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on restricted methods, and use safe and supported functionalities, where possible.

      Parameters:
      address - a memory address pointing to an existing C va_list.
      Returns:
      a new VaList instance backed by the C va_list at address.
    • make

      static CLinker.VaList make(Consumer<CLinker.VaList.Builder> actions)
      Constructs a new VaList using a builder (see CLinker.VaList.Builder).

      If this method needs to allocate native memory for the va list, it will use MemorySegment.allocateNative(long, long) to do so.

      This method will allocate native memory to hold the elements in the va list. This memory will be 'attached' to the returned va list instance, and will be released when close() is called.

      Note that when there are no elements added to the created va list, this method will return the same as empty().

      Parameters:
      actions - a consumer for a builder (see CLinker.VaList.Builder) which can be used to specify the elements of the underlying C va_list.
      Returns:
      a new VaList instance backed by a fresh C va_list.
    • make

      static CLinker.VaList make(Consumer<CLinker.VaList.Builder> actions, NativeScope scope)
      Constructs a new VaList using a builder (see CLinker.VaList.Builder).

      If this method needs to allocate native memory for the va list, it will use the given NativeScope to do so.

      This method will allocate native memory to hold the elements in the va list. This memory will be managed by the given NativeScope, and will be released when the scope is closed.

      Note that when there are no elements added to the created va list, this method will return the same as empty().

      Parameters:
      actions - a consumer for a builder (see CLinker.VaList.Builder) which can be used to specify the elements of the underlying C va_list.
      scope - the scope to be used for the valist allocation.
      Returns:
      a new VaList instance backed by a fresh C va_list.
    • empty

      static CLinker.VaList empty()
      Returns an empty C va_list constant.

      The returned VaList can not be closed.

      Returns:
      a VaList modelling an empty C va_list.