Skip to content

Commit

Permalink
Dropped Guava
Browse files Browse the repository at this point in the history
  we didn't use much of its functionality anyway
  • Loading branch information
superbobry committed Sep 22, 2016
1 parent 099baeb commit d615bc8
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 70 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Version 0.3.1
- Changed 'NpyFile.write' and 'NpzFile.Writer.write' to work in
constant amount of memory.
- Allowed writing arrays using a non-native byte order.
- Dropped Guava dependency.

Version 0.3.0
-------------
Expand Down
1 change: 0 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ repositories {

dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile 'com.google.guava:guava:19.0'

testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile 'junit:junit:4.+'
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Wed Sep 21 12:59:54 MSK 2016
#Thu Sep 22 13:26:27 MSK 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
Expand Down
85 changes: 37 additions & 48 deletions src/main/kotlin/org/jetbrains/bio/npy/Npy.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package org.jetbrains.bio.npy

import com.google.common.base.Charsets
import com.google.common.base.MoreObjects
import com.google.common.base.Strings
import com.google.common.collect.Iterables
import com.google.common.primitives.*
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.channels.FileChannel
Expand Down Expand Up @@ -66,18 +61,11 @@ object NpyFile {
else -> impossible()
} + metaUnpadded.length

Strings.padEnd(metaUnpadded,
metaUnpadded.length + (16 - totalUnpadded % 16),
' ')
metaUnpadded.padEnd(metaUnpadded.length + (16 - totalUnpadded % 16), ' ')
.toByteArray(Charsets.US_ASCII)
}

