1 /*
2 * Copyright (c) 2000, 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
1852
1853 /**
1854 * Modifies this buffer's byte order.
1855 *
1856 * @param bo
1857 * The new byte order,
1858 * either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
1859 * or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}
1860 *
1861 * @return This buffer
1862 */
1863 public final $Type$Buffer order(ByteOrder bo) {
1864 bigEndian = (bo == ByteOrder.BIG_ENDIAN);
1865 nativeByteOrder =
1866 (bigEndian == (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN));
1867 return this;
1868 }
1869
1870 /**
1871 * Returns the memory address, pointing to the byte at the given index,
1872 * modulus the given unit size.
1873 *
1874 * <p> A return value greater than zero indicates the address of the byte at
1875 * the index is misaligned for the unit size, and the value's quantity
1876 * indicates how much the index should be rounded up or down to locate a
1877 * byte at an aligned address. Otherwise, a value of {@code 0} indicates
1878 * that the address of the byte at the index is aligned for the unit size.
1879 *
1880 * @apiNote
1881 * This method may be utilized to determine if unit size bytes from an
1882 * index can be accessed atomically, if supported by the native platform.
1883 *
1884 * @implNote
1885 * This implementation throws {@code UnsupportedOperationException} for
1886 * non-direct buffers when the given unit size is greater then {@code 8}.
1887 *
1888 * @param index
1889 * The index to query for alignment offset, must be non-negative, no
1890 * upper bounds check is performed
1891 *
1892 * @param unitSize
1893 * The unit size in bytes, must be a power of {@code 2}
1894 *
1895 * @return The indexed byte's memory address modulus the unit size
1896 *
1897 * @throws IllegalArgumentException
1898 * If the index is negative or the unit size is not a power of
1899 * {@code 2}
1900 *
1901 * @throws UnsupportedOperationException
1902 * If the native platform does not guarantee stable alignment offset
1903 * values for the given unit size when managing the memory regions
1904 * of buffers of the same kind as this buffer (direct or
1905 * non-direct). For example, if garbage collection would result
1906 * in the moving of a memory region covered by a non-direct buffer
1907 * from one location to another and both locations have different
1908 * alignment characteristics.
1909 *
1910 * @see #alignedSlice(int)
1911 * @since 9
1912 */
1913 public final int alignmentOffset(int index, int unitSize) {
1914 if (index < 0)
1915 throw new IllegalArgumentException("Index less than zero: " + index);
1916 if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
1917 throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
1918 if (unitSize > 8 && !isDirect())
1919 throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
1920
1921 return (int) ((address + index) % unitSize);
1922 }
1923
1924 /**
1925 * Creates a new byte buffer whose content is a shared and aligned
1926 * subsequence of this buffer's content.
1927 *
1928 * <p> The content of the new buffer will start at this buffer's current
1929 * position rounded up to the index of the nearest aligned byte for the
1930 * given unit size, and end at this buffer's limit rounded down to the index
1931 * of the nearest aligned byte for the given unit size.
1932 * If rounding results in out-of-bound values then the new buffer's capacity
1933 * and limit will be zero. If rounding is within bounds the following
1934 * expressions will be true for a new buffer {@code nb} and unit size
1935 * {@code unitSize}:
1936 * <pre>{@code
1937 * nb.alignmentOffset(0, unitSize) == 0
1938 * nb.alignmentOffset(nb.limit(), unitSize) == 0
1939 * }</pre>
1940 *
1941 * <p> Changes to this buffer's content will be visible in the new
|
1 /*
2 * Copyright (c) 2000, 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
1852
1853 /**
1854 * Modifies this buffer's byte order.
1855 *
1856 * @param bo
1857 * The new byte order,
1858 * either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
1859 * or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}
1860 *
1861 * @return This buffer
1862 */
1863 public final $Type$Buffer order(ByteOrder bo) {
1864 bigEndian = (bo == ByteOrder.BIG_ENDIAN);
1865 nativeByteOrder =
1866 (bigEndian == (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN));
1867 return this;
1868 }
1869
1870 /**
1871 * Returns the memory address, pointing to the byte at the given index,
1872 * modulo the given unit size.
1873 *
1874 * <p> The return value is non-negative, with {@code 0} indicating that the
1875 * address of the byte at the index is aligned for the unit size, and a
1876 * positive value that the address is misaligned for the unit size. If the
1877 * address of the byte at the index is misaligned, the return value
1878 * represents how much the index should be adjusted to locate a byte at an
1879 * aligned address. Specifically, the index should either be decremented by
1880 * the return value, or incremented by the unit size minus the return value.
1881 * Therefore given
1882 * <blockquote><pre>
1883 * int value = alignmentOffset(index, unitSize)</pre></blockquote>
1884 * then the identities
1885 * <blockquote><pre>
1886 * alignmentOffset(index - value, unitSize) == 0</pre></blockquote>
1887 * and
1888 * <blockquote><pre>
1889 * alignmentOffset(index + (unitSize - value), unitSize) == 0</pre></blockquote>
1890 * must hold.
1891 *
1892 * @apiNote
1893 * This method may be utilized to determine if unit size bytes from an
1894 * index can be accessed atomically, if supported by the native platform.
1895 *
1896 * @implNote
1897 * This implementation throws {@code UnsupportedOperationException} for
1898 * non-direct buffers when the given unit size is greater then {@code 8}.
1899 *
1900 * @param index
1901 * The index to query for alignment offset, must be non-negative, no
1902 * upper bounds check is performed
1903 *
1904 * @param unitSize
1905 * The unit size in bytes, must be a power of {@code 2}
1906 *
1907 * @return The indexed byte's memory address modulo the unit size
1908 *
1909 * @throws IllegalArgumentException
1910 * If the index is negative or the unit size is not a power of
1911 * {@code 2}
1912 *
1913 * @throws UnsupportedOperationException
1914 * If the native platform does not guarantee stable alignment offset
1915 * values for the given unit size when managing the memory regions
1916 * of buffers of the same kind as this buffer (direct or
1917 * non-direct). For example, if garbage collection would result
1918 * in the moving of a memory region covered by a non-direct buffer
1919 * from one location to another and both locations have different
1920 * alignment characteristics.
1921 *
1922 * @see #alignedSlice(int)
1923 * @since 9
1924 */
1925 public final int alignmentOffset(int index, int unitSize) {
1926 if (index < 0)
1927 throw new IllegalArgumentException("Index less than zero: " + index);
1928 if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
1929 throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
1930 if (unitSize > 8 && !isDirect())
1931 throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
1932
1933 return (int) ((address + index) & (unitSize - 1));
1934 }
1935
1936 /**
1937 * Creates a new byte buffer whose content is a shared and aligned
1938 * subsequence of this buffer's content.
1939 *
1940 * <p> The content of the new buffer will start at this buffer's current
1941 * position rounded up to the index of the nearest aligned byte for the
1942 * given unit size, and end at this buffer's limit rounded down to the index
1943 * of the nearest aligned byte for the given unit size.
1944 * If rounding results in out-of-bound values then the new buffer's capacity
1945 * and limit will be zero. If rounding is within bounds the following
1946 * expressions will be true for a new buffer {@code nb} and unit size
1947 * {@code unitSize}:
1948 * <pre>{@code
1949 * nb.alignmentOffset(0, unitSize) == 0
1950 * nb.alignmentOffset(nb.limit(), unitSize) == 0
1951 * }</pre>
1952 *
1953 * <p> Changes to this buffer's content will be visible in the new
|