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.ConstantDescs;
  29 import java.lang.constant.DynamicConstantDesc;
  30 import java.lang.constant.MethodHandleDesc;
  31 import java.nio.ByteOrder;
  32 import java.util.Objects;
  33 import java.util.Optional;
  34 import java.util.OptionalLong;
  35 
  36 /**
  37  * 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
  38  * (either signed or unsigned) and <em>floating-point</em> types. Each value layout has a size and a byte order (see {@link ByteOrder}).
  39  *
  40  * <p>
  41  * This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>
  42  * class; use of identity-sensitive operations (including reference equality
  43  * ({@code ==}), identity hash code, or synchronization) on instances of
  44  * {@code ValueLayout} may have unpredictable results and should be avoided.
  45  * The {@code equals} method should be used for comparisons.
  46  *
  47  * @implSpec
  48  * This class is immutable and thread-safe.
  49  */
  50 public final class ValueLayout extends AbstractLayout implements MemoryLayout {
  51 
  52     private final ByteOrder order;
  53 
  54     ValueLayout(ByteOrder order, long size) {
  55         this(order, size, size, Optional.empty());
  56     }
  57 
  58     ValueLayout(ByteOrder order, long size, long alignment, Optional<String> name) {
  59         super(OptionalLong.of(size), alignment, name);
  60         this.order = order;
  61     }
  62 
  63     /**
  64      * Returns the value's byte order.
  65      *
  66      * @return the value's  byte order.
  67      */
  68     public ByteOrder order() {
  69         return order;
  70     }
  71 
  72     /**
  73      * Returns a new value layout with given byte order.
  74      *
  75      * @param order the desired byte order.
  76      * @return a new value layout with given byte order.
  77      */
  78     public ValueLayout withOrder(ByteOrder order) {
  79         return new ValueLayout(order, bitSize(), alignment, optName());
  80     }
  81 
  82     @Override
  83     public String toString() {
  84         return decorateLayoutString(String.format("%s%d",
  85                 order == ByteOrder.BIG_ENDIAN ? "B" : "b",
  86                 bitSize()));
  87     }
  88 
  89     @Override
  90     public boolean equals(Object other) {
  91         if (this == other) {
  92             return true;
  93         }
  94         if (!super.equals(other)) {
  95             return false;
  96         }
  97         if (!(other instanceof ValueLayout)) {
  98             return false;
  99         }
 100         ValueLayout v = (ValueLayout)other;
 101         return order.equals(v.order) &&
 102             bitSize() == v.bitSize() &&
 103             alignment == v.alignment;
 104     }
 105 
 106     @Override
 107     public int hashCode() {
 108         return Objects.hash(super.hashCode(), order, bitSize(), alignment);
 109     }
 110 
 111     @Override
 112     ValueLayout dup(long alignment, Optional<String> name) {
 113         return new ValueLayout(order, bitSize(), alignment, name);
 114     }
 115 
 116     @Override
 117     public Optional<DynamicConstantDesc<ValueLayout>> describeConstable() {
 118         return Optional.of(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value",
 119                 CD_VALUE_LAYOUT, MH_VALUE, bitSize(), order == ByteOrder.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN));
 120     }
 121 
 122     //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout
 123     //but that causes issues with javadoc, see JDK-8224052
 124 
 125     /**
 126      * {@inheritDoc}
 127      */
 128     @Override
 129     public ValueLayout withName(String name) {
 130         return (ValueLayout)super.withName(name);
 131     }
 132 
 133     /**
 134      * {@inheritDoc}
 135      */
 136     @Override
 137     public ValueLayout withBitAlignment(long alignmentBits) {
 138         return (ValueLayout)super.withBitAlignment(alignmentBits);
 139     }
 140 }