/*
 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.lang;

Helper for string concatenation. These methods are mostly looked up with private lookups from StringConcatFactory, and used in MethodHandle combinators there.
/** * Helper for string concatenation. These methods are mostly looked up with private lookups * from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle} * combinators there. */
final class StringConcatHelper { private StringConcatHelper() { // no instantiation }
Check for overflow, throw exception on overflow.
Params:
  • lengthCoder – String length and coder
Returns:lengthCoder
/** * Check for overflow, throw exception on overflow. * @param lengthCoder String length and coder * @return lengthCoder */
private static long checkOverflow(long lengthCoder) { if ((int)lengthCoder >= 0) { return lengthCoder; } throw new OutOfMemoryError("Overflow: String length out of range"); }
Mix value length and coder into current length and coder.
Params:
  • current – current length
  • value – value to mix in
Returns:new length and coder
/** * Mix value length and coder into current length and coder. * @param current current length * @param value value to mix in * @return new length and coder */
static long mix(long current, boolean value) { return checkOverflow(current + (value ? 4 : 5)); }
Mix value length and coder into current length and coder.
Params:
  • current – current length
  • value – value to mix in
Returns:new length and coder
/** * Mix value length and coder into current length and coder. * @param current current length * @param value value to mix in * @return new length and coder */
static long mix(long current, byte value) { return mix(current, (int)value); }
Mix value length and coder into current length and coder.
Params:
  • current – current length
  • value – value to mix in
Returns:new length and coder
/** * Mix value length and coder into current length and coder. * @param current current length * @param value value to mix in * @return new length and coder */
static long mix(long current, char value) { return checkOverflow(current + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16); }
Mix value length and coder into current length and coder.
Params:
  • current – current length
  • value – value to mix in
Returns:new length and coder
/** * Mix value length and coder into current length and coder. * @param current current length * @param value value to mix in * @return new length and coder */
static long mix(long current, short value) { return mix(current, (int)value); }
Mix value length and coder into current length and coder.
Params:
  • current – current length
  • value – value to mix in
Returns:new length and coder
/** * Mix value length and coder into current length and coder. * @param current current length * @param value value to mix in * @return new length and coder */
static long mix(long current, int value) { return checkOverflow(current + Integer.stringSize(value)); }
Mix value length and coder into current length and coder.
Params:
  • current – current length
  • value – value to mix in
Returns:new length and coder
/** * Mix value length and coder into current length and coder. * @param current current length * @param value value to mix in * @return new length and coder */
static long mix(long current, long value) { return checkOverflow(current + Long.stringSize(value)); }
Mix value length and coder into current length and coder.
Params:
  • current – current length
  • value – value to mix in
Returns:new length and coder
/** * Mix value length and coder into current length and coder. * @param current current length * @param value value to mix in * @return new length and coder */
static long mix(long current, String value) { current += value.length(); if (value.coder() == String.UTF16) { current |= UTF16; } return checkOverflow(current); }
Prepends the stringly representation of boolean value into buffer, given the coder and final index. Index is measured in chars, not in bytes!
Params:
  • indexCoder – final char index in the buffer, along with coder packed into higher bits.
  • buf – buffer to append to
  • value – boolean value to encode
Returns: updated index (coder value retained)
/** * Prepends the stringly representation of boolean value into buffer, * given the coder and final index. Index is measured in chars, not in bytes! * * @param indexCoder final char index in the buffer, along with coder packed * into higher bits. * @param buf buffer to append to * @param value boolean value to encode * @return updated index (coder value retained) */
static long prepend(long indexCoder, byte[] buf, boolean value) { int index = (int)indexCoder; if (indexCoder < UTF16) { if (value) { buf[--index] = 'e'; buf[--index] = 'u'; buf[--index] = 'r'; buf[--index] = 't'; } else { buf[--index] = 'e'; buf[--index] = 's'; buf[--index] = 'l'; buf[--index] = 'a'; buf[--index] = 'f'; } return index; } else { if (value) { StringUTF16.putChar(buf, --index, 'e'); StringUTF16.putChar(buf, --index, 'u'); StringUTF16.putChar(buf, --index, 'r'); StringUTF16.putChar(buf, --index, 't'); } else { StringUTF16.putChar(buf, --index, 'e'); StringUTF16.putChar(buf, --index, 's'); StringUTF16.putChar(buf, --index, 'l'); StringUTF16.putChar(buf, --index, 'a'); StringUTF16.putChar(buf, --index, 'f'); } return index | UTF16; } }
Prepends the stringly representation of byte value into buffer, given the coder and final index. Index is measured in chars, not in bytes!
Params:
  • indexCoder – final char index in the buffer, along with coder packed into higher bits.
  • buf – buffer to append to
  • value – byte value to encode
Returns: updated index (coder value retained)
/** * Prepends the stringly representation of byte value into buffer, * given the coder and final index. Index is measured in chars, not in bytes! * * @param indexCoder final char index in the buffer, along with coder packed * into higher bits. * @param buf buffer to append to * @param value byte value to encode * @return updated index (coder value retained) */
static long prepend(long indexCoder, byte[] buf, byte value) { return prepend(indexCoder, buf, (int)value); }
Prepends the stringly representation of char value into buffer, given the coder and final index. Index is measured in chars, not in bytes!
Params:
  • indexCoder – final char index in the buffer, along with coder packed into higher bits.
  • buf – buffer to append to
  • value – char value to encode
Returns: updated index (coder value retained)
/** * Prepends the stringly representation of char value into buffer, * given the coder and final index. Index is measured in chars, not in bytes! * * @param indexCoder final char index in the buffer, along with coder packed * into higher bits. * @param buf buffer to append to * @param value char value to encode * @return updated index (coder value retained) */
static long prepend(long indexCoder, byte[] buf, char value) { if (indexCoder < UTF16) { buf[(int)(--indexCoder)] = (byte) (value & 0xFF); } else { StringUTF16.putChar(buf, (int)(--indexCoder), value); } return indexCoder; }
Prepends the stringly representation of short value into buffer, given the coder and final index. Index is measured in chars, not in bytes!
Params:
  • indexCoder – final char index in the buffer, along with coder packed into higher bits.
  • buf – buffer to append to
  • value – short value to encode
Returns: updated index (coder value retained)
/** * Prepends the stringly representation of short value into buffer, * given the coder and final index. Index is measured in chars, not in bytes! * * @param indexCoder final char index in the buffer, along with coder packed * into higher bits. * @param buf buffer to append to * @param value short value to encode * @return updated index (coder value retained) */
static long prepend(long indexCoder, byte[] buf, short value) { return prepend(indexCoder, buf, (int)value); }
Prepends the stringly representation of integer value into buffer, given the coder and final index. Index is measured in chars, not in bytes!
Params:
  • indexCoder – final char index in the buffer, along with coder packed into higher bits.
  • buf – buffer to append to
  • value – integer value to encode
Returns: updated index (coder value retained)
/** * Prepends the stringly representation of integer value into buffer, * given the coder and final index. Index is measured in chars, not in bytes! * * @param indexCoder final char index in the buffer, along with coder packed * into higher bits. * @param buf buffer to append to * @param value integer value to encode * @return updated index (coder value retained) */
static long prepend(long indexCoder, byte[] buf, int value) { if (indexCoder < UTF16) { return Integer.getChars(value, (int)indexCoder, buf); } else { return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16; } }
Prepends the stringly representation of long value into buffer, given the coder and final index. Index is measured in chars, not in bytes!
Params:
  • indexCoder – final char index in the buffer, along with coder packed into higher bits.
  • buf – buffer to append to
  • value – long value to encode
Returns: updated index (coder value retained)
/** * Prepends the stringly representation of long value into buffer, * given the coder and final index. Index is measured in chars, not in bytes! * * @param indexCoder final char index in the buffer, along with coder packed * into higher bits. * @param buf buffer to append to * @param value long value to encode * @return updated index (coder value retained) */
static long prepend(long indexCoder, byte[] buf, long value) { if (indexCoder < UTF16) { return Long.getChars(value, (int)indexCoder, buf); } else { return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16; } }
Prepends the stringly representation of String value into buffer, given the coder and final index. Index is measured in chars, not in bytes!
Params:
  • indexCoder – final char index in the buffer, along with coder packed into higher bits.
  • buf – buffer to append to
  • value – String value to encode
Returns: updated index (coder value retained)
/** * Prepends the stringly representation of String value into buffer, * given the coder and final index. Index is measured in chars, not in bytes! * * @param indexCoder final char index in the buffer, along with coder packed * into higher bits. * @param buf buffer to append to * @param value String value to encode * @return updated index (coder value retained) */
static long prepend(long indexCoder, byte[] buf, String value) { indexCoder -= value.length(); if (indexCoder < UTF16) { value.getBytes(buf, (int)indexCoder, String.LATIN1); } else { value.getBytes(buf, (int)indexCoder, String.UTF16); } return indexCoder; }
Instantiates the String with given buffer and coder
Params:
  • buf – buffer to use
  • indexCoder – remaining index (should be zero) and coder
Returns:String resulting string
/** * Instantiates the String with given buffer and coder * @param buf buffer to use * @param indexCoder remaining index (should be zero) and coder * @return String resulting string */
static String newString(byte[] buf, long indexCoder) { // Use the private, non-copying constructor (unsafe!) if (indexCoder == LATIN1) { return new String(buf, String.LATIN1); } else if (indexCoder == UTF16) { return new String(buf, String.UTF16); } else { throw new InternalError("Storage is not completely initialized, " + (int)indexCoder + " bytes left"); } } private static final long LATIN1 = (long)String.LATIN1 << 32; private static final long UTF16 = (long)String.UTF16 << 32;
Provides the initial coder for the String.
Returns:initial coder, adjusted into the upper half
/** * Provides the initial coder for the String. * @return initial coder, adjusted into the upper half */
static long initialCoder() { return String.COMPACT_STRINGS ? LATIN1 : UTF16; } }