content: /*
   * Copyright (C) 2010 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 dev.dworks.apps.anexplorer.libcore.io;
  
  import android.annotation.TargetApi;
  import android.content.res.AssetFileDescriptor;
  import android.database.Cursor;
  import android.os.Build;
  
  import java.io.Closeable;
  import java.io.File;
  import java.io.FileDescriptor;
  import java.io.Flushable;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InterruptedIOException;
  import java.io.OutputStream;
  import java.net.Socket;
  import java.util.zip.ZipFile;
  
  public final class IoUtils {
  
      /**
       * The default buffer size to use.
       */
      private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
  
      private IoUtils() {
      }
  
      /**
       * Closes 'AssetFileDescriptor', ignoring any checked exceptions. Does nothing if 'AssetFileDescriptor' is null.
       */
      public static void closeQuietly(AssetFileDescriptor closeable) {
          if (closeable != null) {
              try {
                  closeable.close();
              } catch (RuntimeException rethrown) {
                  throw rethrown;
              } catch (Exception ignored) {
              }
          }
      }
      
      /**
       * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
       */
      public static void closeQuietly(Closeable closeable) {
          if (closeable != null) {
              try {
                  closeable.close();
              } catch (RuntimeException rethrown) {
                  throw rethrown;
              } catch (Exception ignored) {
              }
          }
      }
      
      /**
       * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
       */
      public static void closeQuietly(Cursor closeable) {
          if (closeable != null) {
              try {
                  closeable.close();
              } catch (RuntimeException rethrown) {
                  throw rethrown;
              } catch (Exception ignored) {
              }
          }
      }
      
      /**
       * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
       */
      @TargetApi(Build.VERSION_CODES.KITKAT)
      public static void closeQuietly(AutoCloseable closeable) {
          if (closeable != null) {
              try {
                  closeable.close();
              } catch (RuntimeException rethrown) {
                  throw rethrown;
              } catch (Exception ignored) {
              }
          }
      }
  
      /**
       * Closes 'socket', ignoring any exceptions. Does nothing if 'socket' is null.
       */
      public static void closeQuietly(Socket socket) {
          if (socket != null) {
              try {
                  socket.close();
              } catch (Exception ignored) {
              }
          }
      }
  
      /**
       * Closes 'zipfile', ignoring any checked exceptions. Does nothing if 'closeable' is null.
       */
      public static void closeQuietly(ZipFile closeable) {
          if (closeable != null) {
              try {
                  closeable.close();
              } catch (RuntimeException rethrown) {
                  throw rethrown;
              } catch (Exception ignored) {
              }
          }
      }
  
      /**
       * Recursively delete everything in {@code dir}.
       */
      // TODO: this should specify paths as Strings rather than as Files
      public static void deleteContents(File dir) throws IOException {
          File[] files = dir.listFiles();
          if (files == null) {
              throw new IllegalArgumentException("not a directory: " + dir);
          }
          for (File file : files) {
              if (file.isDirectory()) {
                  deleteContents(file);
              }
              if (!file.delete()) {
                  throw new IOException("failed to delete file: " + file);
              }
          }
      }
      
      /**
       * Calls close(2) on 'fd'. Also resets the internal int to -1. Does nothing if 'fd' is null
       * or invalid.
       */
      public static void close(FileDescriptor fd) throws IOException {
  /*        try {
              if (fd != null && fd.valid()) {
                  Libcore.os.close(fd);
              }
          } catch (ErrnoException errnoException) {
              throw errnoException.rethrowAsIOException();
          }*/
      }
  
      /**
       * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
       */
  //    public static void closeQuietly(Cursor closeable) {
  //        if (closeable != null) {
  //            try {
  //                closeable.close();
  //            } catch (RuntimeException rethrown) {
  //                throw rethrown;
  //            } catch (Exception ignored) {
  //            }
  //        }
  //    }
  
      /**
       * Closes 'fd', ignoring any exceptions. Does nothing if 'fd' is null or invalid.
       */
      public static void closeQuietly(FileDescriptor fd) {
          try {
              IoUtils.close(fd);
          } catch (IOException ignored) {
          }
      }
  
      /**
       * Sets 'fd' to be blocking or non-blocking, according to the state of 'blocking'.
       */
      public static void setBlocking(FileDescriptor fd, boolean blocking) throws IOException {
  /*        try {
              int flags = Libcore.os.fcntlVoid(fd, F_GETFL);
              if (!blocking) {
                  flags |= O_NONBLOCK;
              } else {
                  flags &= ~O_NONBLOCK;
              }
              Libcore.os.fcntlLong(fd, F_SETFL, flags);
          } catch (ErrnoException errnoException) {
              throw errnoException.rethrowAsIOException();
          }*/
      }
  
      /**
       * Returns the contents of 'path' as a byte array.
       */
  /*    public static byte[] readFileAsByteArray(String path) throws IOException {
          return readFileAsBytes(path).toByteArray();
      }*/
  
      /**
       * Returns the contents of 'path' as a string. The contents are assumed to be UTF-8.
       */
  /*    public static String readFileAsString(String path) throws IOException {
          return readFileAsBytes(path).toString(Charsets.UTF_8);
      }
  
      private static UnsafeByteSequence readFileAsBytes(String path) throws IOException {
          RandomAccessFile f = null;
          try {
              f = new RandomAccessFile(path, "r");
              UnsafeByteSequence bytes = new UnsafeByteSequence((int) f.length());
              byte[] buffer = new byte[8192];
              while (true) {
                  int byteCount = f.read(buffer);
                  if (byteCount == -1) {
                      return bytes;
                  }
                  bytes.write(buffer, 0, byteCount);
              }
          } finally {
              IoUtils.closeQuietly(f);
          }
      }
  */
      /**
       * Checks whether {@code path} can be opened read-only. Similar to File.exists, but doesn't
       * require read permission on the parent, so it'll work in more cases, and allow you to
       * remove read permission from more directories.
       */
      public static boolean canOpenReadOnly(String path) {
  /*        try {
              // Use open(2) rather than stat(2) so we require fewer permissions. http://b/6485312.
              FileDescriptor fd = Libcore.os.open(path, O_RDONLY, 0);
              Libcore.os.close(fd);
              return true;
          } catch (ErrnoException errnoException) {
              return false;
          }*/
      	return false;
      }
  
      public static void throwInterruptedIoException() throws InterruptedIOException {
          // This is typically thrown in response to an
          // InterruptedException which does not leave the thread in an
          // interrupted state, so explicitly interrupt here.
          Thread.currentThread().interrupt();
          // TODO: set InterruptedIOException.bytesTransferred
          throw new InterruptedIOException();
      }
  
      // copy from InputStream
      //-----------------------------------------------------------------------
      /**
       * Copy bytes from an <code>InputStream</code> to an
       * <code>OutputStream</code>.
       * <p>
       * This method buffers the input internally, so there is no need to use a
       * <code>BufferedInputStream</code>.
       * <p>
       * Large streams (over 2GB) will return a bytes copied value of
       * <code>-1</code> after the copy has completed since the correct
       * number of bytes cannot be returned as an int. For large streams
       * use the <code>copyLarge(InputStream, OutputStream)</code> method.
       *
       * @param input  the <code>InputStream</code> to read from
       * @param output  the <code>OutputStream</code> to write to
       * @return the number of bytes copied
       * @throws NullPointerException if the input or output is null
       * @throws IOException if an I/O error occurs
       * @throws ArithmeticException if the byte count is too large
       * @since Commons IO 1.1
       */
      public static int copy(InputStream input, OutputStream output) throws IOException {
          long count = copyLarge(input, output);
          if (count > Integer.MAX_VALUE) {
              return -1;
          }
          return (int) count;
      }
  
      /**
       * Copy bytes from a large (over 2GB) <code>InputStream</code> to an
       * <code>OutputStream</code>.
       * <p>
       * This method buffers the input internally, so there is no need to use a
       * <code>BufferedInputStream</code>.
       *
       * @param input  the <code>InputStream</code> to read from
       * @param output  the <code>OutputStream</code> to write to
       * @return the number of bytes copied
       * @throws NullPointerException if the input or output is null
       * @throws IOException if an I/O error occurs
       * @since Commons IO 1.3
       */
      public static long copyLarge(InputStream input, OutputStream output)
              throws IOException {
          byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
          long count = 0;
          int n = 0;
          while (-1 != (n = input.read(buffer))) {
              output.write(buffer, 0, n);
              count += n;
          }
          return count;
      }
  
      /**
       * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
       */
      public static void flushQuietly(Flushable flushable) {
          if (flushable != null) {
              try {
                  flushable.flush();
              } catch (RuntimeException rethrown) {
                  throw rethrown;
              } catch (Exception ignored) {
              }
          }
      }
  }
  