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 }