All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.openhft.chronicle.bytes.util.StringInternerBytes Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2016-2022 chronicle.software
 *
 *     https://chronicle.software
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.openhft.chronicle.bytes.util;

import net.openhft.chronicle.bytes.Bytes;
import net.openhft.chronicle.bytes.algo.BytesStoreHash;
import net.openhft.chronicle.core.Maths;
import net.openhft.chronicle.core.annotation.NonNegative;
import net.openhft.chronicle.core.io.ClosedIllegalStateException;
import net.openhft.chronicle.core.io.ThreadingIllegalStateException;
import net.openhft.chronicle.core.pool.StringInterner;
import net.openhft.chronicle.core.util.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.nio.BufferUnderflowException;

import static net.openhft.chronicle.bytes.BytesUtil.toCharArray;

/**
 * String interner optimized for Bytes. This class extends {@link StringInterner} and is specifically
 * designed to handle interning of strings represented in {@link Bytes} objects.
 */
public class StringInternerBytes extends StringInterner {

    /**
     * Constructs a new {@code StringInternerBytes} instance with the specified capacity.
     *
     * @param capacity the number of strings that can be stored in the interner.
     * @throws IllegalArgumentException If the specified capacity is negative.
     */
    public StringInternerBytes(@NonNegative int capacity)
            throws IllegalArgumentException {
        super(capacity);
    }

    /**
     * Interns the string representation of the given bytes. The length of the string
     * is automatically determined based on the remaining bytes to read.
     *
     * @param bytes the bytes to be converted and interned as a string.
     * @return the interned string representation of the bytes.
     * @throws ArithmeticException      If there is an integer overflow when calculating the length.
     * @throws BufferUnderflowException If there are not enough bytes remaining to read.
     * @throws ClosedIllegalStateException    If the resource has been released or closed.
     * @throws ThreadingIllegalStateException If this resource was accessed by multiple threads in an unsafe way
     */
    public String intern(@NotNull final Bytes bytes)
            throws ArithmeticException, IllegalStateException, BufferUnderflowException {
        return intern(bytes, Maths.toUInt31(bytes.readRemaining()));
    }

    /**
     * Converts the given bytes to an ISO-8859-1 encoded string, and interns it. The string ends
     * either at the byte limit or the specified length, whichever comes first. If the string is
     * already in the pool, the pooled instance is returned. Otherwise, the string is added to the
     * pool.
     *
     * @param bytes  the bytes to convert to a string.
     * @param length specifies the maximum number of bytes to be converted, must be non-negative.
     * @return the interned string representation of the bytes.
     * @throws IllegalArgumentException If length is negative.
     * @throws BufferUnderflowException If there are not enough bytes remaining to read.
     * @throws ClosedIllegalStateException    If the resource has been released or closed.
     * @throws ThreadingIllegalStateException If this resource was accessed by multiple threads in an unsafe way
     */
    public String intern(@NotNull final Bytes bytes, @NonNegative int length)
            throws IllegalStateException, BufferUnderflowException {
        try {

            // Throw exception if length is negative
            if (length < 0) {
                throw new IllegalArgumentException("length=" + length);
            }

            // Calculate hash code of the bytes
            int hash32 = BytesStoreHash.hash32(bytes, length);
            int h = hash32 & mask;
            String s = interner[h];
            long position = bytes.readPosition();

            // Check if the bytes match an existing string in the pool
            if (bytes.isEqual(position, length, s)) {
                return s;
            }

            // Calculate secondary hash
            int h2 = (hash32 >> shift) & mask;
            String s2 = interner[h2];
            if (bytes.isEqual(position, length, s2)) {
                return s2;
            }

            // Convert bytes to characters
            char[] chars = toCharArray(bytes, position, length);

            // Determine where to place the new string in the interner array
            final int toPlace = s == null || (s2 != null && toggle()) ? h : h2;

            // Create a new string and add to the pool
            String result = StringUtils.newString(chars);
            interner[toPlace] = result;
            return result;

        } finally {
            // Skip read position by length
            bytes.readSkip(length);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy