001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.core.layout;
018
019import java.nio.ByteBuffer;
020
021/**
022 * Helper class for ByteBufferDestination implementors.
023 *
024 * @since 2.9 (see LOG4J2-1874)
025 */
026public final class ByteBufferDestinationHelper {
027
028    private ByteBufferDestinationHelper() {
029    }
030
031    /**
032     * Writes the specified data to the specified destination. Doesn't synchronize on the destination object. The helper
033     * method for {@link ByteBufferDestination#writeBytes(ByteBuffer)} implementations.
034     *
035     * @param source        the data to write
036     * @param destination the {@code ByteBufferDestination} to write to
037     */
038    public static void writeToUnsynchronized(final ByteBuffer source, final ByteBufferDestination destination) {
039        ByteBuffer destBuff = destination.getByteBuffer();
040        while (source.remaining() > destBuff.remaining()) {
041            final int originalLimit = source.limit();
042            source.limit(Math.min(source.limit(), source.position() + destBuff.remaining()));
043            destBuff.put(source);
044            source.limit(originalLimit);
045            destBuff = destination.drain(destBuff);
046        }
047        destBuff.put(source);
048        // No drain in the end.
049    }
050
051    /**
052     * Writes the specified data to the specified destination. Doesn't synchronize on the destination object. The helper
053     * method for {@link ByteBufferDestination#writeBytes(byte[], int, int)} implementations.
054     *
055     * @param data        the data to write
056     * @param offset      where to start in the specified data array
057     * @param length      the number of bytes to write
058     * @param destination the {@code ByteBufferDestination} to write to
059     */
060    public static void writeToUnsynchronized(final byte[] data, int offset, int length,
061            final ByteBufferDestination destination) {
062        ByteBuffer buffer = destination.getByteBuffer();
063        while (length > buffer.remaining()) {
064            final int chunk = buffer.remaining();
065            buffer.put(data, offset, chunk);
066            offset += chunk;
067            length -= chunk;
068            buffer = destination.drain(buffer);
069        }
070        buffer.put(data, offset, length);
071        // No drain in the end.
072    }
073}