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 }