1 /* 2 * Copyright (c) 2019, 2023, 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.internal.foreign.layout; 27 28 import jdk.internal.foreign.Utils; 29 30 import java.lang.foreign.GroupLayout; 31 import java.lang.foreign.MemoryLayout; 32 import java.lang.foreign.SequenceLayout; 33 import java.lang.foreign.StructLayout; 34 import java.lang.foreign.UnionLayout; 35 import java.lang.foreign.ValueLayout; 36 import java.util.Objects; 37 import java.util.Optional; 38 39 public abstract sealed class AbstractLayout<L extends AbstractLayout<L> & MemoryLayout> 40 permits AbstractGroupLayout, PaddingLayoutImpl, SequenceLayoutImpl, ValueLayouts.AbstractValueLayout { 41 42 private final long byteSize; 43 private final long byteAlignment; 44 private final Optional<String> name; 45 46 AbstractLayout(long byteSize, long byteAlignment, Optional<String> name) { 47 this.byteSize = MemoryLayoutUtil.requireByteSizeValid(byteSize, true); 48 this.byteAlignment = requirePowerOfTwoAndGreaterOrEqualToOne(byteAlignment); 49 this.name = Objects.requireNonNull(name); 50 } 51 52 public final L withName(String name) { 53 return dup(byteAlignment(), Optional.of(name)); 54 } 55 56 public final L withoutName() { 57 return dup(byteAlignment(), Optional.empty()); 58 } 59 60 public final Optional<String> name() { 61 return name; 62 } 63 64 public L withByteAlignment(long byteAlignment) { 65 return dup(byteAlignment, name); 66 } 67 68 public final long byteAlignment() { 69 return byteAlignment; 70 } 71 72 public final long byteSize() { 73 return byteSize; 74 } 75 76 public boolean hasNaturalAlignment() { 77 return byteSize == byteAlignment; 78 } 79 80 // the following methods have to copy the same Javadoc as in MemoryLayout, or subclasses will just show 81 // the Object methods javadoc 82 83 /** 84 * {@return the hash code value for this layout} 85 */ 86 @Override 87 public int hashCode() { 88 return Objects.hash(name, byteSize, byteAlignment); 89 } 90 91 /** 92 * Compares the specified object with this layout for equality. Returns {@code true} if and only if the specified 93 * object is also a layout, and it is equal to this layout. Two layouts are considered equal if they are of 94 * the same kind, have the same size, name and alignment constraints. Furthermore, depending on the layout kind, additional 95 * conditions must be satisfied: 96 * <ul> 97 * <li>two value layouts are considered equal if they have the same {@linkplain ValueLayout#order() order}, 98 * and {@linkplain ValueLayout#carrier() carrier}</li> 99 * <li>two sequence layouts are considered equal if they have the same element count (see {@link SequenceLayout#elementCount()}), and 100 * if their element layouts (see {@link SequenceLayout#elementLayout()}) are also equal</li> 101 * <li>two group layouts are considered equal if they are of the same type (see {@link StructLayout}, 102 * {@link UnionLayout}) and if their member layouts (see {@link GroupLayout#memberLayouts()}) are also equal</li> 103 * </ul> 104 * 105 * @param other the object to be compared for equality with this layout. 106 * @return {@code true} if the specified object is equal to this layout. 107 */ 108 @Override 109 public boolean equals(Object other) { 110 return other instanceof AbstractLayout<?> otherLayout && 111 name.equals(otherLayout.name) && 112 byteSize == otherLayout.byteSize && 113 byteAlignment == otherLayout.byteAlignment; 114 } 115 116 /** 117 * {@return the string representation of this layout} 118 */ 119 @Override 120 public abstract String toString(); 121 122 abstract L dup(long byteAlignment, Optional<String> name); 123 124 String decorateLayoutString(String s) { 125 if (name().isPresent()) { 126 s = String.format("%s(%s)", s, name().get()); 127 } 128 if (!hasNaturalAlignment()) { 129 s = byteAlignment() + "%" + s; 130 } 131 return s; 132 } 133 134 private static long requirePowerOfTwoAndGreaterOrEqualToOne(long value) { 135 if (!Utils.isPowerOfTwo(value) || // value must be a power of two 136 value < 1) { // value must be greater or equal to 1 137 throw new IllegalArgumentException("Invalid alignment: " + value); 138 } 139 return value; 140 } 141 142 }