content: /*
   * Copyright (C) 2019 The Android Open Source Project
   *
   * 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 com.google.android.exoplayer2.extractor;
  
  import androidx.annotation.Nullable;
  import com.google.android.exoplayer2.C;
  import com.google.android.exoplayer2.ParserException;
  import java.io.EOFException;
  import java.io.IOException;
  import org.checkerframework.dataflow.qual.Pure;
  
  /** Extractor related utility methods. */
  public final class ExtractorUtil {
  
    /**
     * If {@code expression} is false, throws a {@link ParserException#createForMalformedContainer
     * container malformed ParserException} with the given message. Otherwise, does nothing.
     */
    @Pure
    public static void checkContainerInput(boolean expression, @Nullable String message)
        throws ParserException {
      if (!expression) {
        throw ParserException.createForMalformedContainer(message, /* cause= */ null);
      }
    }
  
    /**
     * Peeks {@code length} bytes from the input peek position, or all the bytes to the end of the
     * input if there was less than {@code length} bytes left.
     *
     * <p>If an exception is thrown, there is no guarantee on the peek position.
     *
     * @param input The stream input to peek the data from.
     * @param target A target array into which data should be written.
     * @param offset The offset into the target array at which to write.
     * @param length The maximum number of bytes to peek from the input.
     * @return The number of bytes peeked.
     * @throws IOException If an error occurs peeking from the input.
     */
    public static int peekToLength(ExtractorInput input, byte[] target, int offset, int length)
        throws IOException {
      int totalBytesPeeked = 0;
      while (totalBytesPeeked < length) {
        int bytesPeeked = input.peek(target, offset + totalBytesPeeked, length - totalBytesPeeked);
        if (bytesPeeked == C.RESULT_END_OF_INPUT) {
          break;
        }
        totalBytesPeeked += bytesPeeked;
      }
      return totalBytesPeeked;
    }
  
    /**
     * Equivalent to {@link ExtractorInput#readFully(byte[], int, int)} except that it returns {@code
     * false} instead of throwing an {@link EOFException} if the end of input is encountered without
     * having fully satisfied the read.
     */
    public static boolean readFullyQuietly(
        ExtractorInput input, byte[] output, int offset, int length) throws IOException {
      try {
        input.readFully(output, offset, length);
      } catch (EOFException e) {
        return false;
      }
      return true;
    }
  
    /**
     * Equivalent to {@link ExtractorInput#skipFully(int)} except that it returns {@code false}
     * instead of throwing an {@link EOFException} if the end of input is encountered without having
     * fully satisfied the skip.
     */
    public static boolean skipFullyQuietly(ExtractorInput input, int length) throws IOException {
      try {
        input.skipFully(length);
      } catch (EOFException e) {
        return false;
      }
      return true;
    }
  
    /**
     * Peeks data from {@code input}, respecting {@code allowEndOfInput}. Returns true if the peek is
     * successful.
     *
     * <p>If {@code allowEndOfInput=false} then encountering the end of the input (whether before or
     * after reading some data) will throw {@link EOFException}.
     *
     * <p>If {@code allowEndOfInput=true} then encountering the end of the input (even after reading
     * some data) will return {@code false}.
     *
     * <p>This is slightly different to the behaviour of {@link ExtractorInput#peekFully(byte[], int,
     * int, boolean)}, where {@code allowEndOfInput=true} only returns false (and suppresses the
     * exception) if the end of the input is reached before reading any data.
     */
    public static boolean peekFullyQuietly(
        ExtractorInput input, byte[] output, int offset, int length, boolean allowEndOfInput)
        throws IOException {
      try {
        return input.peekFully(output, offset, length, /* allowEndOfInput= */ allowEndOfInput);
      } catch (EOFException e) {
        if (allowEndOfInput) {
          return false;
        } else {
          throw e;
        }
      }
    }
  
    private ExtractorUtil() {}
  }
  