// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.google.protobuf;

import static java.lang.Math.max;
import static java.lang.Math.min;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;

/**
 * Utility class to provide efficient writing of {@link ByteBuffer}s to {@link OutputStream}s.
 */
final class ByteBufferWriter {
  private ByteBufferWriter() {}

  /**
   * Minimum size for a cached buffer. This prevents us from allocating buffers that are too
   * small to be easily reused.
   */
  // TODO(nathanmittler): tune this property or allow configuration?
  private static final int MIN_CACHED_BUFFER_SIZE = 1024;

  /**
   * Maximum size for a cached buffer. If a larger buffer is required, it will be allocated
   * but not cached.
   */
  // TODO(nathanmittler): tune this property or allow configuration?
  private static final int MAX_CACHED_BUFFER_SIZE = 16 * 1024;

  /**
   * The fraction of the requested buffer size under which the buffer will be reallocated.
   */
  // TODO(nathanmittler): tune this property or allow configuration?
  private static final float BUFFER_REALLOCATION_THRESHOLD = 0.5f;

  /**
   * Keeping a soft reference to a thread-local buffer. This buffer is used for writing a
   * {@link ByteBuffer} to an {@link OutputStream} when no zero-copy alternative was available.
   * Using a "soft" reference since VMs may keep this reference around longer than "weak"
   * (e.g. HotSpot will maintain soft references until memory pressure warrants collection).
   */
  private static final ThreadLocal<SoftReference<byte[]>> BUFFER =
      new ThreadLocal<SoftReference<byte[]>>();

  /**
   * This is a hack for GAE, where {@code FileOutputStream} is unavailable.
   */
  private static final Class<?> FILE_OUTPUT_STREAM_CLASS = safeGetClass("java.io.FileOutputStream");
  private static final long CHANNEL_FIELD_OFFSET = getChannelFieldOffset(FILE_OUTPUT_STREAM_CLASS);

  /**
   * For testing purposes only. Clears the cached buffer to force a new allocation on the next
   * invocation.
   */
  static void clearCachedBuffer() {
    BUFFER.set(null);
  }

  /**
   * Writes the remaining content of the buffer to the given stream. The buffer {@code position}
   * will remain unchanged by this method.
   */
  static void write(ByteBuffer buffer, OutputStream output) throws IOException {
    final int initialPos = buffer.position();
    try {
      if (buffer.hasArray()) {
        // Optimized write for array-backed buffers.
        // Note that we're taking the risk that a malicious OutputStream could modify the array.
        output.write(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
      } else if (!writeToChannel(buffer, output)){
        // Read all of the data from the buffer to an array.
        // TODO(nathanmittler): Consider performance improvements for other "known" stream types.
        final byte[] array = getOrCreateBuffer(buffer.remaining());
        while (buffer.hasRemaining()) {
          int length = min(buffer.remaining(), array.length);
          buffer.get(array, 0, length);
          output.write(array, 0, length);
        }
      }
    } finally {
      // Restore the initial position.
      buffer.position(initialPos);
    }
  }

  private static byte[] getOrCreateBuffer(int requestedSize) {
    requestedSize = max(requestedSize, MIN_CACHED_BUFFER_SIZE);

    byte[] buffer = getBuffer();
    // Only allocate if we need to.
    if (buffer == null || needToReallocate(requestedSize, buffer.length)) {
      buffer = new byte[requestedSize];

      // Only cache the buffer if it's not too big.
      if (requestedSize <= MAX_CACHED_BUFFER_SIZE) {
        setBuffer(buffer);
      }
    }
    return buffer;
  }

  private static boolean needToReallocate(int requestedSize, int bufferLength) {
    // First check against just the requested length to avoid the multiply.
    return bufferLength < requestedSize
        && bufferLength < requestedSize * BUFFER_REALLOCATION_THRESHOLD;
  }

  private static byte[] getBuffer() {
    SoftReference<byte[]> sr = BUFFER.get();
    return sr == null ? null : sr.get();
  }

  private static void setBuffer(byte[] value) {
    BUFFER.set(new SoftReference<byte[]>(value));
  }

  private static boolean writeToChannel(ByteBuffer buffer, OutputStream output) throws IOException {
    if (CHANNEL_FIELD_OFFSET >= 0 && FILE_OUTPUT_STREAM_CLASS.isInstance(output)) {
      // Use a channel to write out the ByteBuffer. This will automatically empty the buffer.
      WritableByteChannel channel = null;
      try {
        channel = (WritableByteChannel) UnsafeUtil.getObject(output, CHANNEL_FIELD_OFFSET);
      } catch (ClassCastException e) {
        // Absorb.
      }
      if (channel != null) {
        channel.write(buffer);
        return true;
      }
    }
    return false;
  }

  private static Class<?> safeGetClass(String className) {
    try {
      return Class.forName(className);
    } catch (ClassNotFoundException e) {
      return null;
    }
  }
  private static long getChannelFieldOffset(Class<?> clazz) {
    try {
      if (clazz != null && UnsafeUtil.hasUnsafeArrayOperations()) {
        Field field = clazz.getDeclaredField("channel");
        return UnsafeUtil.objectFieldOffset(field);
      }
    } catch (Throwable e) {
      // Absorb
    }
    return -1;
  }
}
