<commit_before>/* NSC -- new Scala compiler
 * Copyright 2005-2011 LAMP/EPFL
 * @author  <NAME>
 */

package scala.tools.nsc
package io

import java.net.URL
import java.io.{ IOException, InputStream, ByteArrayInputStream }
import java.util.zip.{ ZipEntry, ZipFile, ZipInputStream }
import scala.collection.{ immutable, mutable }
import annotation.tailrec

/** An abstraction for zip files and streams.  Everything is written the way
 *  it is for performance: we come through here a lot on every run.  Be careful
 *  about changing it.
 *
 *  @author  <NAME> (original version)
 *  @author  <NAME> (this one)
 *  @version 2.0,
 */
object ZipArchive {
  def fromPath(path: String): FileZipArchive = fromFile(new JFile(path))
  def fromPath(path: Path): FileZipArchive = fromFile(path.toFile)

  /**
   * @param   file  a File
   * @return  A ZipArchive if `file` is a readable zip file, otherwise null.
   */
  def fromFile(file: File): FileZipArchive = fromFile(file.jfile)
  def fromFile(file: JFile): FileZipArchive =
    try   { new FileZipArchive(file) }
    catch { case _: IOException => null }

  /**
   * @param   url  the url of a zip file
   * @return  A ZipArchive backed by the given url.
   */
  def fromURL(url: URL): URLZipArchive = new URLZipArchive(url)
  def fromURL(url: String): URLZipArchive = fromURL(new URL(url))

  private def dirName(path: String)  = splitPath(path, true)
  private def baseName(path: String) = splitPath(path, false)
  private def splitPath(path0: String, front: Boolean): String = {
    val isDir = path0.charAt(path0.length - 1) == '/'
    val path  = if (isDir) path0.substring(0, path0.length - 1) else path0
    val idx   = path.lastIndexOf('/')

    if (idx < 0)
      if (front) "/"
      else path
    else
      if (front) path.substring(0, idx + 1)
      else path.substring(idx + 1)
  }
}
import ZipArchive._

abstract class ZipArchive(override val file: JFile) extends AbstractFile with Equals {
  self =>

  override def underlyingSource = Some(this)
  def isDirectory = true
  def lookupName(name: String, directory: Boolean) = unsupported
  def lookupNameUnchecked(name: String, directory: Boolean) = unsupported
  def create()  = unsupported
  def delete()  = unsupported
  def output    = unsupported
  def container = unsupported
  def absolute  = unsupported

  private def walkIterator(its: Iterator[AbstractFile]): Iterator[AbstractFile] = {
    its flatMap { f =>
      if (f.isDirectory) walkIterator(f.iterator)
      else Iterator(f)
    }
  }
  def deepIterator = walkIterator(iterator)

  sealed abstract class Entry(path: String) extends VirtualFile(baseName(path), path) {
    // have to keep this name for compat with sbt's compiler-interface
    def getArchive: ZipFile = null
    override def underlyingSource = Some(self)
    override def toString = self.path + "(" + path + ")"
  }
  class DirEntry(path: String) extends Entry(path) {
    val entries = mutable.HashMap[String, Entry]()

    override def isDirectory = true
    override def iterator = entries.valuesIterator
    override def lookupName(name: String, directory: Boolean): Entry = {
      if (directory) entries(name + "/")
      else entries(name)
    }
  }

  private def newDir(dirs: mutable.Map[String, DirEntry], path: String, zipEntry: ZipEntry): DirEntry = {
    val parent = {
      val parentPath = dirName(path)
      if (dirs contains parentPath) dirs(parentPath)
      else newDir(dirs, parentPath, null)
    }
    val dir = new DirEntry(path)
    parent.entries(baseName(path)) = dir
    dirs(path) = dir
    dir
  }
  protected def getDir(dirs: mutable.Map[String, DirEntry], entry: ZipEntry): DirEntry = {
    val name = entry.getName
    if (entry.isDirectory) {
      if (dirs contains name) dirs(name)
      else newDir(dirs, name, entry)
    }
    else {
      val path = dirName(name)
      if (dirs contains path) dirs(path)
      else newDir(dirs, path, null)
    }
  }
}

