1 /*
  2  *  Copyright (c) 2019, 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 java.lang.constant.Constable;
 29 import java.lang.constant.ConstantDescs;
 30 import java.lang.constant.DynamicConstantDesc;
 31 import java.nio.ByteOrder;
 32 import java.util.Map;
 33 import java.util.Objects;
 34 import java.util.Optional;
 35 import java.util.OptionalLong;
 36 
 37 /**
 38  * A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as <em>integral</em> types
 39  * (either signed or unsigned) and <em>floating-point</em> types. Each value layout has a size and a byte order (see {@link ByteOrder}).
 40  *
 41  * <p>
 42  * This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>
 43  * class; programmers should treat instances that are
 44  * {@linkplain #equals(Object) equal} as interchangeable and should not
 45  * use instances for synchronization, or unpredictable behavior may
 46  * occur. For example, in a future release, synchronization may fail.
 47  * The {@code equals} method should be used for comparisons.
 48  *
 49  * <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
 50  * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
 51  *
 52  * @implSpec
 53  * This class is immutable and thread-safe.
 54  */
 55 public final class ValueLayout extends AbstractLayout implements MemoryLayout {
 56 
 57     private final ByteOrder order;
 58 
 59     ValueLayout(ByteOrder order, long size) {
 60         this(order, size, size, Map.of());
 61     }
 62 
 63     ValueLayout(ByteOrder order, long size, long alignment, Map<String, Constable> attributes) {
 64         super(OptionalLong.of(size), alignment, attributes);
 65         this.order = order;
 66     }
 67 
 68     /**
 69      * Returns the value's byte order.
 70      *
 71      * @return the value's  byte order.
 72      */
 73     public ByteOrder order() {
 74         return order;
 75     }
 76 
 77     /**
 78      * Returns a new value layout with given byte order.
 79      *
 80      * @param order the desired byte order.
 81      * @return a new value layout with given byte order.
 82      */
 83     public ValueLayout withOrder(ByteOrder order) {
 84         return new ValueLayout(Objects.requireNonNull(order), bitSize(), alignment, attributes);
 85     }
 86 
 87     @Override
 88     public String toString() {
 89         return decorateLayoutString(String.format("%s%d",
 90                 order == ByteOrder.BIG_ENDIAN ? "B" : "b",
 91                 bitSize()));
 92     }
 93 
 94     @Override
 95     public boolean equals(Object other) {
 96         if (this == other) {
 97             return true;
 98         }
 99         if (!super.equals(other)) {
100             return false;
101         }
102         if (!(other instanceof ValueLayout)) {
103             return false;
104         }
105         ValueLayout v = (ValueLayout)other;
106         return order.equals(v.order) &&
107             bitSize() == v.bitSize() &&
108             alignment == v.alignment;
109     }
110 
111     @Override
112     public int hashCode() {
113         return Objects.hash(super.hashCode(), order, bitSize(), alignment);
114     }
115 
116     @Override
117     ValueLayout dup(long alignment, Map<String, Constable> attributes) {
118         return new ValueLayout(order, bitSize(), alignment, attributes);
119     }
120 
121     @Override
122     public Optional<DynamicConstantDesc<ValueLayout>> describeConstable() {
123         return Optional.of(decorateLayoutConstant(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value",
124                 CD_VALUE_LAYOUT, MH_VALUE, bitSize(), order == ByteOrder.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN)));
125     }
126 
127     //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout
128     //but that causes issues with javadoc, see JDK-8224052
129 
130     /**
131      * {@inheritDoc}
132      */
133     @Override
134     public ValueLayout withName(String name) {
135         return (ValueLayout)super.withName(name);
136     }
137 
138     /**
139      * {@inheritDoc}
140      */
141     @Override
142     public ValueLayout withBitAlignment(long alignmentBits) {
143         return (ValueLayout)super.withBitAlignment(alignmentBits);
144     }
145 
146     /**
147      * {@inheritDoc}
148      */
149     @Override
150     public ValueLayout withAttribute(String name, Constable value) {
151         return (ValueLayout)super.withAttribute(name, value);
152     }
153 }