1 /*
  2  *  Copyright (c) 2020, 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.incubator.foreign;
 27 
 28 import jdk.internal.foreign.AbstractMemorySegmentImpl;
 29 import jdk.internal.foreign.Utils;
 30 import jdk.internal.foreign.abi.SharedUtils;
 31 
 32 import java.lang.invoke.VarHandle;
 33 import java.nio.ByteOrder;
 34 import java.nio.charset.Charset;
 35 import java.util.Objects;
 36 import java.util.function.Consumer;
 37 
 38 /**
 39  * A set of utilities for working with libraries using the C language/ABI
 40  */
 41 public class CSupport {
 42     /**
 43      * Obtain a linker that uses the de facto C ABI of the current system to do it's linking.
 44      * <p>
 45      * This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
 46      * the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
 47      * restricted methods, and use safe and supported functionalities, where possible.
 48      * @return a linker for this system.
 49      * @throws IllegalAccessError if the runtime property {@code foreign.restricted} is not set to either
 50      * {@code permit}, {@code warn} or {@code debug} (the default value is set to {@code deny}).
 51      */
 52     public static ForeignLinker getSystemLinker() {
 53         Utils.checkRestrictedAccess("CSupport.getSystemLinker");
 54         return SharedUtils.getSystemLinker();
 55     }
 56 
 57     /**
 58      * An interface that models a C {@code va_list}.
 59      *
 60      * Per the C specification (see C standard 6.5.2.2 Function calls - item 6),
 61      * arguments to variadic calls are erased by way of 'default argument promotions',
 62      * which erases integral types by way of integer promotion (see C standard 6.3.1.1 - item 2),
 63      * and which erases all {@code float} arguments to {@code double}.
 64      *
 65      * As such, this interface only supports reading {@code int}, {@code double},
 66      * and any other type that fits into a {@code long}.
 67      */
 68     public interface VaList extends AutoCloseable {
 69 
 70         /**
 71          * Reads a value into an {@code int}
 72          *
 73          * @param layout the layout of the value
 74          * @return the value read as an {@code int}
 75          * @throws IllegalStateException if the C {@code va_list} associated with this instance is no longer valid
 76          * (see {@link #close()}).
 77          */
 78         int vargAsInt(MemoryLayout layout);
 79 
 80         /**
 81          * Reads a value into a {@code long}
 82          *
 83          * @param layout the layout of the value
 84          * @return the value read as an {@code long}
 85          * @throws IllegalStateException if the C {@code va_list} associated with this instance is no longer valid
 86          * (see {@link #close()}).
 87          */
 88         long vargAsLong(MemoryLayout layout);
 89 
 90         /**
 91          * Reads a value into a {@code double}
 92          *
 93          * @param layout the layout of the value
 94          * @return the value read as an {@code double}
 95          * @throws IllegalStateException if the C {@code va_list} associated with this instance is no longer valid
 96          * (see {@link #close()}).
 97          */
 98         double vargAsDouble(MemoryLayout layout);
 99 
100         /**
101          * Reads a value into a {@code MemoryAddress}
102          *
103          * @param layout the layout of the value
104          * @return the value read as an {@code MemoryAddress}
105          * @throws IllegalStateException if the C {@code va_list} associated with this instance is no longer valid
106          * (see {@link #close()}).
107          */
108         MemoryAddress vargAsAddress(MemoryLayout layout);
109 
110         /**
111          * Reads a value into a {@code MemorySegment}
112          *
113          * @param layout the layout of the value
114          * @return the value read as an {@code MemorySegment}
115          * @throws IllegalStateException if the C {@code va_list} associated with this instance is no longer valid
116          * (see {@link #close()}).
117          */
118         MemorySegment vargAsSegment(MemoryLayout layout);
119 
120         /**
121          * Skips a number of va arguments with the given memory layouts.
122          *
123          * @param layouts the layout of the value
124          * @throws IllegalStateException if the C {@code va_list} associated with this instance is no longer valid
125          * (see {@link #close()}).
126          */
127         void skip(MemoryLayout... layouts);
128 
129         /**
130          * A predicate used to check if the memory associated with the C {@code va_list} modelled
131          * by this instance is still valid; or, in other words, if {@code close()} has been called on this
132          * instance.
133          *
134          * @return true, if the memory associated with the C {@code va_list} modelled by this instance is still valid
135          * @see #close()
136          */
137         boolean isAlive();
138 
139         /**
140          * Releases the underlying C {@code va_list} modelled by this instance. As a result, subsequent attempts to call
141          * operations on this instance (e.g. {@link #copy()} will fail with an exception.
142          *
143          * @see #isAlive()
144          */
145         void close();
146 
147         /**
148          * Copies this C {@code va_list}.
149          *
150          * @return a copy of this C {@code va_list}.
151          * @throws IllegalStateException if the C {@code va_list} associated with this instance is no longer valid
152          * (see {@link #close()}).
153          */
154         VaList copy();
155 
156         /**
157          * Returns the memory address of the C {@code va_list} associated with this instance.
158          *
159          * @return the memory address of the C {@code va_list} associated with this instance.
160          */
161         MemoryAddress address();
162 
163         /**
164          * Constructs a new {@code VaList} instance out of a memory address pointing to an existing C {@code va_list}.
165          *
166          * @param address a memory address pointing to an existing C {@code va_list}.
167          * @return a new {@code VaList} instance backed by the C {@code va_list} at {@code address}.
168          */
169         static VaList ofAddress(MemoryAddress address) {
170             return SharedUtils.newVaListOfAddress(address);
171         }
172 
173         /**
174          * Constructs a new {@code VaList} using a builder (see {@link Builder}).
175          *
176          * @param actions a consumer for a builder (see {@link Builder}) which can be used to specify the contents
177          *                of the underlying C {@code va_list}.
178          * @return a new {@code VaList} instance backed by a fresh C {@code va_list}.
179          */
180         static VaList make(Consumer<VaList.Builder> actions) {
181             return SharedUtils.newVaList(actions);
182         }
183 
184         /**
185          * A builder interface used to construct a C {@code va_list}.
186          */
187         interface Builder {
188 
189             /**
190              * Adds a native value represented as an {@code int} to the C {@code va_list} being constructed.
191              *
192              * @param layout the native layout of the value.
193              * @param value the value, represented as an {@code int}.
194              * @return this builder.
195              */
196             Builder vargFromInt(MemoryLayout layout, int value);
197 
198             /**
199              * Adds a native value represented as a {@code long} to the C {@code va_list} being constructed.
200              *
201              * @param layout the native layout of the value.
202              * @param value the value, represented as a {@code long}.
203              * @return this builder.
204              */
205             Builder vargFromLong(MemoryLayout layout, long value);
206 
207             /**
208              * Adds a native value represented as a {@code double} to the C {@code va_list} being constructed.
209              *
210              * @param layout the native layout of the value.
211              * @param value the value, represented as a {@code double}.
212              * @return this builder.
213              */
214             Builder vargFromDouble(MemoryLayout layout, double value);
215 
216             /**
217              * Adds a native value represented as a {@code MemoryAddress} to the C {@code va_list} being constructed.
218              *
219              * @param layout the native layout of the value.
220              * @param value the value, represented as a {@code MemoryAddress}.
221              * @return this builder.
222              */
223             Builder vargFromAddress(MemoryLayout layout, MemoryAddress value);
224 
225             /**
226              * Adds a native value represented as a {@code MemorySegment} to the C {@code va_list} being constructed.
227              *
228              * @param layout the native layout of the value.
229              * @param value the value, represented as a {@code MemorySegment}.
230              * @return this builder.
231              */
232             Builder vargFromSegment(MemoryLayout layout, MemorySegment value);
233         }
234     }
235 
236     /**
237      * The {@code _Bool} native type.
238      */
239     public static final ValueLayout C_BOOL = Utils.pick(SysV.C_BOOL, Win64.C_BOOL, AArch64.C_BOOL);
240     /**
241      * The {@code char} native type.
242      */
243     public static final ValueLayout C_CHAR = Utils.pick(SysV.C_CHAR, Win64.C_CHAR, AArch64.C_CHAR);
244     /**
245      * The {@code short} native type.
246      */
247     public static final ValueLayout C_SHORT = Utils.pick(SysV.C_SHORT, Win64.C_SHORT, AArch64.C_SHORT);
248     /**
249      * The {@code int} native type.
250      */
251     public static final ValueLayout C_INT = Utils.pick(SysV.C_INT, Win64.C_INT, AArch64.C_INT);
252     /**
253      * The {@code long} native type.
254      */
255     public static final ValueLayout C_LONG = Utils.pick(SysV.C_LONG, Win64.C_LONG, AArch64.C_LONG);
256     /**
257      * The {@code long long} native type.
258      */
259     public static final ValueLayout C_LONGLONG = Utils.pick(SysV.C_LONGLONG, Win64.C_LONGLONG, AArch64.C_LONGLONG);
260     /**
261      * The {@code float} native type.
262      */
263     public static final ValueLayout C_FLOAT = Utils.pick(SysV.C_FLOAT, Win64.C_FLOAT, AArch64.C_FLOAT);
264     /**
265      * The {@code double} native type.
266      */
267     public static final ValueLayout C_DOUBLE = Utils.pick(SysV.C_DOUBLE, Win64.C_DOUBLE, AArch64.C_DOUBLE);
268     /**
269      * The {@code long double} native type.
270      */
271     public static final ValueLayout C_LONGDOUBLE = Utils.pick(SysV.C_LONGDOUBLE, Win64.C_LONGDOUBLE, AArch64.C_LONGDOUBLE);
272     /**
273      * The {@code T*} native type.
274      */
275     public static final ValueLayout C_POINTER = Utils.pick(SysV.C_POINTER, Win64.C_POINTER, AArch64.C_POINTER);
276 
277     /**
278      * The {@code va_list} native type.
279      */
280     public static final MemoryLayout C_VA_LIST = Utils.pick(SysV.C_VA_LIST, Win64.C_VA_LIST, null);
281 
282     /**
283      * This class defines layout constants modelling standard primitive types supported by the x64 SystemV ABI.
284      */
285     public static final class SysV {
286         private SysV() {
287             //just the one
288         }
289 
290         /**
291          * The name of the SysV linker ({@see ForeignLinker#name})
292          */
293         public static final String NAME = "SysV";
294 
295         public final static String CLASS_ATTRIBUTE_NAME = "abi/sysv/class";
296 
297         public enum ArgumentClass {
298             INTEGER,
299             SSE,
300             X87,
301             COMPLEX_87,
302             POINTER;
303         }
304 
305         /**
306          * The {@code _Bool} native type.
307          */
308         public static final ValueLayout C_BOOL = MemoryLayouts.BITS_8_LE
309                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
310 
311         /**
312          * The {@code char} native type.
313          */
314         public static final ValueLayout C_CHAR = MemoryLayouts.BITS_8_LE
315                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
316 
317         /**
318          * The {@code short} native type.
319          */
320         public static final ValueLayout C_SHORT = MemoryLayouts.BITS_16_LE
321                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
322 
323         /**
324          * The {@code int} native type.
325          */
326         public static final ValueLayout C_INT = MemoryLayouts.BITS_32_LE
327                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
328 
329         /**
330          * The {@code long} native type.
331          */
332         public static final ValueLayout C_LONG = MemoryLayouts.BITS_64_LE
333                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
334 
335         /**
336          * The {@code long long} native type.
337          */
338         public static final ValueLayout C_LONGLONG = MemoryLayouts.BITS_64_LE
339                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
340 
341         /**
342          * The {@code float} native type.
343          */
344         public static final ValueLayout C_FLOAT = MemoryLayouts.BITS_32_LE
345                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.SSE);
346 
347         /**
348          * The {@code double} native type.
349          */
350         public static final ValueLayout C_DOUBLE = MemoryLayouts.BITS_64_LE
351                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.SSE);
352 
353         /**
354          * The {@code long double} native type.
355          */
356         public static final ValueLayout C_LONGDOUBLE = MemoryLayout.ofValueBits(128, ByteOrder.LITTLE_ENDIAN)
357                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.X87);
358 
359         /**
360          * The {@code complex long double} native type.
361          */
362         public static final GroupLayout C_COMPLEX_LONGDOUBLE = MemoryLayout.ofStruct(C_LONGDOUBLE, C_LONGDOUBLE)
363                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.COMPLEX_87);
364 
365         /**
366          * The {@code T*} native type.
367          */
368         public static final ValueLayout C_POINTER = MemoryLayouts.BITS_64_LE
369                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.POINTER);
370 
371         /**
372          * The {@code va_list} native type, as it is passed to a function.
373          */
374         public static final MemoryLayout C_VA_LIST = SysV.C_POINTER;
375     }
376 
377     /**
378      * This class defines layout constants modelling standard primitive types supported by the x64 Windows ABI.
379      */
380     public static final class Win64 {
381 
382         private Win64() {
383             //just the one
384         }
385 
386         /**
387          * The name of the Windows linker ({@see ForeignLinker#name})
388          */
389         public final static String NAME = "Windows";
390 
391         public final static String VARARGS_ATTRIBUTE_NAME = "abi/windows/varargs";
392 
393         public final static String CLASS_ATTRIBUTE_NAME = "abi/windows/class";
394 
395         public enum ArgumentClass {
396             INTEGER,
397             FLOAT,
398             POINTER;
399         }
400 
401         /**
402          * The {@code _Bool} native type.
403          */
404         public static final ValueLayout C_BOOL = MemoryLayouts.BITS_8_LE
405                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
406 
407         /**
408          * The {@code char} native type.
409          */
410         public static final ValueLayout C_CHAR = MemoryLayouts.BITS_8_LE
411                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
412 
413         /**
414          * The {@code short} native type.
415          */
416         public static final ValueLayout C_SHORT = MemoryLayouts.BITS_16_LE
417                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
418 
419         /**
420          * The {@code int} native type.
421          */
422         public static final ValueLayout C_INT = MemoryLayouts.BITS_32_LE
423                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
424 
425         /**
426          * The {@code long} native type.
427          */
428         public static final ValueLayout C_LONG = MemoryLayouts.BITS_32_LE
429                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
430 
431         /**
432          * The {@code long long} native type.
433          */
434         public static final ValueLayout C_LONGLONG = MemoryLayouts.BITS_64_LE
435                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
436 
437         /**
438          * The {@code float} native type.
439          */
440         public static final ValueLayout C_FLOAT = MemoryLayouts.BITS_32_LE
441                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.FLOAT);
442 
443         /**
444          * The {@code double} native type.
445          */
446         public static final ValueLayout C_DOUBLE = MemoryLayouts.BITS_64_LE
447                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.FLOAT);
448 
449         /**
450          * The {@code long double} native type.
451          */
452         public static final ValueLayout C_LONGDOUBLE = MemoryLayouts.BITS_64_LE
453                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.FLOAT);
454 
455         /**
456          * The {@code T*} native type.
457          */
458         public static final ValueLayout C_POINTER = MemoryLayouts.BITS_64_LE
459                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.POINTER);
460 
461         /**
462          * The {@code va_list} native type, as it is passed to a function.
463          */
464         public static final MemoryLayout C_VA_LIST = Win64.C_POINTER;
465 
466         public static ValueLayout asVarArg(ValueLayout l) {
467             return l.withAttribute(VARARGS_ATTRIBUTE_NAME, "true");
468         }
469     }
470 
471     /**
472      * This class defines layout constants modelling standard primitive types supported by the AArch64 ABI.
473      */
474     public static final class AArch64 {
475 
476         private AArch64() {
477             //just the one
478         }
479 
480         /**
481          * The name of the AArch64 linker ({@see ForeignLinker#name})
482          */
483         public final static String NAME = "AArch64";
484 
485         public static final String CLASS_ATTRIBUTE_NAME = "abi/aarch64/class";
486 
487         public enum ArgumentClass {
488             INTEGER,
489             VECTOR,
490             POINTER;
491         }
492 
493         /**
494          * The {@code _Bool} native type.
495          */
496         public static final ValueLayout C_BOOL = MemoryLayouts.BITS_8_LE
497                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
498 
499         /**
500          * The {@code char} native type.
501          */
502         public static final ValueLayout C_CHAR = MemoryLayouts.BITS_8_LE
503                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
504 
505         /**
506          * The {@code short} native type.
507          */
508         public static final ValueLayout C_SHORT = MemoryLayouts.BITS_16_LE
509                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
510 
511         /**
512          * The {@code int} native type.
513          */
514         public static final ValueLayout C_INT = MemoryLayouts.BITS_32_LE
515                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
516 
517         /**
518          * The {@code long} native type.
519          */
520         public static final ValueLayout C_LONG = MemoryLayouts.BITS_64_LE
521                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
522 
523         /**
524          * The {@code long long} native type.
525          */
526         public static final ValueLayout C_LONGLONG = MemoryLayouts.BITS_64_LE
527                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
528 
529         /**
530          * The {@code float} native type.
531          */
532         public static final ValueLayout C_FLOAT = MemoryLayouts.BITS_32_LE
533                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.VECTOR);
534 
535         /**
536          * The {@code double} native type.
537          */
538         public static final ValueLayout C_DOUBLE = MemoryLayouts.BITS_64_LE
539                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.VECTOR);
540 
541         /**
542          * The {@code long double} native type.
543          */
544         public static final ValueLayout C_LONGDOUBLE = MemoryLayout.ofValueBits(128, ByteOrder.LITTLE_ENDIAN)
545                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.VECTOR);
546 
547         /**
548          * The {@code T*} native type.
549          */
550         public static final ValueLayout C_POINTER = MemoryLayouts.BITS_64_LE
551                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.POINTER);
552     }
553 
554     private final static VarHandle byteArrHandle =
555             MemoryLayout.ofSequence(C_CHAR).varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
556 
557     /**
558      * Convert a Java string into a null-terminated C string, using the
559      * platform's default charset, storing the result into a new native memory segment.
560      * <p>
561      * This method always replaces malformed-input and unmappable-character
562      * sequences with this charset's default replacement byte array.  The
563      * {@link java.nio.charset.CharsetEncoder} class should be used when more
564      * control over the encoding process is required.
565      *
566      * @param str the Java string to be converted into a C string.
567      * @return a new native memory segment containing the converted C string.
568      * @throws NullPointerException if either {@code str == null}.
569      */
570     public static MemorySegment toCString(String str) {
571         Objects.requireNonNull(str);
572         return toCString(str.getBytes());
573     }
574 
575     /**
576      * Convert a Java string into a null-terminated C string, using the given {@linkplain java.nio.charset.Charset charset},
577      * storing the result into a new native memory segment.
578      * <p>
579      * This method always replaces malformed-input and unmappable-character
580      * sequences with this charset's default replacement byte array.  The
581      * {@link java.nio.charset.CharsetEncoder} class should be used when more
582      * control over the encoding process is required.
583      *
584      * @param str the Java string to be converted into a C string.
585      * @param charset The {@linkplain java.nio.charset.Charset} to be used to compute the contents of the C string.
586      * @return a new native memory segment containing the converted C string.
587      * @throws NullPointerException if either {@code str == null} or {@code charset == null}.
588      */
589     public static MemorySegment toCString(String str, Charset charset) {
590         Objects.requireNonNull(str);
591         Objects.requireNonNull(charset);
592         return toCString(str.getBytes(charset));
593     }
594 
595     /**
596      * Convert a Java string into a null-terminated C string, using the platform's default charset,
597      * storing the result into a native memory segment allocated using the provided scope.
598      * <p>
599      * This method always replaces malformed-input and unmappable-character
600      * sequences with this charset's default replacement byte array.  The
601      * {@link java.nio.charset.CharsetEncoder} class should be used when more
602      * control over the encoding process is required.
603      *
604      * @param str the Java string to be converted into a C string.
605      * @param scope the scope to be used for the native segment allocation.
606      * @return a new native memory segment containing the converted C string.
607      * @throws NullPointerException if either {@code str == null} or {@code scope == null}.
608      */
609     public static MemoryAddress toCString(String str, NativeScope scope) {
610         Objects.requireNonNull(str);
611         Objects.requireNonNull(scope);
612         return toCString(str.getBytes(), scope);
613     }
614 
615     /**
616      * Convert a Java string into a null-terminated C string, using the given {@linkplain java.nio.charset.Charset charset},
617      * storing the result into a new native memory segment native memory segment allocated using the provided scope.
618      * <p>
619      * This method always replaces malformed-input and unmappable-character
620      * sequences with this charset's default replacement byte array.  The
621      * {@link java.nio.charset.CharsetEncoder} class should be used when more
622      * control over the encoding process is required.
623      *
624      * @param str the Java string to be converted into a C string.
625      * @param charset The {@linkplain java.nio.charset.Charset} to be used to compute the contents of the C string.
626      * @param scope the scope to be used for the native segment allocation.
627      * @return a new native memory segment containing the converted C string.
628      * @throws NullPointerException if either {@code str == null}, {@code charset == null} or {@code scope == null}.
629      */
630     public static MemoryAddress toCString(String str, Charset charset, NativeScope scope) {
631         Objects.requireNonNull(str);
632         Objects.requireNonNull(charset);
633         Objects.requireNonNull(scope);
634         return toCString(str.getBytes(charset), scope);
635     }
636 
637     /**
638      * Convert a null-terminated C string stored at given address into a Java string.
639      * <p>
640      * This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
641      * the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
642      * restricted methods, and use safe and supported functionalities, where possible.
643      * @param addr the address at which the string is stored.
644      * @return a Java string with the contents of the null-terminated C string at given address.
645      * @throws NullPointerException if {@code addr == null}
646      * @throws IllegalArgumentException if the size of the native string is greater than {@code Integer.MAX_VALUE}.
647      */
648     public static String toJavaStringRestricted(MemoryAddress addr) {
649         Utils.checkRestrictedAccess("CSupport.toJavaStringRestricted");
650         return toJavaStringInternal(addr.rebase(AbstractMemorySegmentImpl.EVERYTHING));
651     }
652 
653     /**
654      * Convert a null-terminated C string stored at given address into a Java string.
655      * @param addr the address at which the string is stored.
656      * @return a Java string with the contents of the null-terminated C string at given address.
657      * @throws NullPointerException if {@code addr == null}
658      * @throws IllegalArgumentException if the size of the native string is greater than {@code Integer.MAX_VALUE}.
659      * @throws IllegalStateException if the size of the native string is greater than the size of the segment
660      * associated with {@code addr}, or if {@code addr} is associated with a segment that is </em>not alive<em>.
661      */
662     public static String toJavaString(MemoryAddress addr) {
663         return toJavaStringInternal(addr);
664     }
665 
666     private static String toJavaStringInternal(MemoryAddress addr) {
667         StringBuilder buf = new StringBuilder();
668         // iterate until overflow (String can only hold a byte[], whose length can be expressed as an int)
669         for (int offset = 0 ; offset >= 0 ; offset++) {
670             byte curr = (byte) byteArrHandle.get(addr, (long)offset);
671             if (curr == 0) {
672                 return buf.toString();
673             }
674             buf.append((char) curr);
675         }
676         throw new IllegalArgumentException("String too large");
677     }
678 
679     private static void copy(MemoryAddress addr, byte[] bytes) {
680         var heapSegment = MemorySegment.ofArray(bytes);
681         addr.segment().copyFrom(heapSegment);
682         byteArrHandle.set(addr, (long)bytes.length, (byte)0);
683     }
684 
685     private static MemorySegment toCString(byte[] bytes) {
686         MemorySegment segment = MemorySegment.allocateNative(bytes.length + 1, 1L);
687         MemoryAddress addr = segment.baseAddress();
688         copy(addr, bytes);
689         return segment;
690     }
691 
692     private static MemoryAddress toCString(byte[] bytes, NativeScope scope) {
693         MemoryAddress addr = scope.allocate(bytes.length + 1, 1L);
694         copy(addr, bytes);
695         return addr;
696     }
697 }