final class FileZipArchive(file: JFile) extends ZipArchive(file) {
  def iterator = {
    val zipFile = new ZipFile(file)<commit_msg>Now that I've convinced myself getOrElseUpdate ...<commit_after>/* NSC -- new Scala compiler
 * Copyright 2005-2011 LAMP/EPFL
 * @author  <NAME>
 */

package scala.tools.nsc
package io

import java.net.URL
import java.io.{ IOException, InputStream, ByteArrayInputStream }
import java.util.zip.{ ZipEntry, ZipFile, ZipInputStream }
import scala.collection.{ immutable, mutable }
import annotation.tailrec

/** An abstraction for zip files and streams.  Everything is written the way
 *  it is for performance: we come through here a lot on every run.  Be careful
 *  about changing it.
 *
 *  @author  <NAME> (original version)
 *  @author  <NAME> (this one)
 *  @version 2.0,
 */
object ZipArchive {
  def fromPath(path: String): FileZipArchive = fromFile(new JFile(path))
  def fromPath(path: Path): FileZipArchive = fromFile(path.toFile)

  /**
   * @param   file  a File
   * @return  A ZipArchive if `file` is a readable zip file, otherwise null.
   */
  def fromFile(file: File): FileZipArchive = fromFile(file.jfile)
  def fromFile(file: JFile): FileZipArchive =
    try   { new FileZipArchive(file) }
    catch { case _: IOException => null }

  /**
   * @param   url  the url of a zip file
   * @return  A ZipArchive backed by the given url.
   */
  def fromURL(url: URL): URLZipArchive = new URLZipArchive(url)
  def fromURL(url: String): URLZipArchive = fromURL(new URL(url))

  private def dirName(path: String)  = splitPath(path, true)
  private def baseName(path: String) = splitPath(path, false)
  private def splitPath(path0: String, front: Boolean): String = {
    val isDir = path0.charAt(path0.length - 1) == '/'
    val path  = if (isDir) path0.substring(0, path0.length - 1) else path0
    val idx   = path.lastIndexOf('/')

    if (idx < 0)
      if (front) "/"
      else path
    else
      if (front) path.substring(0, idx + 1)
      else path.substring(idx + 1)
  }
}
import ZipArchive._

abstract class ZipArchive(override val file: JFile) extends AbstractFile with Equals {
  self =>

  override def underlyingSource = Some(this)
  def isDirectory = true
  def lookupName(name: String, directory: Boolean) = unsupported
  def lookupNameUnchecked(name: String, directory: Boolean) = unsupported
  def create()  = unsupported
  def delete()  = unsupported
  def output    = unsupported
  def container = unsupported
  def absolute  = unsupported

  private def walkIterator(its: Iterator[AbstractFile]): Iterator[AbstractFile] = {
    its flatMap { f =>
      if (f.isDirectory) walkIterator(f.iterator)
      else Iterator(f)
    }
  }
  def deepIterator = walkIterator(iterator)

  sealed abstract class Entry(path: String) extends VirtualFile(baseName(path), path) {
    // have to keep this name for compat with sbt's compiler-interface
    def getArchive: ZipFile = null
    override def underlyingSource = Some(self)
    override def toString = self.path + "(" + path + ")"
  }
  class DirEntry(path: String) extends Entry(path) {
    val entries = mutable.HashMap[String, Entry]()

    override def isDirectory = true
    override def iterator = entries.valuesIterator
    override def lookupName(name: String, directory: Boolean): Entry = {
      if (directory) entries(name + "/")
      else entries(name)
    }
  }

  private def ensureDir(dirs: mutable.Map[String, DirEntry], path: String, zipEntry: ZipEntry): DirEntry = {
    dirs.getOrElseUpdate(path, {
      val parent = ensureDir(dirs, dirName(path), null)
      val dir    = new DirEntry(path)
      parent.entries(baseName(path)) = dir
      dir
    })
  }
  protected def getDir(dirs: mutable.Map[String, DirEntry], entry: ZipEntry): DirEntry = {
    if (entry.isDirectory) ensureDir(dirs, entry.getName, entry)
    else ensureDir(dirs, dirName(entry.getName), null)
  }
}

final class FileZipArchive(file: JFile) extends ZipArchive(file) {
  def iterator = {
    val zipFile = new ZipFile(file)
{'fraction_non_alphanumeric': 0.10741206030150753, 'fraction_numerical': 0.005778894472361809, 'mean_word_length': 3.4599439775910366, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6881540', 'n_tokens_mistral': 2581, 'n_tokens_neox': 2436, 'n_words': 775}