/**
* Allocates a [ByteBuffer] for the contents described by the header.
*
* The returned buffer already contains the serialized header and is
* guaranteed to be in correct [ByteOrder].
*/
/** Allocates a [ByteBuffer] for this header. */
fun allocate(): ByteBuffer {
val total = MAGIC.size + 2 + when (major to minor) {
1 to 0 -> 2
Expand All @@ -92,7 +80,10 @@ object NpyFile {
put(minor.toByte())

when (major to minor) {
1 to 0 -> putShort(Shorts.checkedCast(meta.size.toLong()))
1 to 0 -> {
check(meta.size <= Short.MAX_VALUE)
putShort(meta.size.toShort())
}
2 to 0 -> putInt(meta.size)
}

Expand Down Expand Up @@ -251,7 +242,7 @@ object NpyFile {
write(path, allocate(data, shape))
}

private fun write(path: Path, chunks: Iterable<ByteBuffer>) {
private fun write(path: Path, chunks: Sequence<ByteBuffer>) {
FileChannel.open(path,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE).use {
Expand All @@ -264,57 +255,55 @@ object NpyFile {
}
}

internal fun allocate(data: BooleanArray, shape: IntArray): Iterable<ByteBuffer> {
internal fun allocate(data: BooleanArray, shape: IntArray): Sequence<ByteBuffer> {
val header = Header(order = null, type = 'b', bytes = 1, shape = shape)
return Iterables.concat(listOf(header.allocate()),
BooleanArraySplitBuffer(data))
return sequenceOf(header.allocate()) + BooleanArraySplitBuffer(data)
}

internal fun allocate(data: ByteArray, shape: IntArray): Iterable<ByteBuffer> {
internal fun allocate(data: ByteArray, shape: IntArray): Sequence<ByteBuffer> {
val header = Header(order = null, type = 'i', bytes = 1, shape = shape)
return listOf(header.allocate(), ByteBuffer.wrap(data))
return sequenceOf(header.allocate()) + ByteBuffer.wrap(data)
}

internal fun allocate(data: ShortArray, shape: IntArray,
order: ByteOrder): Iterable<ByteBuffer> {
val header = Header(order = order, type = 'i', bytes = Shorts.BYTES, shape = shape)
return Iterables.concat(listOf(header.allocate()),
ShortArraySplitBuffer(data, order))
order: ByteOrder): Sequence<ByteBuffer> {
val header = Header(order = order, type = 'i',
bytes = java.lang.Short.BYTES, shape = shape)
return sequenceOf(header.allocate()) + ShortArraySplitBuffer(data, order)
}

internal fun allocate(data: IntArray, shape: IntArray,
order: ByteOrder): Iterable<ByteBuffer> {
val header = Header(order = order, type = 'i', bytes = Ints.BYTES, shape = shape)
return Iterables.concat(listOf(header.allocate()),
IntArraySplitBuffer(data, order))
order: ByteOrder): Sequence<ByteBuffer> {
val header = Header(order = order, type = 'i',
bytes = java.lang.Integer.BYTES, shape = shape)
return sequenceOf(header.allocate()) + IntArraySplitBuffer(data, order)
}

internal fun allocate(data: LongArray, shape: IntArray,
order: ByteOrder): Iterable<ByteBuffer> {
val header = Header(order = order, type = 'i', bytes = Longs.BYTES, shape = shape)
return Iterables.concat(listOf(header.allocate()),
LongArraySplitBuffer(data, order))
order: ByteOrder): Sequence<ByteBuffer> {
val header = Header(order = order, type = 'i',
bytes = java.lang.Long.BYTES, shape = shape)
return sequenceOf(header.allocate()) + LongArraySplitBuffer(data, order)
}

internal fun allocate(data: FloatArray, shape: IntArray,
order: ByteOrder): Iterable<ByteBuffer> {
val header = Header(order = order, type = 'f', bytes = Floats.BYTES, shape = shape)
return Iterables.concat(listOf(header.allocate()),
FloatArraySplitBuffer(data, order))
order: ByteOrder): Sequence<ByteBuffer> {
val header = Header(order = order, type = 'f',
bytes = java.lang.Float.BYTES, shape = shape)
return sequenceOf(header.allocate()) + FloatArraySplitBuffer(data, order)
}

internal fun allocate(data: DoubleArray, shape: IntArray,
order: ByteOrder): Iterable<ByteBuffer> {
val header = Header(order = order, type = 'f', bytes = Doubles.BYTES, shape = shape)
return Iterables.concat(listOf(header.allocate()),
DoubleArraySplitBuffer(data, order))
order: ByteOrder): Sequence<ByteBuffer> {
val header = Header(order = order, type = 'f',
bytes = java.lang.Double.BYTES, shape = shape)
return sequenceOf(header.allocate()) + DoubleArraySplitBuffer(data, order)
}

internal fun allocate(data: Array<String>, shape: IntArray): Iterable<ByteBuffer> {
internal fun allocate(data: Array<String>, shape: IntArray): Sequence<ByteBuffer> {
val bytes = data.asSequence().map { it.length }.max() ?: 0
val header = Header(order = null, type = 'S', bytes = bytes, shape = shape)
return Iterables.concat(listOf(header.allocate()),
StringArraySplitBuffer(data))
return sequenceOf(header.allocate()) + StringArraySplitBuffer(data)
}
}

Expand Down Expand Up @@ -342,10 +331,10 @@ class NpyArray(
@Suppress("unchecked_cast")
fun asStringArray() = data as Array<String>

override fun toString() = MoreObjects.toStringHelper(this)
.add("data", Arrays.deepToString(arrayOf(data))
override fun toString() = StringJoiner(", ", "NpyArray{", "}")
.add("data=" + Arrays.deepToString(arrayOf(data))
.removeSurrounding("[", "]"))
.add("shape", Arrays.toString(shape))
.add("shape=" + Arrays.toString(shape))
.toString()
}

Expand All @@ -371,4 +360,4 @@ internal fun npyExample() {

println(NpyFile.read(path))
// => NpyArray{data=[1, 2, 3, 4, 5, 6], shape=[2, 3]}
}
}
11 changes: 5 additions & 6 deletions src/main/kotlin/org/jetbrains/bio/npy/Npz.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.jetbrains.bio.npy

import com.google.common.base.MoreObjects
import java.io.Closeable
import java.nio.ByteBuffer
import java.nio.ByteOrder
Expand Down Expand Up @@ -147,7 +146,7 @@ object NpzFile {
writeEntry(name) { NpyFile.allocate(data, shape) }
}

private inline fun writeEntry(name: String, block: () -> Iterable<ByteBuffer>) {
private inline fun writeEntry(name: String, block: () -> Sequence<ByteBuffer>) {
val chunks = block()
val entry = ZipEntry(name + ".npy").apply {
if (compressed) {
Expand Down Expand Up @@ -192,10 +191,10 @@ object NpzFile {

/** A stripped down NPY header for an array in NPZ. */
class NpzEntry(val name: String, val type: Class<*>, val shape: IntArray) {
override fun toString() = MoreObjects.toStringHelper(this)
.add("name", name)
.add("type", type)
.add("shape", Arrays.toString(shape))
override fun toString() = StringJoiner(", ", "NpzEntry{", "}")
.add("name=" + name)
.add("type=" + type)
.add("shape=" + Arrays.toString(shape))
.toString()
}

Expand Down
16 changes: 7 additions & 9 deletions src/main/kotlin/org/jetbrains/bio/npy/SplitBuffer.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.jetbrains.bio.npy

import com.google.common.collect.UnmodifiableIterator
import com.google.common.primitives.*
import java.nio.ByteBuffer
import java.nio.ByteOrder

Expand Down Expand Up @@ -32,7 +30,7 @@ internal abstract class ArraySplitBuffer<T>(
/** Number of elements in the array. */
private val size: Int,
/** Byte order for the produced buffers. */
private val order: ByteOrder) : Iterable<ByteBuffer> {
private val order: ByteOrder) : Sequence<ByteBuffer> {
abstract val bytes: Int

/**
Expand All @@ -42,7 +40,7 @@ internal abstract class ArraySplitBuffer<T>(
*/
abstract fun ByteBuffer.fill(data: T, offset: Int, size: Int)

override fun iterator() = object : UnmodifiableIterator<ByteBuffer>() {
override fun iterator() = object : Iterator<ByteBuffer> {
private var offset = 0 // into the [data].
private var step = DEFAULT_BUFFER_SIZE / bytes
// Only allocated 'cache' if the [data] is bigger than [step].
Expand Down Expand Up @@ -84,7 +82,7 @@ internal class BooleanArraySplitBuffer(data: BooleanArray) :

internal class ShortArraySplitBuffer(data: ShortArray, order: ByteOrder) :
ArraySplitBuffer<ShortArray>(data, data.size, order) {
override val bytes: Int get() = Shorts.BYTES
override val bytes: Int get() = java.lang.Short.BYTES

override fun ByteBuffer.fill(data: ShortArray, offset: Int, size: Int) {
asShortBuffer().put(data, offset, size)
Expand All @@ -93,7 +91,7 @@ internal class ShortArraySplitBuffer(data: ShortArray, order: ByteOrder) :

internal class IntArraySplitBuffer(data: IntArray, order: ByteOrder) :
ArraySplitBuffer<IntArray>(data, data.size, order) {
override val bytes: Int get() = Ints.BYTES
override val bytes: Int get() = java.lang.Integer.BYTES

override fun ByteBuffer.fill(data: IntArray, offset: Int, size: Int) {
asIntBuffer().put(data, offset, size)
Expand All @@ -102,7 +100,7 @@ internal class IntArraySplitBuffer(data: IntArray, order: ByteOrder) :

internal class LongArraySplitBuffer(data: LongArray, order: ByteOrder) :
ArraySplitBuffer<LongArray>(data, data.size, order) {
override val bytes: Int get() = Longs.BYTES
override val bytes: Int get() = java.lang.Long.BYTES

override fun ByteBuffer.fill(data: LongArray, offset: Int, size: Int) {
asLongBuffer().put(data, offset, size)
Expand All @@ -111,7 +109,7 @@ internal class LongArraySplitBuffer(data: LongArray, order: ByteOrder) :

internal class FloatArraySplitBuffer(data: FloatArray, order: ByteOrder) :
ArraySplitBuffer<FloatArray>(data, data.size, order) {
override val bytes: Int get() = Floats.BYTES
override val bytes: Int get() = java.lang.Float.BYTES

override fun ByteBuffer.fill(data: FloatArray, offset: Int, size: Int) {
asFloatBuffer().put(data, offset, size)
Expand All @@ -120,7 +118,7 @@ internal class FloatArraySplitBuffer(data: FloatArray, order: ByteOrder) :

internal class DoubleArraySplitBuffer(data: DoubleArray, order: ByteOrder) :
ArraySplitBuffer<DoubleArray>(data, data.size, order) {
override val bytes: Int get() = Doubles.BYTES
override val bytes: Int get() = java.lang.Double.BYTES

override fun ByteBuffer.fill(data: DoubleArray, offset: Int, size: Int) {
asDoubleBuffer().put(data, offset, size)
Expand Down
32 changes: 29 additions & 3 deletions src/main/kotlin/org/jetbrains/bio/npy/Support.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.jetbrains.bio.npy

import com.google.common.collect.Iterators
import com.google.common.collect.PeekingIterator
import java.util.*

/** A marker function for "impossible" `when` branches. */
Expand Down Expand Up @@ -92,7 +90,7 @@ private fun tokenize(s: String): PeekingIterator<SpannedToken> {
best
}

return Iterators.peekingIterator(tokens.iterator())
return PeekingIterator(tokens.iterator())
}

/** Consume a token and return it. */
Expand All @@ -109,4 +107,32 @@ private fun PeekingIterator<SpannedToken>.tryEat(expected: Token): SpannedToken?
} else {
null
}
}

// XXX doesn't support iterators which might yield null.
private class PeekingIterator<out T>(private val it: Iterator<T>): Iterator<T> {
private var hasPeeked = false
private var item: T? = null

override fun hasNext() = hasPeeked || it.hasNext()

override fun next(): T {
return if (hasPeeked) {
val result = item
hasPeeked = false
item = null
result!!
} else {
it.next()
}
}

fun peek(): T {
if (!hasPeeked) {
item = it.next()
hasPeeked = true
}

return item!!
}
}
4 changes: 2 additions & 2 deletions src/test/kotlin/org/jetbrains/bio/npy/NpyFileTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.jetbrains.bio.npy

import com.google.common.primitives.Shorts
import org.junit.Assert.assertArrayEquals
import org.junit.Test
import org.junit.runner.RunWith
Expand Down Expand Up @@ -100,7 +99,8 @@ class NpyFileHeaderTest {
val header = NpyFile.Header(major = 1, minor = 0,
type = 'i', bytes = 4,
shape = intArrayOf(42))
val headerSize = NpyFile.Header.MAGIC.size + 2 + Shorts.BYTES + header.meta.size
val headerSize = NpyFile.Header.MAGIC.size + 2 +
java.lang.Short.BYTES + header.meta.size
assertTrue(headerSize % 16 == 0)
}

Expand Down

0 comments on commit d615bc8

Please sign in to comment.