<commit_before>//
//  File.swift
//  PerfectLib
//
//  Created by <NAME> on 7/7/15.
//	Copyright (C) 2015 PerfectlySoft, Inc.
//
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU Affero General Public License as
//	published by the Free Software Foundation, either version 3 of the
//	License, or (at your option) any later version, as supplemented by the
//	Perfect Additional Terms.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU Affero General Public License, as supplemented by the
//	Perfect Additional Terms, for more details.
//
//	You should have received a copy of the GNU Affero General Public License
//	and the Perfect Additional Terms that immediately follow the terms and
//	conditions of the GNU Affero General Public License along with this
//	program. If not, see <http://www.perfect.org/AGPL_3_0_With_Perfect_Additional_Terms.txt>.
//

#if os(Linux)
import SwiftGlibc
import LinuxBridge

// !FIX! these are obviously sketchy
// I hope SwiftGlibc to eventually include these
// Otherwise, export them from LinuxBridge
let S_IRGRP = (S_IRUSR >> 3)
let S_IWGRP	= (S_IWUSR >> 3)
let S_IRWXU = (__S_IREAD|__S_IWRITE|__S_IEXEC)
let S_IRWXG = (S_IRWXU >> 3)
let S_IRWXO = (S_IRWXG >> 3)

let SEEK_CUR: Int32 = 1
let EXDEV = Int32(18)
let EACCES = Int32(13)
let EAGAIN = Int32(11)
let F_OK: Int32 = 0

#else
import Darwin
#endif

let fileCopyBufferSize = 16384

/// Provides access to a file on the local file system
public class File : Closeable {
	
	var openMode = Int(O_RDONLY)
	var fd = -1
	var internalPath = ""
	
	/// Create a file object given a path and open mode
	/// - parameter path: Path to the file which will be accessed
	/// - parameter openMode: Default mode with which the file will be opened. Defaults to read-only. The file can be opened in any other mode by calling the accosiated openXXX function.
	public init(_ path: String, openMode: Int = Int(O_RDONLY)) {
		self.internalPath = path
		self.openMode = openMode
	}

	/// Create a file object given an already opened file descriptor
	/// - parameter fd: The file descriptor
	/// - parameter path: The path to the file which has been previously opened. Defaults to no path.
	public init(fd: Int32, path: String = "") {
		self.fd = Int(fd)
		self.internalPath = path
	}
	
	/// Create a temporary file, usually in the system's /tmp/ directory
	/// - parameter tempFilePrefix: The prefix for the temporary file's name. Random characters will be appended to the file's eventual name.
	public convenience init(tempFilePrefix: String) {
		let template = tempFilePrefix + "XXXXXX"
		let utf8 = template.utf8
		let name = UnsafeMutablePointer<Int8>.alloc(utf8.count + 1)
		var i = utf8.startIndex
		for index in 0..<utf8.count {
			name[index] = Int8(utf8[i])
			i = i.successor()
		}
		name[utf8.count] = 0
		
		let fd = mkstemp(name)
		let tmpFileName = String.fromCString(name)!
		
		name.dealloc(utf8.count + 1)
		name.destroy()
		
		self.init(fd: fd, path: tmpFileName)
	}
	
	/// Returns the file's path
	public func path() -> String { return internalPath }
	
	/// Returns the file path. If the file is a symbolic link, the link will be resolved.
	public func realPath() -> String {
		if isLink() {
			let buffer = UnsafeMutablePointer<Int8>.alloc(2048)
			defer { buffer.destroy() ; buffer.dealloc(2048) }
			let res = readlink(internalPath, buffer, 2048)
			if res != -1 {
				let ary = completeArray(buffer, count: res)
				let trailPath = UTF8Encoding.encode(ary)
				return trailPath
			}
		}
		return internalPath
	}
	
	/// Closes and deletes the file
	public func delete() {
		if isOpen() {
			close()
		}
		unlink(path())
	}
	
