Skip to content

Commit

Permalink
filery Prerelease 2 is out! The main changes are:
Browse files Browse the repository at this point in the history
- refactored inner structure. It will be effortless to add new platform support
- partial Linux support. Linux is the first platform where Kotlin/Native support will come
- appending and writing of UTF-8 text
  • Loading branch information
bpavuk committed Oct 24, 2023
1 parent 64f4ef8 commit b2dcca7
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 9 deletions.
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# filery — the multiplatform library for file fuckery

Latest version: Prerelease 2 (0.2)

WARNING: this project is currently on its early steps, is not production-ready and is welcome to contributions

This project aims to provide you with a common and intuitive API for files while remaining
easy to maintain and nuance-less

## Starting points

filery has two starting points - the `Filery` class and the `filery(path: String, block: Filery.() -> Unit)` function.
The first one is familiar for JVM users, meanwhile, the second is a more idiomatic and DSL-ish way. Here are the examples:

```kotlin
fun main() = runBlocking {
// filery function automatically closes the file in case of any error
// and when work upon the file is finished
filery("/home/bpavuk/fuckery.txt") {
println(readLine()) // outputs "Hello, filery"
}
}
```

Same but with `Filery` class:
```kotlin
fun main() = runBlocking {
val file = Filery("/home/bpavuk/fuckery.txt").open()
println(file.readText())
file.close()
}
```

Currently, filery is limited to two platforms: Linux (partially implemented) and JVM (fully implemented)

You can connect the filery to your Gradle project by adding the GitHub Registry and this dependency:
```
"com.bpavuk:filery:Prerelease_2"
```

Have a nice file fuckery!
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

group = "com.bpavuk"
version = "Prerelease_1"
version = "Prerelease_2"

repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@ public interface IFilePointer {
public fun delete(): Boolean
}

public expect class FilePointer : IFilePointer
public expect class FilePointer(
path: Path,
mode: Modes = Modes.ReadWrite
) : IFilePointer

3 changes: 2 additions & 1 deletion src/commonTest/kotlin/WriteTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

import com.bpavuk.filery.filery
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals

class WriteTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public actual class FilePointer(
override val platformFilePointer: JvmFile,
override val mode: Modes = Modes.ReadWrite
) : IFilePointer {
public constructor(path: Path, mode: Modes = Modes.ReadWrite): this(JvmFile(path), mode)
public actual constructor(path: Path, mode: Modes): this(JvmFile(path), mode)

override val path: Path = platformFilePointer.path

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.bpavuk.filery.expects

import com.bpavuk.filery.exceptions.FileDoesNotExistException
import com.bpavuk.filery.expects.pointers.DirectoryPointer
import com.bpavuk.filery.expects.pointers.FilePointer
import com.bpavuk.filery.types.Path
import kotlinx.cinterop.ExperimentalForeignApi
import platform.posix.F_OK
import platform.posix.access
import platform.posix.fclose
import platform.posix.fopen
import kotlinx.cinterop.alloc
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.ptr
import platform.posix.*


@OptIn(ExperimentalForeignApi::class)
public actual fun FileSystemEntity.createFile(path: Path): Boolean {
Expand All @@ -19,5 +23,33 @@ public actual fun FileSystemEntity.createFile(path: Path): Boolean {
}

public actual fun FileSystemEntity.createDir(path: Path): Boolean {
return mkdir("new_directory", (S_IRWXU or S_IRWXG or S_IRWXO).toUInt()) == 0
}

private fun S_ISREG(m: __mode_t): Boolean = m.toInt() and S_IFMT == S_IFREG

private fun S_ISDIR(m: __mode_t): Boolean = m.toInt() and S_IFMT == S_IFDIR

@OptIn(ExperimentalForeignApi::class)
public actual fun fileSystemEntityBuilder(
path: Path,
createFileOnNonExistence: Boolean
): FileSystemEntity {
val statPtr = memScoped {
alloc<stat>()
}
stat(path.path, statPtr.ptr)
return if (S_ISREG(statPtr.st_mode)) {
FileSystemEntity.File(
path,
FilePointer(path)
)
} else if (S_ISDIR(statPtr.st_mode)) {
FileSystemEntity.Directory(
path,
DirectoryPointer(path)
)
} else {
throw FileDoesNotExistException(path.path)
}
}
9 changes: 9 additions & 0 deletions src/linuxMain/kotlin/com/bpavuk/filery/expects/Utils.linux.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.bpavuk.filery.expects

import com.bpavuk.filery.types.Path
import platform.posix.F_OK
import platform.posix.access

public actual object Utils : IUtils {
override fun exists(path: Path): Boolean = access(path.path, F_OK) != -1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.bpavuk.filery.expects.pointers

import com.bpavuk.filery.types.Modes
import com.bpavuk.filery.types.Path

public actual class DirectoryPointer actual constructor(
override val path: Path,
override val mode: Modes
) : IDirectoryPointer {
override val platformDirectoryPointer: Any
get() = TODO("Not yet implemented")

override suspend fun listFiles(): List<Path> {
TODO("Not yet implemented")
}

override fun go(relativePath: String, mode: Modes): IDirectoryPointer {
TODO("Not yet implemented")
}

override fun create(relativePath: String): IDirectoryPointer {
TODO("Not yet implemented")
}

override fun delete(): Boolean {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,56 @@
package com.bpavuk.filery.expects.pointers

public actual class FilePointer : IFilePointer
import com.bpavuk.filery.types.Modes
import com.bpavuk.filery.types.Path
import kotlinx.cinterop.*
import kotlinx.io.files.FileNotFoundException
import platform.posix.*

@OptIn(ExperimentalForeignApi::class)
public actual class FilePointer actual constructor(
override val path: Path,
override val mode: Modes
) : IFilePointer {
private val modeAsString: String = when (mode) {
Modes.Read -> "r"
Modes.Write -> "r+"
Modes.ReadWrite -> "r+"
}
override val platformFilePointer: CFilePointer = CFilePointer(
currentPointer = fopen(path.path, modeAsString)
?: throw FileNotFoundException(path.path)
)

override fun close(): Boolean =
fclose(platformFilePointer.currentPointer) == 0

override fun delete(): Boolean = remove(path.path) == 0

override suspend fun readBytes(amount: Int?): ByteArray {
platformFilePointer.currentPosition = ftell(platformFilePointer.currentPointer)
platformFilePointer.currentPointer = fopen(path.path, "r") ?: throw FileNotFoundException(path.path)
fseek(platformFilePointer.currentPointer, 0, SEEK_END)
val fileSize = ftell(platformFilePointer.currentPointer)
val bytesLeft = (fileSize - platformFilePointer.currentPosition).toULong()
fseek(platformFilePointer.currentPointer, platformFilePointer.currentPosition, SEEK_SET)

val realAmount = amount?.toULong() ?: bytesLeft
val cByteArray = nativeHeap.allocArray<ByteVar>(realAmount.toInt())
fread(cByteArray, 1.toULong(), realAmount, platformFilePointer.currentPointer)
return cByteArray.readBytes(realAmount.toInt())
}

override suspend fun writeBytes(bytes: ByteArray) {
TODO("Not yet implemented")
}

override suspend fun appendBytes(bytes: ByteArray) {
TODO("Not yet implemented")
}
}

@OptIn(ExperimentalForeignApi::class)
public data class CFilePointer(
var currentPointer: CPointer<FILE>,
var currentPosition: Long = 0
)

0 comments on commit b2dcca7

Please sign in to comment.