...
 
Commits (9)
......@@ -14,6 +14,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Light weight JSON Parser (`net.jemzart.jsonkraken`)
* `toListOfType` extension for JsonArray
* `toObjectOfType` extension for JsonObject
* Directory (`klib.files.Directory`)
* `asDirectory` extension for File
* `readAll` extension for FileList
* `writeAll` extensions for FileList
* `replaceAllOf` extension for MutableFileList
### Changed
* Moved and Renamed a lot of packages (Major Breaking Change)
* `toObjectFromType` extension on String uses Generics
......@@ -24,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* SimpleJSON was removed again (`org.json.*`)
* GSON was removed again (`com.google.gson`)
* `toObject(json, type)` function from Json interface
* `binSearch` extension from MutableList
### Fixed
### Security
......
package klib.extensions
import java.io.File
/**
* Sorting a list using quicksort by returning the sorted list
*
......@@ -65,4 +67,50 @@ fun <T : Comparable<T>> List<T>.binSearch(element: T, start: Int = 0, end: Int =
}
return binSearch(this, element, start, end)
}
/**
* Read all files contents
*
* @return HashMap with file name and content
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun List<File>.readAll(): HashMap<String, String> {
val content = HashMap<String, String>()
this.forEach {
content[it.name] = it.readText()
}
return content
}
/**
* Write all files contents
*
* @param content HashMap with file name and content
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun List<File>.writeAll(content: HashMap<String, String>) {
writeAll(content.toMutableMap())
}
/**
* Write all files contents
*
* @param content MutableMap with file name and content
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun List<File>.writeAll(content: MutableMap<String, String>) {
this.forEach {
if (it.name in content) {
it.writeText(content[it.name] ?: "")
}
}
}
\ No newline at end of file
package klib.extensions
import java.io.File
/**
* Swap two indexes in a MutableList
*
......@@ -132,28 +134,23 @@ fun <T, E> MutableList<T>.toListWithConvert(convert: (T) -> E): List<E> {
}
/**
* Recursion based Binary Search (About 50% faster then binarySearch)
* Replace all in all file contents
*
* @param element Element to search for
* @param start Index to start from
* @param end Index to stop at
* @return Index when Found, -1 when not
* @param search The string to replace
* @param replace The string to replace with
* @param ignoreCase Ignore case on search
*
* @since 3.2.0
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun <T : Comparable<T>> MutableList<T>.binSearch(element: T, start: Int = 0, end: Int = size): Int {
fun binSearch(array: List<T>, element: T, left: Int, right: Int): Int {
val middle = (left + right) / 2
return when {
left > right -> -1
array[middle] == element -> middle
array[middle] > element -> binSearch(array, element, left, middle - 1)
array[middle] < element -> binSearch(array, element, middle + 1, right)
else -> -1
fun MutableList<File>.replaceAllOf(search: String, replace: String, ignoreCase: Boolean = false) {
val content = this.readAll().toMutableMap()
content.forEach {
while (it.value.contains(search, ignoreCase)) {
content[it.key] = it.value.replace(search, replace, ignoreCase)
}
}
return binSearch(this, element, start, end)
this.writeAll(content)
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package klib.extensions
import klib.encoding.base.Base58e
import klib.exceptions.InvalidValueException
import klib.exceptions.RequireValueException
import klib.files.Directory
import klib.hash.Sha1
import klib.hash.Sha256
import klib.kLibInf
......@@ -233,6 +234,16 @@ fun String.fromBase64(): String {
*/
fun String.asFile() = File(this)
/**
* Uses the string as path for a new Directory object
*
* @return Directory object with string as path
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun String.asDirectory() = Directory(this)
/**
* Opens the string as file and returns the input stream
*
......
package klib.files
import klib.extensions.readAll
import klib.extensions.replaceAllOf
import java.io.File
import java.io.FileNotFoundException
/**
* Enhanced Directory API
*
* @param directoryPath The path of the directory
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
class Directory(val directoryPath: String) {
private val files: MutableList<File> = ArrayList()
private val filesContent: HashMap<String, String> = HashMap()
init {
val directory = File(directoryPath)
fun addDirectory(direct: File) {
// If given path exists and is directory
if (direct.exists()) {
if (direct.isDirectory) {
direct.listFiles()?.forEach {
// Recursively call add
addDirectory(it)
}
}
if (direct.isFile) {
// Add as file
addFile(direct)
}
}
}
// Start recursive load
addDirectory(directory)
// Read all the files content
readAll()
}
/**
* Add one file to the Directory
*
* @param file The file to add
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun addFile(newFile: File) {
var found = false
for (i in 0 until files.size) {
val file = files[i]
// File in cache
if (file.name == newFile.name) {
// override file
files[i] = file
found = true
break
}
}
// File not found in cache
if (!found) {
// add to cache
files.add(newFile)
}
// Read content of file
filesContent[newFile.name] = newFile.readText()
}
/**
* Add multiple files to the Directory
*
* @param fileList The list of files
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun addFiles(vararg fileList: File) {
fileList.forEach { addFile(it) }
}
/**
* Add multiple files to the Directory
*
* @param filesList The list of files
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun addFiles(filesList: List<File>) {
filesList.forEach { addFile(it) }
}
/**
* Get all files
*
* @return List of all files
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun all(): List<File> = files
/**
* Get one File by index
*
* @param index The index of the file
* @return The File
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun get(index: Int) = files[index]
/**
* Get the first file
*
* @return The File
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun first() = files.first()
/**
* Get the last file
*
* @return The File
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun last() = files.last()
/**
* Read one File from the Directory
*
* @param fileName The file to read
* @param forceNewRead Forces to read the file, causes the file to be added to the directory if not existent
* @return The content of the file as nullable String
*
* @throws FileNotFoundException
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun readOne(fileName: String, forceNewRead: Boolean = false): String? {
/**
* Local only function to read one files content
*
* @param file The File to read
* @return The content of the file as nullable String
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun readFile(file: File): String? {
filesContent[file.name] = file.readText()
return filesContent[file.name]
}
// Find the file in the directory
val file = files.find { it.name == fileName }
// If read is forced
if (forceNewRead) {
// and file exists in the directory
return if (file != null) {
// Read the file
readFile(file)
} else {
// Add the file to the directory
val newFile = File(fileName)
addFile(newFile)
// and read its content
readFile(newFile)
}
}
return when {
// File content already cached, return it
fileName in filesContent -> filesContent[fileName]
// File not null but in directory, read it
file != null -> readFile(file)
else -> {
// File was not found in the directory (dont just force add as it would be unexpected behavior)
throw FileNotFoundException(fileName)
}
}
}
/**
* Read all files contents
*
* @return HashMap with file name and content
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun readAll(): HashMap<String, String> {
filesContent.apply { files.readAll() }
return filesContent
}
/**
* Replace all in all file contents
*
* @param search The string to replace
* @param replace The string to replace with
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun replaceAll(search: String, replace: String) {
files.replaceAllOf(search, replace)
}
/**
* Write all files back to disk
*
* @param enableGitShield Dont write files in .git folder to prevent corruption
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun writeAll(enableGitShield: Boolean = true) {
for (file in files) {
if (!file.exists()) {
throw FileNotFoundException(file.name)
}
if (!file.isFile) {
continue
}
if (!file.canWrite()) {
continue
}
// Ignore .git folder to prevent repository corruption
if (file.path.contains(".git") && enableGitShield) {
continue
}
val fileContent = filesContent[file.name] ?: ""
println("File: ${file.name}; Path: ${file.path}; Content: $fileContent")
file.writeText(fileContent)
}
}
/**
* Find all files with one extension
*
* @param extension The extension to search for
* @return The list of files
*
* @since 4.0.0
* @author Thomas Obernosterer
*/
fun findWithExtension(extension: String): List<File> {
val filesWithExt: MutableList<File> = ArrayList()
files.forEach {
if (it.extension == extension) {
filesWithExt.add(it)
}
}
return filesWithExt
}
}
\ No newline at end of file
package devtests
import klib.extensions.asDirectory
import klib.extensions.replaceAllOf
fun main() {
val directory = "/stmp/vulture".asDirectory()
val cppFiles = directory.findWithExtension("cpp").toMutableList()
cppFiles.replaceAllOf("Vulture", "Cookie", true)
directory.addFiles(cppFiles)
directory.writeAll()
}
\ No newline at end of file
package devtests
import klib.extensions.binSearch
fun main() {
val list = mutableListOf(1,4,7,9,11,66,99)
println(list.binSearch(7))
}
\ No newline at end of file