	/// Closes the file if it had been opened
	public func close() {
		if fd != -1 {
		#if os(Linux)
			SwiftGlibc.close(CInt(fd))
		#else
			Darwin.close(CInt(fd))
		#endif<commit_msg>Further tightened link resolution logic.<commit_after>//
//  File.swift
//  PerfectLib
//
//  Created by <NAME> on 7/7/15.
//	Copyright (C) 2015 PerfectlySoft, Inc.
//
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU Affero General Public License as
//	published by the Free Software Foundation, either version 3 of the
//	License, or (at your option) any later version, as supplemented by the
//	Perfect Additional Terms.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU Affero General Public License, as supplemented by the
//	Perfect Additional Terms, for more details.
//
//	You should have received a copy of the GNU Affero General Public License
//	and the Perfect Additional Terms that immediately follow the terms and
//	conditions of the GNU Affero General Public License along with this
//	program. If not, see <http://www.perfect.org/AGPL_3_0_With_Perfect_Additional_Terms.txt>.
//

#if os(Linux)
import SwiftGlibc
import LinuxBridge

// !FIX! these are obviously sketchy
// I hope SwiftGlibc to eventually include these
// Otherwise, export them from LinuxBridge
let S_IRGRP = (S_IRUSR >> 3)
let S_IWGRP	= (S_IWUSR >> 3)
let S_IRWXU = (__S_IREAD|__S_IWRITE|__S_IEXEC)
let S_IRWXG = (S_IRWXU >> 3)
let S_IRWXO = (S_IRWXG >> 3)

let SEEK_CUR: Int32 = 1
let EXDEV = Int32(18)
let EACCES = Int32(13)
let EAGAIN = Int32(11)
let F_OK: Int32 = 0

#else
import Darwin
#endif

let fileCopyBufferSize = 16384

/// Provides access to a file on the local file system
public class File : Closeable {
	
	var openMode = Int(O_RDONLY)
	var fd = -1
	var internalPath = ""
	
	/// Create a file object given a path and open mode
	/// - parameter path: Path to the file which will be accessed
	/// - parameter openMode: Default mode with which the file will be opened. Defaults to read-only. The file can be opened in any other mode by calling the accosiated openXXX function.
	public init(_ path: String, openMode: Int = Int(O_RDONLY)) {
		self.internalPath = path
		self.openMode = openMode
	}

	/// Create a file object given an already opened file descriptor
	/// - parameter fd: The file descriptor
	/// - parameter path: The path to the file which has been previously opened. Defaults to no path.
	public init(fd: Int32, path: String = "") {
		self.fd = Int(fd)
		self.internalPath = path
	}
	
	/// Create a temporary file, usually in the system's /tmp/ directory
	/// - parameter tempFilePrefix: The prefix for the temporary file's name. Random characters will be appended to the file's eventual name.
	public convenience init(tempFilePrefix: String) {
		let template = tempFilePrefix + "XXXXXX"
		let utf8 = template.utf8
		let name = UnsafeMutablePointer<Int8>.alloc(utf8.count + 1)
		var i = utf8.startIndex
		for index in 0..<utf8.count {
			name[index] = Int8(utf8[i])
			i = i.successor()
		}
		name[utf8.count] = 0
		
		let fd = mkstemp(name)
		let tmpFileName = String.fromCString(name)!
		
		name.dealloc(utf8.count + 1)
		name.destroy()
		
		self.init(fd: fd, path: tmpFileName)
	}
	
	/// Returns the file's path
	public func path() -> String { return internalPath }
	
	/// Returns the file path. If the file is a symbolic link, the link will be resolved.
	public func realPath() -> String {
		if isLink() {
			let buffer = UnsafeMutablePointer<Int8>.alloc(2048)
			defer { buffer.destroy() ; buffer.dealloc(2048) }
			let res = readlink(internalPath, buffer, 2048)
			if res != -1 {
				let ary = completeArray(buffer, count: res)
				let trailPath = UTF8Encoding.encode(ary)
				if trailPath[trailPath.startIndex] != "/" && trailPath[trailPath.startIndex] != "." {
					return internalPath.stringByDeletingLastPathComponent + "/" + trailPath
				}
				return trailPath
			}
		}
		return internalPath
	}
	
	/// Closes and deletes the file
	public func delete() {
		if isOpen() {
			close()
		}
		unlink(path())
	}
	
	/// Closes the file if it had been opened
	public func close() {
		if fd != -1 {
		#if os(Linux)
			SwiftGlibc.close(CInt(fd))
		#else
			Darwin.close(CInt(fd))
		#endif
{'fraction_non_alphanumeric': 0.09985405010946241, 'fraction_numerical': 0.017270737046947215, 'mean_word_length': 3.357710651828299, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5408824', 'n_tokens_mistral': 2894, 'n_tokens_neox': 2577, 'n_words': 1001}