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 }