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          * Note that when there are no arguments added to the created va list,
177          * this method will return the same as {@linkplain #empty()}.
178          *
179          * @param actions a consumer for a builder (see {@link Builder}) which can be used to specify the contents
180          *                of the underlying C {@code va_list}.
181          * @return a new {@code VaList} instance backed by a fresh C {@code va_list}.
182          */
183         static VaList make(Consumer<VaList.Builder> actions) {
184             return SharedUtils.newVaList(actions);
185         }
186 
187         /**
188          * Returns an empty C {@code va_list} constant.
189          *
190          * The returned {@code VaList} can not be closed.
191          *
192          * @return a {@code VaList} modelling an empty C {@code va_list}.
193          */
194         static VaList empty() {
195             return SharedUtils.emptyVaList();
196         }
197 
198         /**
199          * A builder interface used to construct a C {@code va_list}.
200          */
201         interface Builder {
202 
203             /**
204              * Adds a native value represented as an {@code int} to the C {@code va_list} being constructed.
205              *
206              * @param layout the native layout of the value.
207              * @param value the value, represented as an {@code int}.
208              * @return this builder.
209              */
210             Builder vargFromInt(MemoryLayout layout, int value);
211 
212             /**
213              * Adds a native value represented as a {@code long} to the C {@code va_list} being constructed.
214              *
215              * @param layout the native layout of the value.
216              * @param value the value, represented as a {@code long}.
217              * @return this builder.
218              */
219             Builder vargFromLong(MemoryLayout layout, long value);
220 
221             /**
222              * Adds a native value represented as a {@code double} to the C {@code va_list} being constructed.
223              *
224              * @param layout the native layout of the value.
225              * @param value the value, represented as a {@code double}.
226              * @return this builder.
227              */
228             Builder vargFromDouble(MemoryLayout layout, double value);
229 
230             /**
231              * Adds a native value represented as a {@code MemoryAddress} to the C {@code va_list} being constructed.
232              *
233              * @param layout the native layout of the value.
234              * @param value the value, represented as a {@code MemoryAddress}.
235              * @return this builder.
236              */
237             Builder vargFromAddress(MemoryLayout layout, MemoryAddress value);
238 
239             /**
240              * Adds a native value represented as a {@code MemorySegment} to the C {@code va_list} being constructed.
241              *
242              * @param layout the native layout of the value.
243              * @param value the value, represented as a {@code MemorySegment}.
244              * @return this builder.
245              */
246             Builder vargFromSegment(MemoryLayout layout, MemorySegment value);
247         }
248     }
249 
250     /**
251      * The {@code _Bool} native type.
252      */
253     public static final ValueLayout C_BOOL = Utils.pick(SysV.C_BOOL, Win64.C_BOOL, AArch64.C_BOOL);
254     /**
255      * The {@code char} native type.
256      */
257     public static final ValueLayout C_CHAR = Utils.pick(SysV.C_CHAR, Win64.C_CHAR, AArch64.C_CHAR);
258     /**
259      * The {@code short} native type.
260      */
261     public static final ValueLayout C_SHORT = Utils.pick(SysV.C_SHORT, Win64.C_SHORT, AArch64.C_SHORT);
262     /**
263      * The {@code int} native type.
264      */
265     public static final ValueLayout C_INT = Utils.pick(SysV.C_INT, Win64.C_INT, AArch64.C_INT);
266     /**
267      * The {@code long} native type.
268      */
269     public static final ValueLayout C_LONG = Utils.pick(SysV.C_LONG, Win64.C_LONG, AArch64.C_LONG);
270     /**
271      * The {@code long long} native type.
272      */
273     public static final ValueLayout C_LONGLONG = Utils.pick(SysV.C_LONGLONG, Win64.C_LONGLONG, AArch64.C_LONGLONG);
274     /**
275      * The {@code float} native type.
276      */
277     public static final ValueLayout C_FLOAT = Utils.pick(SysV.C_FLOAT, Win64.C_FLOAT, AArch64.C_FLOAT);
278     /**
279      * The {@code double} native type.
280      */
281     public static final ValueLayout C_DOUBLE = Utils.pick(SysV.C_DOUBLE, Win64.C_DOUBLE, AArch64.C_DOUBLE);
282     /**
283      * The {@code long double} native type.
284      */
285     public static final ValueLayout C_LONGDOUBLE = Utils.pick(SysV.C_LONGDOUBLE, Win64.C_LONGDOUBLE, AArch64.C_LONGDOUBLE);
286     /**
287      * The {@code T*} native type.
288      */
289     public static final ValueLayout C_POINTER = Utils.pick(SysV.C_POINTER, Win64.C_POINTER, AArch64.C_POINTER);
290 
291     /**
292      * The {@code va_list} native type.
293      */
294     public static final MemoryLayout C_VA_LIST = Utils.pick(SysV.C_VA_LIST, Win64.C_VA_LIST, null);
295 
296     /**
297      * This class defines layout constants modelling standard primitive types supported by the x64 SystemV ABI.
298      */
299     public static final class SysV {
300         private SysV() {
301             //just the one
302         }
303 
304         /**
305          * The name of the SysV linker ({@see ForeignLinker#name})
306          */
307         public static final String NAME = "SysV";
308 
309         public final static String CLASS_ATTRIBUTE_NAME = "abi/sysv/class";
310 
311         public enum ArgumentClass {
312             INTEGER,
313             SSE,
314             X87,
315             COMPLEX_87,
316             POINTER;
317         }
318 
319         /**
320          * The {@code _Bool} native type.
321          */
322         public static final ValueLayout C_BOOL = MemoryLayouts.BITS_8_LE
323                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
324 
325         /**
326          * The {@code char} native type.
327          */
328         public static final ValueLayout C_CHAR = MemoryLayouts.BITS_8_LE
329                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
330 
331         /**
332          * The {@code short} native type.
333          */
334         public static final ValueLayout C_SHORT = MemoryLayouts.BITS_16_LE
335                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
336 
337         /**
338          * The {@code int} native type.
339          */
340         public static final ValueLayout C_INT = MemoryLayouts.BITS_32_LE
341                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
342 
343         /**
344          * The {@code long} native type.
345          */
346         public static final ValueLayout C_LONG = MemoryLayouts.BITS_64_LE
347                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
348 
349         /**
350          * The {@code long long} native type.
351          */
352         public static final ValueLayout C_LONGLONG = MemoryLayouts.BITS_64_LE
353                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
354 
355         /**
356          * The {@code float} native type.
357          */
358         public static final ValueLayout C_FLOAT = MemoryLayouts.BITS_32_LE
359                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.SSE);
360 
361         /**
362          * The {@code double} native type.
363          */
364         public static final ValueLayout C_DOUBLE = MemoryLayouts.BITS_64_LE
365                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.SSE);
366 
367         /**
368          * The {@code long double} native type.
369          */
370         public static final ValueLayout C_LONGDOUBLE = MemoryLayout.ofValueBits(128, ByteOrder.LITTLE_ENDIAN)
371                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.X87);
372 
373         /**
374          * The {@code complex long double} native type.
375          */
376         public static final GroupLayout C_COMPLEX_LONGDOUBLE = MemoryLayout.ofStruct(C_LONGDOUBLE, C_LONGDOUBLE)
377                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.COMPLEX_87);
378 
379         /**
380          * The {@code T*} native type.
381          */
382         public static final ValueLayout C_POINTER = MemoryLayouts.BITS_64_LE
383                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.POINTER);
384 
385         /**
386          * The {@code va_list} native type, as it is passed to a function.
387          */
388         public static final MemoryLayout C_VA_LIST = SysV.C_POINTER;
389     }
390 
391     /**
392      * This class defines layout constants modelling standard primitive types supported by the x64 Windows ABI.
393      */
394     public static final class Win64 {
395 
396         private Win64() {
397             //just the one
398         }
399 
400         /**
401          * The name of the Windows linker ({@see ForeignLinker#name})
402          */
403         public final static String NAME = "Windows";
404 
405         public final static String VARARGS_ATTRIBUTE_NAME = "abi/windows/varargs";
406 
407         public final static String CLASS_ATTRIBUTE_NAME = "abi/windows/class";
408 
409         public enum ArgumentClass {
410             INTEGER,
411             FLOAT,
412             POINTER;
413         }
414 
415         /**
416          * The {@code _Bool} native type.
417          */
418         public static final ValueLayout C_BOOL = MemoryLayouts.BITS_8_LE
419                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
420 
421         /**
422          * The {@code char} native type.
423          */
424         public static final ValueLayout C_CHAR = MemoryLayouts.BITS_8_LE
425                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
426 
427         /**
428          * The {@code short} native type.
429          */
430         public static final ValueLayout C_SHORT = MemoryLayouts.BITS_16_LE
431                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
432 
433         /**
434          * The {@code int} native type.
435          */
436         public static final ValueLayout C_INT = MemoryLayouts.BITS_32_LE
437                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
438 
439         /**
440          * The {@code long} native type.
441          */
442         public static final ValueLayout C_LONG = MemoryLayouts.BITS_32_LE
443                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
444 
445         /**
446          * The {@code long long} native type.
447          */
448         public static final ValueLayout C_LONGLONG = MemoryLayouts.BITS_64_LE
449                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
450 
451         /**
452          * The {@code float} native type.
453          */
454         public static final ValueLayout C_FLOAT = MemoryLayouts.BITS_32_LE
455                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.FLOAT);
456 
457         /**
458          * The {@code double} native type.
459          */
460         public static final ValueLayout C_DOUBLE = MemoryLayouts.BITS_64_LE
461                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.FLOAT);
462 
463         /**
464          * The {@code long double} native type.
465          */
466         public static final ValueLayout C_LONGDOUBLE = MemoryLayouts.BITS_64_LE
467                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.FLOAT);
468 
469         /**
470          * The {@code T*} native type.
471          */
472         public static final ValueLayout C_POINTER = MemoryLayouts.BITS_64_LE
473                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.POINTER);
474 
475         /**
476          * The {@code va_list} native type, as it is passed to a function.
477          */
478         public static final MemoryLayout C_VA_LIST = Win64.C_POINTER;
479 
480         public static ValueLayout asVarArg(ValueLayout l) {
481             return l.withAttribute(VARARGS_ATTRIBUTE_NAME, "true");
482         }
483     }
484 
485     /**
486      * This class defines layout constants modelling standard primitive types supported by the AArch64 ABI.
487      */
488     public static final class AArch64 {
489 
490         private AArch64() {
491             //just the one
492         }
493 
494         /**
495          * The name of the AArch64 linker ({@see ForeignLinker#name})
496          */
497         public final static String NAME = "AArch64";
498 
499         public static final String CLASS_ATTRIBUTE_NAME = "abi/aarch64/class";
500 
501         public enum ArgumentClass {
502             INTEGER,
503             VECTOR,
504             POINTER;
505         }
506 
507         /**
508          * The {@code _Bool} native type.
509          */
510         public static final ValueLayout C_BOOL = MemoryLayouts.BITS_8_LE
511                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
512 
513         /**
514          * The {@code char} native type.
515          */
516         public static final ValueLayout C_CHAR = MemoryLayouts.BITS_8_LE
517                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
518 
519         /**
520          * The {@code short} native type.
521          */
522         public static final ValueLayout C_SHORT = MemoryLayouts.BITS_16_LE
523                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
524 
525         /**
526          * The {@code int} native type.
527          */
528         public static final ValueLayout C_INT = MemoryLayouts.BITS_32_LE
529                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
530 
531         /**
532          * The {@code long} native type.
533          */
534         public static final ValueLayout C_LONG = MemoryLayouts.BITS_64_LE
535                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
536 
537         /**
538          * The {@code long long} native type.
539          */
540         public static final ValueLayout C_LONGLONG = MemoryLayouts.BITS_64_LE
541                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.INTEGER);
542 
543         /**
544          * The {@code float} native type.
545          */
546         public static final ValueLayout C_FLOAT = MemoryLayouts.BITS_32_LE
547                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.VECTOR);
548 
549         /**
550          * The {@code double} native type.
551          */
552         public static final ValueLayout C_DOUBLE = MemoryLayouts.BITS_64_LE
553                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.VECTOR);
554 
555         /**
556          * The {@code long double} native type.
557          */
558         public static final ValueLayout C_LONGDOUBLE = MemoryLayout.ofValueBits(128, ByteOrder.LITTLE_ENDIAN)
559                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.VECTOR);
560 
561         /**
562          * The {@code T*} native type.
563          */
564         public static final ValueLayout C_POINTER = MemoryLayouts.BITS_64_LE
565                 .withAttribute(CLASS_ATTRIBUTE_NAME, ArgumentClass.POINTER);
566     }
567 
568     private final static VarHandle byteArrHandle =
569             MemoryLayout.ofSequence(C_CHAR).varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
570 
571     /**
572      * Convert a Java string into a null-terminated C string, using the
573      * platform's default charset, storing the result into a new native memory segment.
574      * <p>
575      * This method always replaces malformed-input and unmappable-character
576      * sequences with this charset's default replacement byte array.  The
577      * {@link java.nio.charset.CharsetEncoder} class should be used when more
578      * control over the encoding process is required.
579      *
580      * @param str the Java string to be converted into a C string.
581      * @return a new native memory segment containing the converted C string.
582      * @throws NullPointerException if either {@code str == null}.
583      */
584     public static MemorySegment toCString(String str) {
585         Objects.requireNonNull(str);
586         return toCString(str.getBytes());
587     }
588 
589     /**
590      * Convert a Java string into a null-terminated C string, using the given {@linkplain java.nio.charset.Charset charset},
591      * storing the result into a new native memory segment.
592      * <p>
593      * This method always replaces malformed-input and unmappable-character
594      * sequences with this charset's default replacement byte array.  The
595      * {@link java.nio.charset.CharsetEncoder} class should be used when more
596      * control over the encoding process is required.
597      *
598      * @param str the Java string to be converted into a C string.
599      * @param charset The {@linkplain java.nio.charset.Charset} to be used to compute the contents of the C string.
600      * @return a new native memory segment containing the converted C string.
601      * @throws NullPointerException if either {@code str == null} or {@code charset == null}.
602      */
603     public static MemorySegment toCString(String str, Charset charset) {
604         Objects.requireNonNull(str);
605         Objects.requireNonNull(charset);
606         return toCString(str.getBytes(charset));
607     }
608 
609     /**
610      * Convert a Java string into a null-terminated C string, using the platform's default charset,
611      * storing the result into a native memory segment allocated using the provided scope.
612      * <p>
613      * This method always replaces malformed-input and unmappable-character
614      * sequences with this charset's default replacement byte array.  The
615      * {@link java.nio.charset.CharsetEncoder} class should be used when more
616      * control over the encoding process is required.
617      *
618      * @param str the Java string to be converted into a C string.
619      * @param scope the scope to be used for the native segment allocation.
620      * @return a new native memory segment containing the converted C string.
621      * @throws NullPointerException if either {@code str == null} or {@code scope == null}.
622      */
623     public static MemoryAddress toCString(String str, NativeScope scope) {
624         Objects.requireNonNull(str);
625         Objects.requireNonNull(scope);
626         return toCString(str.getBytes(), scope);
627     }
628 
629     /**
630      * Convert a Java string into a null-terminated C string, using the given {@linkplain java.nio.charset.Charset charset},
631      * storing the result into a new native memory segment native memory segment allocated using the provided scope.
632      * <p>
633      * This method always replaces malformed-input and unmappable-character
634      * sequences with this charset's default replacement byte array.  The
635      * {@link java.nio.charset.CharsetEncoder} class should be used when more
636      * control over the encoding process is required.
637      *
638      * @param str the Java string to be converted into a C string.
639      * @param charset The {@linkplain java.nio.charset.Charset} to be used to compute the contents of the C string.
640      * @param scope the scope to be used for the native segment allocation.
641      * @return a new native memory segment containing the converted C string.
642      * @throws NullPointerException if either {@code str == null}, {@code charset == null} or {@code scope == null}.
643      */
644     public static MemoryAddress toCString(String str, Charset charset, NativeScope scope) {
645         Objects.requireNonNull(str);
646         Objects.requireNonNull(charset);
647         Objects.requireNonNull(scope);
648         return toCString(str.getBytes(charset), scope);
649     }
650 
651     /**
652      * Convert a null-terminated C string stored at given address into a Java string.
653      * <p>
654      * This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
655      * the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
656      * restricted methods, and use safe and supported functionalities, where possible.
657      * @param addr the address at which the string is stored.
658      * @return a Java string with the contents of the null-terminated C string at given address.
659      * @throws NullPointerException if {@code addr == null}
660      * @throws IllegalArgumentException if the size of the native string is greater than {@code Integer.MAX_VALUE}.
661      */
662     public static String toJavaStringRestricted(MemoryAddress addr) {
663         Utils.checkRestrictedAccess("CSupport.toJavaStringRestricted");
664         return toJavaStringInternal(addr.rebase(AbstractMemorySegmentImpl.EVERYTHING));
665     }
666 
667     /**
668      * Convert a null-terminated C string stored at given address into a Java string.
669      * @param addr the address at which the string is stored.
670      * @return a Java string with the contents of the null-terminated C string at given address.
671      * @throws NullPointerException if {@code addr == null}
672      * @throws IllegalArgumentException if the size of the native string is greater than {@code Integer.MAX_VALUE}.
673      * @throws IllegalStateException if the size of the native string is greater than the size of the segment
674      * associated with {@code addr}, or if {@code addr} is associated with a segment that is </em>not alive<em>.
675      */
676     public static String toJavaString(MemoryAddress addr) {
677         return toJavaStringInternal(addr);
678     }
679 
680     private static String toJavaStringInternal(MemoryAddress addr) {
681         StringBuilder buf = new StringBuilder();
682         // iterate until overflow (String can only hold a byte[], whose length can be expressed as an int)
683         for (int offset = 0 ; offset >= 0 ; offset++) {
684             byte curr = (byte) byteArrHandle.get(addr, (long)offset);
685             if (curr == 0) {
686                 return buf.toString();
687             }
688             buf.append((char) curr);
689         }
690         throw new IllegalArgumentException("String too large");
691     }
692 
693     private static void copy(MemoryAddress addr, byte[] bytes) {
694         var heapSegment = MemorySegment.ofArray(bytes);
695         addr.segment().copyFrom(heapSegment);
696         byteArrHandle.set(addr, (long)bytes.length, (byte)0);
697     }
698 
699     private static MemorySegment toCString(byte[] bytes) {
700         MemorySegment segment = MemorySegment.allocateNative(bytes.length + 1, 1L);
701         MemoryAddress addr = segment.baseAddress();
702         copy(addr, bytes);
703         return segment;
704     }
705 
706     private static MemoryAddress toCString(byte[] bytes, NativeScope scope) {
707         MemoryAddress addr = scope.allocate(bytes.length + 1, 1L);
708         copy(addr, bytes);
709         return addr;
710     }
711 }