diff --git a/.idea/kotlinScripting.xml b/.idea/kotlinScripting.xml deleted file mode 100644 index bc444de..0000000 --- a/.idea/kotlinScripting.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 0fc3113..f8467b4 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index ea81d94..e06d79b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,9 +6,9 @@ import org.lwjgl.Lwjgl.Module.jemalloc import org.lwjgl.lwjgl plugins { - kotlin("jvm") version embeddedKotlinVersion + embeddedKotlin("jvm") id("org.lwjgl.plugin") version "0.0.34" - id("elect86.magik") version "0.3.2" + id("elect86.magik") version "0.3.3" `maven-publish` // id("com.github.johnrengelman.shadow") version "8.1.1" } @@ -19,7 +19,7 @@ repositories { dependencies { lwjgl { implementation(jemalloc) } - testImplementation(kotlin("test")) + testImplementation(embeddedKotlin("test")) } kotlin.jvmToolchain { languageVersion.set(JavaLanguageVersion.of(8)) } diff --git a/buildSrc/src/main/kotlin/kool/gen/GenerateCode.kt b/buildSrc/src/main/kotlin/kool/gen/GenerateCode.kt index b4c58b1..89bb45e 100644 --- a/buildSrc/src/main/kotlin/kool/gen/GenerateCode.kt +++ b/buildSrc/src/main/kotlin/kool/gen/GenerateCode.kt @@ -3,6 +3,7 @@ package kool.gen import kool.* import org.gradle.api.DefaultTask import org.gradle.api.file.Directory +import org.gradle.api.file.FileSystemOperations import org.gradle.api.file.ProjectLayout import org.gradle.api.provider.Provider import org.gradle.api.tasks.OutputDirectory @@ -14,19 +15,22 @@ abstract class GenerateCode: DefaultTask() { init { group = "build" - description = "Generate glm code" + description = "Generate code" } @get:Inject abstract val layout: ProjectLayout + @get:Inject + abstract val files: FileSystemOperations + @get:OutputDirectory - val targetDir: Provider - get() = layout.buildDirectory.dir("generated/common") + val targetDir: Directory = layout.projectDirectory.dir("src/mainGen/kotlin") @TaskAction fun generate() { - val target = targetDir.get().asFile + files.delete { delete(targetDir) } + val target = targetDir.asFile ubuffers(target) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d7b400a..a5e31d4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,6 +3,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip -distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae diff --git a/settings.gradle.kts b/settings.gradle.kts index f370dfb..c4799be 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,7 +10,7 @@ pluginManagement { gradle.rootProject { group = "kotlin.graphics" - version = "0.9.77" + version = "0.9.78" } //includeBuild("../build-logic") \ No newline at end of file diff --git a/src/mainGen/kotlin/kool/buffersJvm.kt b/src/mainGen/kotlin/kool/buffersJvm.kt new file mode 100644 index 0000000..c91d7fe --- /dev/null +++ b/src/mainGen/kotlin/kool/buffersJvm.kt @@ -0,0 +1,12568 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:OptIn(kotlin.experimental.ExperimentalTypeInference::class, kotlin.ExperimentalUnsignedTypes::class) +package kool +import kool.ubuffers.UByteBuffer +import java.nio.LongBuffer +import kool.ubuffers.UShortBuffer +import kool.ubuffers.ULongBuffer +import kool.lib.mapCapacity +import kool.set +import java.nio.IntBuffer +import java.nio.ByteBuffer +import kool.rem +import org.lwjgl.PointerBuffer +import kool.iterator +import java.nio.ShortBuffer +import java.nio.DoubleBuffer +import java.nio.FloatBuffer +import java.nio.CharBuffer +import kool.lib.collectionSizeOrDefault +import kool.ubuffers.UIntBuffer + +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun CharBuffer.component1(): Char = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun CharBuffer.component2(): Char = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun CharBuffer.component3(): Char = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun CharBuffer.component4(): Char = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun CharBuffer.component5(): Char = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun CharBuffer.contains(element: Char): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun CharBuffer.elementAt(index: Int): Char = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun CharBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> Char): Char = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun CharBuffer.elementAtOrNull(index: Int): Char? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun CharBuffer.find(predicate: (Char) -> Boolean): Char? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun CharBuffer.findLast(predicate: (Char) -> Boolean): Char? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun CharBuffer.first(): Char { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun CharBuffer.first(predicate: (Char) -> Boolean): Char { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun CharBuffer.firstOrNull(): Char? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun CharBuffer.firstOrNull(predicate: (Char) -> Boolean): Char? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun CharBuffer.getOrElse(index: Int, defaultValue: (Int) -> Char): Char = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun CharBuffer.getOrNull(index: Int): Char? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun CharBuffer.indexOf(element: Char): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun CharBuffer.indexOfFirst(predicate: (Char) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun CharBuffer.indexOfLast(predicate: (Char) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun CharBuffer.last(): Char { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun CharBuffer.last(predicate: (Char) -> Boolean): Char { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun CharBuffer.lastIndexOf(element: Char): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun CharBuffer.lastOrNull(): Char? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun CharBuffer.lastOrNull(predicate: (Char) -> Boolean): Char? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun CharBuffer.single(): Char = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun CharBuffer.single(predicate: (Char) -> Boolean): Char { + var single: Char? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as Char +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun CharBuffer.singleOrNull(): Char? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun CharBuffer.singleOrNull(predicate: (Char) -> Boolean): Char? { + var single: Char? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun CharBuffer.filter(predicate: (Char) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun CharBuffer.filterIndexed(predicate: (index: Int, Char) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > CharBuffer.filterIndexedTo(destination: C, predicate: (index: Int, Char) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun CharBuffer.filterNot(predicate: (Char) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > CharBuffer.filterNotTo(destination: C, predicate: (Char) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > CharBuffer.filterTo(destination: C, predicate: (Char) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun CharBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun CharBuffer.sliceArray(indices: Collection): CharArray { + val result = CharArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun CharBuffer.sortDescending() { + if (rem > 1) { + val array = toCharArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun CharBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun CharBuffer.sortedArray(): CharArray = toCharArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun CharBuffer.sortedArrayDescending(): CharArray = toCharArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > CharBuffer.sortedBy(crossinline selector: (Char) -> R?): List = toCharArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > CharBuffer.sortedByDescending(crossinline selector: (Char) -> R?): List = toCharArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun CharBuffer.sortedDescending(): List = toCharArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun CharBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun CharBuffer.sort() { + if (rem > 1) { + val array = toCharArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun CharBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun CharBuffer.fill(element: Char, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val CharBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun CharBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun CharBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val CharBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun CharBuffer.toCharArray(): CharArray = CharArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun CharBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun CharBuffer.associate(transform: (Char) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun CharBuffer.associateBy(keySelector: (Char) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun CharBuffer.associateBy(keySelector: (Char) -> K, valueTransform: (Char) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > CharBuffer.associateByTo(destination: M, keySelector: (Char) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > CharBuffer.associateByTo(destination: M, keySelector: (Char) -> K, valueTransform: (Char) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > CharBuffer.associateTo(destination: M, transform: (Char) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun CharBuffer.associateWith(valueSelector: (Char) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > CharBuffer.associateWithTo(destination: M, valueSelector: (Char) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > CharBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun CharBuffer.flatMap(transform: (Char) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > CharBuffer.flatMapTo(destination: C, transform: (Char) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun CharBuffer.groupBy(keySelector: (Char) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun CharBuffer.groupBy(keySelector: (Char) -> K, valueTransform: (Char) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> CharBuffer.groupByTo(destination: M, keySelector: (Char) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> CharBuffer.groupByTo(destination: M, keySelector: (Char) -> K, valueTransform: (Char) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun CharBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun CharBuffer.distinctBy(selector: (Char) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun CharBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun CharBuffer.map(transform: (Char) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun CharBuffer.mapIndexed(transform: (index: Int, Char) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > CharBuffer.mapIndexedTo(destination: C, transform: (index: Int, Char) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > CharBuffer.mapTo(destination: C, transform: (Char) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun CharBuffer.all(predicate: (Char) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun CharBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun CharBuffer.any(predicate: (Char) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun CharBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun CharBuffer.count(predicate: (Char) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun CharBuffer.forEach(action: (Char) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun CharBuffer.forEachIndexed(action: (index: Int, Char) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun CharBuffer.max(): Char { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > CharBuffer.maxBy(selector: (Char) -> R): Char { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > CharBuffer.maxByOrNull(selector: (Char) -> R): Char? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun CharBuffer.maxOrNull(): Char? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun CharBuffer.maxWith(comparator: Comparator): Char { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun CharBuffer.maxWithOrNull(comparator: Comparator): Char? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun CharBuffer.min(): Char { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > CharBuffer.minBy(selector: (Char) -> R): Char { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > CharBuffer.minByOrNull(selector: (Char) -> R): Char? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun CharBuffer.minOf(selector: (Char) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun CharBuffer.minOf(selector: (Char) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > CharBuffer.minOf(selector: (Char) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun CharBuffer.minOfOrNull(selector: (Char) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun CharBuffer.minOfOrNull(selector: (Char) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > CharBuffer.minOfOrNull(selector: (Char) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun CharBuffer.minOfWith(comparator: Comparator, selector: (Char) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun CharBuffer.minOfWithOrNull(comparator: Comparator, selector: (Char) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun CharBuffer.minOrNull(): Char? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun CharBuffer.minWith(comparator: Comparator): Char { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun CharBuffer.minWithOrNull(comparator: Comparator): Char? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun CharBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun CharBuffer.none(predicate: (Char) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun CharBuffer.onEach(action: (Char) -> Unit): CharBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun CharBuffer.onEachIndexed(action: (index: Int, Char) -> Unit): CharBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun CharBuffer.reduce(operation: (acc: Char, Char) -> Char): Char { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun CharBuffer.reduceIndexed(operation: (index: Int, acc: Char, Char) -> Char): Char { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun CharBuffer.reduceIndexedOrNull(operation: (index: Int, acc: Char, Char) -> Char): Char? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun CharBuffer.reduceOrNull(operation: (acc: Char, Char) -> Char): Char? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun CharBuffer.reduceRight(operation: (Char, acc: Char) -> Char): Char { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun CharBuffer.reduceRightIndexed(operation: (index: Int, Char, acc: Char) -> Char): Char { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun CharBuffer.reduceRightIndexedOrNull(operation: (index: Int, Char, acc: Char) -> Char): Char? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun CharBuffer.reduceRightOrNull(operation: (Char, acc: Char) -> Char): Char? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun CharBuffer.partition(predicate: (Char) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun CharBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun CharBuffer.zip(other: Array, transform: (a: Char, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun CharBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun CharBuffer.zip(other: Iterable, transform: (a: Char, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun CharBuffer.zip(other: CharArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun CharBuffer.zip(other: CharArray, transform: (a: Char, b: Char) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun CharBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Char) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun CharBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Char) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun ByteBuffer.component1(): Byte = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun ByteBuffer.component2(): Byte = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun ByteBuffer.component3(): Byte = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun ByteBuffer.component4(): Byte = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun ByteBuffer.component5(): Byte = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun ByteBuffer.contains(element: Byte): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun ByteBuffer.elementAt(index: Int): Byte = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun ByteBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> Byte): Byte = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun ByteBuffer.elementAtOrNull(index: Int): Byte? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun ByteBuffer.find(predicate: (Byte) -> Boolean): Byte? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun ByteBuffer.findLast(predicate: (Byte) -> Boolean): Byte? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ByteBuffer.first(): Byte { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun ByteBuffer.first(predicate: (Byte) -> Boolean): Byte { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun ByteBuffer.firstOrNull(): Byte? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun ByteBuffer.firstOrNull(predicate: (Byte) -> Boolean): Byte? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun ByteBuffer.getOrElse(index: Int, defaultValue: (Int) -> Byte): Byte = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun ByteBuffer.getOrNull(index: Int): Byte? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun ByteBuffer.indexOf(element: Byte): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun ByteBuffer.indexOfFirst(predicate: (Byte) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun ByteBuffer.indexOfLast(predicate: (Byte) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ByteBuffer.last(): Byte { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun ByteBuffer.last(predicate: (Byte) -> Boolean): Byte { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun ByteBuffer.lastIndexOf(element: Byte): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun ByteBuffer.lastOrNull(): Byte? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun ByteBuffer.lastOrNull(predicate: (Byte) -> Boolean): Byte? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun ByteBuffer.single(): Byte = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun ByteBuffer.single(predicate: (Byte) -> Boolean): Byte { + var single: Byte? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as Byte +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun ByteBuffer.singleOrNull(): Byte? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun ByteBuffer.singleOrNull(predicate: (Byte) -> Boolean): Byte? { + var single: Byte? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun ByteBuffer.filter(predicate: (Byte) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun ByteBuffer.filterIndexed(predicate: (index: Int, Byte) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > ByteBuffer.filterIndexedTo(destination: C, predicate: (index: Int, Byte) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun ByteBuffer.filterNot(predicate: (Byte) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > ByteBuffer.filterNotTo(destination: C, predicate: (Byte) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > ByteBuffer.filterTo(destination: C, predicate: (Byte) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun ByteBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun ByteBuffer.sliceArray(indices: Collection): ByteArray { + val result = ByteArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun ByteBuffer.sortDescending() { + if (rem > 1) { + val array = toByteArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun ByteBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun ByteBuffer.sortedArray(): ByteArray = toByteArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun ByteBuffer.sortedArrayDescending(): ByteArray = toByteArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > ByteBuffer.sortedBy(crossinline selector: (Byte) -> R?): List = toByteArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > ByteBuffer.sortedByDescending(crossinline selector: (Byte) -> R?): List = toByteArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun ByteBuffer.sortedDescending(): List = toByteArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun ByteBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun ByteBuffer.sort() { + if (rem > 1) { + val array = toByteArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun ByteBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun ByteBuffer.fill(element: Byte, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val ByteBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun ByteBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun ByteBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val ByteBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun ByteBuffer.toByteArray(): ByteArray = ByteArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun ByteBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ByteBuffer.associate(transform: (Byte) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ByteBuffer.associateBy(keySelector: (Byte) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ByteBuffer.associateBy(keySelector: (Byte) -> K, valueTransform: (Byte) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > ByteBuffer.associateByTo(destination: M, keySelector: (Byte) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > ByteBuffer.associateByTo(destination: M, keySelector: (Byte) -> K, valueTransform: (Byte) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > ByteBuffer.associateTo(destination: M, transform: (Byte) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ByteBuffer.associateWith(valueSelector: (Byte) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > ByteBuffer.associateWithTo(destination: M, valueSelector: (Byte) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > ByteBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun ByteBuffer.flatMap(transform: (Byte) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > ByteBuffer.flatMapTo(destination: C, transform: (Byte) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun ByteBuffer.groupBy(keySelector: (Byte) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun ByteBuffer.groupBy(keySelector: (Byte) -> K, valueTransform: (Byte) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> ByteBuffer.groupByTo(destination: M, keySelector: (Byte) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> ByteBuffer.groupByTo(destination: M, keySelector: (Byte) -> K, valueTransform: (Byte) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun ByteBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun ByteBuffer.distinctBy(selector: (Byte) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun ByteBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun ByteBuffer.map(transform: (Byte) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun ByteBuffer.mapIndexed(transform: (index: Int, Byte) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > ByteBuffer.mapIndexedTo(destination: C, transform: (index: Int, Byte) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > ByteBuffer.mapTo(destination: C, transform: (Byte) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun ByteBuffer.all(predicate: (Byte) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun ByteBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun ByteBuffer.any(predicate: (Byte) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun ByteBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun ByteBuffer.count(predicate: (Byte) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun ByteBuffer.forEach(action: (Byte) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun ByteBuffer.forEachIndexed(action: (index: Int, Byte) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ByteBuffer.max(): Byte { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > ByteBuffer.maxBy(selector: (Byte) -> R): Byte { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > ByteBuffer.maxByOrNull(selector: (Byte) -> R): Byte? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun ByteBuffer.maxOrNull(): Byte? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ByteBuffer.maxWith(comparator: Comparator): Byte { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun ByteBuffer.maxWithOrNull(comparator: Comparator): Byte? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ByteBuffer.min(): Byte { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > ByteBuffer.minBy(selector: (Byte) -> R): Byte { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > ByteBuffer.minByOrNull(selector: (Byte) -> R): Byte? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun ByteBuffer.minOf(selector: (Byte) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun ByteBuffer.minOf(selector: (Byte) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > ByteBuffer.minOf(selector: (Byte) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun ByteBuffer.minOfOrNull(selector: (Byte) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun ByteBuffer.minOfOrNull(selector: (Byte) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > ByteBuffer.minOfOrNull(selector: (Byte) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun ByteBuffer.minOfWith(comparator: Comparator, selector: (Byte) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun ByteBuffer.minOfWithOrNull(comparator: Comparator, selector: (Byte) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun ByteBuffer.minOrNull(): Byte? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ByteBuffer.minWith(comparator: Comparator): Byte { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun ByteBuffer.minWithOrNull(comparator: Comparator): Byte? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun ByteBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun ByteBuffer.none(predicate: (Byte) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun ByteBuffer.onEach(action: (Byte) -> Unit): ByteBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun ByteBuffer.onEachIndexed(action: (index: Int, Byte) -> Unit): ByteBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun ByteBuffer.reduce(operation: (acc: Byte, Byte) -> Byte): Byte { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun ByteBuffer.reduceIndexed(operation: (index: Int, acc: Byte, Byte) -> Byte): Byte { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun ByteBuffer.reduceIndexedOrNull(operation: (index: Int, acc: Byte, Byte) -> Byte): Byte? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun ByteBuffer.reduceOrNull(operation: (acc: Byte, Byte) -> Byte): Byte? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun ByteBuffer.reduceRight(operation: (Byte, acc: Byte) -> Byte): Byte { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun ByteBuffer.reduceRightIndexed(operation: (index: Int, Byte, acc: Byte) -> Byte): Byte { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun ByteBuffer.reduceRightIndexedOrNull(operation: (index: Int, Byte, acc: Byte) -> Byte): Byte? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun ByteBuffer.reduceRightOrNull(operation: (Byte, acc: Byte) -> Byte): Byte? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun ByteBuffer.partition(predicate: (Byte) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun ByteBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun ByteBuffer.zip(other: Array, transform: (a: Byte, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun ByteBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun ByteBuffer.zip(other: Iterable, transform: (a: Byte, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun ByteBuffer.zip(other: ByteArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun ByteBuffer.zip(other: ByteArray, transform: (a: Byte, b: Byte) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun ByteBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Byte) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun ByteBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Byte) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun ShortBuffer.component1(): Short = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun ShortBuffer.component2(): Short = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun ShortBuffer.component3(): Short = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun ShortBuffer.component4(): Short = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun ShortBuffer.component5(): Short = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun ShortBuffer.contains(element: Short): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun ShortBuffer.elementAt(index: Int): Short = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun ShortBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> Short): Short = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun ShortBuffer.elementAtOrNull(index: Int): Short? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun ShortBuffer.find(predicate: (Short) -> Boolean): Short? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun ShortBuffer.findLast(predicate: (Short) -> Boolean): Short? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ShortBuffer.first(): Short { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun ShortBuffer.first(predicate: (Short) -> Boolean): Short { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun ShortBuffer.firstOrNull(): Short? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun ShortBuffer.firstOrNull(predicate: (Short) -> Boolean): Short? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun ShortBuffer.getOrElse(index: Int, defaultValue: (Int) -> Short): Short = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun ShortBuffer.getOrNull(index: Int): Short? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun ShortBuffer.indexOf(element: Short): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun ShortBuffer.indexOfFirst(predicate: (Short) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun ShortBuffer.indexOfLast(predicate: (Short) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ShortBuffer.last(): Short { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun ShortBuffer.last(predicate: (Short) -> Boolean): Short { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun ShortBuffer.lastIndexOf(element: Short): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun ShortBuffer.lastOrNull(): Short? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun ShortBuffer.lastOrNull(predicate: (Short) -> Boolean): Short? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun ShortBuffer.single(): Short = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun ShortBuffer.single(predicate: (Short) -> Boolean): Short { + var single: Short? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as Short +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun ShortBuffer.singleOrNull(): Short? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun ShortBuffer.singleOrNull(predicate: (Short) -> Boolean): Short? { + var single: Short? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun ShortBuffer.filter(predicate: (Short) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun ShortBuffer.filterIndexed(predicate: (index: Int, Short) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > ShortBuffer.filterIndexedTo(destination: C, predicate: (index: Int, Short) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun ShortBuffer.filterNot(predicate: (Short) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > ShortBuffer.filterNotTo(destination: C, predicate: (Short) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > ShortBuffer.filterTo(destination: C, predicate: (Short) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun ShortBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun ShortBuffer.sliceArray(indices: Collection): ShortArray { + val result = ShortArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun ShortBuffer.sortDescending() { + if (rem > 1) { + val array = toShortArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun ShortBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun ShortBuffer.sortedArray(): ShortArray = toShortArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun ShortBuffer.sortedArrayDescending(): ShortArray = toShortArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > ShortBuffer.sortedBy(crossinline selector: (Short) -> R?): List = toShortArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > ShortBuffer.sortedByDescending(crossinline selector: (Short) -> R?): List = toShortArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun ShortBuffer.sortedDescending(): List = toShortArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun ShortBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun ShortBuffer.sort() { + if (rem > 1) { + val array = toShortArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun ShortBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun ShortBuffer.fill(element: Short, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val ShortBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun ShortBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun ShortBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val ShortBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun ShortBuffer.toShortArray(): ShortArray = ShortArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun ShortBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ShortBuffer.associate(transform: (Short) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ShortBuffer.associateBy(keySelector: (Short) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ShortBuffer.associateBy(keySelector: (Short) -> K, valueTransform: (Short) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > ShortBuffer.associateByTo(destination: M, keySelector: (Short) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > ShortBuffer.associateByTo(destination: M, keySelector: (Short) -> K, valueTransform: (Short) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > ShortBuffer.associateTo(destination: M, transform: (Short) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ShortBuffer.associateWith(valueSelector: (Short) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > ShortBuffer.associateWithTo(destination: M, valueSelector: (Short) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > ShortBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun ShortBuffer.flatMap(transform: (Short) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > ShortBuffer.flatMapTo(destination: C, transform: (Short) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun ShortBuffer.groupBy(keySelector: (Short) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun ShortBuffer.groupBy(keySelector: (Short) -> K, valueTransform: (Short) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> ShortBuffer.groupByTo(destination: M, keySelector: (Short) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> ShortBuffer.groupByTo(destination: M, keySelector: (Short) -> K, valueTransform: (Short) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun ShortBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun ShortBuffer.distinctBy(selector: (Short) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun ShortBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun ShortBuffer.map(transform: (Short) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun ShortBuffer.mapIndexed(transform: (index: Int, Short) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > ShortBuffer.mapIndexedTo(destination: C, transform: (index: Int, Short) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > ShortBuffer.mapTo(destination: C, transform: (Short) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun ShortBuffer.all(predicate: (Short) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun ShortBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun ShortBuffer.any(predicate: (Short) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun ShortBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun ShortBuffer.count(predicate: (Short) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun ShortBuffer.forEach(action: (Short) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun ShortBuffer.forEachIndexed(action: (index: Int, Short) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ShortBuffer.max(): Short { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > ShortBuffer.maxBy(selector: (Short) -> R): Short { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > ShortBuffer.maxByOrNull(selector: (Short) -> R): Short? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun ShortBuffer.maxOrNull(): Short? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ShortBuffer.maxWith(comparator: Comparator): Short { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun ShortBuffer.maxWithOrNull(comparator: Comparator): Short? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ShortBuffer.min(): Short { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > ShortBuffer.minBy(selector: (Short) -> R): Short { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > ShortBuffer.minByOrNull(selector: (Short) -> R): Short? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun ShortBuffer.minOf(selector: (Short) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun ShortBuffer.minOf(selector: (Short) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > ShortBuffer.minOf(selector: (Short) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun ShortBuffer.minOfOrNull(selector: (Short) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun ShortBuffer.minOfOrNull(selector: (Short) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > ShortBuffer.minOfOrNull(selector: (Short) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun ShortBuffer.minOfWith(comparator: Comparator, selector: (Short) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun ShortBuffer.minOfWithOrNull(comparator: Comparator, selector: (Short) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun ShortBuffer.minOrNull(): Short? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ShortBuffer.minWith(comparator: Comparator): Short { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun ShortBuffer.minWithOrNull(comparator: Comparator): Short? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun ShortBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun ShortBuffer.none(predicate: (Short) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun ShortBuffer.onEach(action: (Short) -> Unit): ShortBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun ShortBuffer.onEachIndexed(action: (index: Int, Short) -> Unit): ShortBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun ShortBuffer.reduce(operation: (acc: Short, Short) -> Short): Short { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun ShortBuffer.reduceIndexed(operation: (index: Int, acc: Short, Short) -> Short): Short { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun ShortBuffer.reduceIndexedOrNull(operation: (index: Int, acc: Short, Short) -> Short): Short? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun ShortBuffer.reduceOrNull(operation: (acc: Short, Short) -> Short): Short? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun ShortBuffer.reduceRight(operation: (Short, acc: Short) -> Short): Short { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun ShortBuffer.reduceRightIndexed(operation: (index: Int, Short, acc: Short) -> Short): Short { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun ShortBuffer.reduceRightIndexedOrNull(operation: (index: Int, Short, acc: Short) -> Short): Short? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun ShortBuffer.reduceRightOrNull(operation: (Short, acc: Short) -> Short): Short? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun ShortBuffer.partition(predicate: (Short) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun ShortBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun ShortBuffer.zip(other: Array, transform: (a: Short, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun ShortBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun ShortBuffer.zip(other: Iterable, transform: (a: Short, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun ShortBuffer.zip(other: ShortArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun ShortBuffer.zip(other: ShortArray, transform: (a: Short, b: Short) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun ShortBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Short) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun ShortBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Short) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun IntBuffer.component1(): Int = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun IntBuffer.component2(): Int = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun IntBuffer.component3(): Int = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun IntBuffer.component4(): Int = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun IntBuffer.component5(): Int = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun IntBuffer.contains(element: Int): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun IntBuffer.elementAt(index: Int): Int = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun IntBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> Int): Int = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun IntBuffer.elementAtOrNull(index: Int): Int? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun IntBuffer.find(predicate: (Int) -> Boolean): Int? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun IntBuffer.findLast(predicate: (Int) -> Boolean): Int? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun IntBuffer.first(): Int { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun IntBuffer.first(predicate: (Int) -> Boolean): Int { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun IntBuffer.firstOrNull(): Int? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun IntBuffer.firstOrNull(predicate: (Int) -> Boolean): Int? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun IntBuffer.getOrElse(index: Int, defaultValue: (Int) -> Int): Int = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun IntBuffer.getOrNull(index: Int): Int? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun IntBuffer.indexOf(element: Int): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun IntBuffer.indexOfFirst(predicate: (Int) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun IntBuffer.indexOfLast(predicate: (Int) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun IntBuffer.last(): Int { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun IntBuffer.last(predicate: (Int) -> Boolean): Int { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun IntBuffer.lastIndexOf(element: Int): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun IntBuffer.lastOrNull(): Int? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun IntBuffer.lastOrNull(predicate: (Int) -> Boolean): Int? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun IntBuffer.single(): Int = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun IntBuffer.single(predicate: (Int) -> Boolean): Int { + var single: Int? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as Int +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun IntBuffer.singleOrNull(): Int? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun IntBuffer.singleOrNull(predicate: (Int) -> Boolean): Int? { + var single: Int? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun IntBuffer.filter(predicate: (Int) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun IntBuffer.filterIndexed(predicate: (index: Int, Int) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > IntBuffer.filterIndexedTo(destination: C, predicate: (index: Int, Int) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun IntBuffer.filterNot(predicate: (Int) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > IntBuffer.filterNotTo(destination: C, predicate: (Int) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > IntBuffer.filterTo(destination: C, predicate: (Int) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun IntBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun IntBuffer.sliceArray(indices: Collection): IntArray { + val result = IntArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun IntBuffer.sortDescending() { + if (rem > 1) { + val array = toIntArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun IntBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun IntBuffer.sortedArray(): IntArray = toIntArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun IntBuffer.sortedArrayDescending(): IntArray = toIntArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > IntBuffer.sortedBy(crossinline selector: (Int) -> R?): List = toIntArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > IntBuffer.sortedByDescending(crossinline selector: (Int) -> R?): List = toIntArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun IntBuffer.sortedDescending(): List = toIntArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun IntBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun IntBuffer.sort() { + if (rem > 1) { + val array = toIntArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun IntBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun IntBuffer.fill(element: Int, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val IntBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun IntBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun IntBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val IntBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun IntBuffer.toIntArray(): IntArray = IntArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun IntBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun IntBuffer.associate(transform: (Int) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun IntBuffer.associateBy(keySelector: (Int) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun IntBuffer.associateBy(keySelector: (Int) -> K, valueTransform: (Int) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > IntBuffer.associateByTo(destination: M, keySelector: (Int) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > IntBuffer.associateByTo(destination: M, keySelector: (Int) -> K, valueTransform: (Int) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > IntBuffer.associateTo(destination: M, transform: (Int) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun IntBuffer.associateWith(valueSelector: (Int) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > IntBuffer.associateWithTo(destination: M, valueSelector: (Int) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > IntBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun IntBuffer.flatMap(transform: (Int) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > IntBuffer.flatMapTo(destination: C, transform: (Int) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun IntBuffer.groupBy(keySelector: (Int) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun IntBuffer.groupBy(keySelector: (Int) -> K, valueTransform: (Int) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> IntBuffer.groupByTo(destination: M, keySelector: (Int) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> IntBuffer.groupByTo(destination: M, keySelector: (Int) -> K, valueTransform: (Int) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun IntBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun IntBuffer.distinctBy(selector: (Int) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun IntBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun IntBuffer.map(transform: (Int) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun IntBuffer.mapIndexed(transform: (index: Int, Int) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > IntBuffer.mapIndexedTo(destination: C, transform: (index: Int, Int) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > IntBuffer.mapTo(destination: C, transform: (Int) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun IntBuffer.all(predicate: (Int) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun IntBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun IntBuffer.any(predicate: (Int) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun IntBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun IntBuffer.count(predicate: (Int) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun IntBuffer.forEach(action: (Int) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun IntBuffer.forEachIndexed(action: (index: Int, Int) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun IntBuffer.max(): Int { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > IntBuffer.maxBy(selector: (Int) -> R): Int { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > IntBuffer.maxByOrNull(selector: (Int) -> R): Int? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun IntBuffer.maxOrNull(): Int? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun IntBuffer.maxWith(comparator: Comparator): Int { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun IntBuffer.maxWithOrNull(comparator: Comparator): Int? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun IntBuffer.min(): Int { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > IntBuffer.minBy(selector: (Int) -> R): Int { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > IntBuffer.minByOrNull(selector: (Int) -> R): Int? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun IntBuffer.minOf(selector: (Int) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun IntBuffer.minOf(selector: (Int) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > IntBuffer.minOf(selector: (Int) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun IntBuffer.minOfOrNull(selector: (Int) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun IntBuffer.minOfOrNull(selector: (Int) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > IntBuffer.minOfOrNull(selector: (Int) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun IntBuffer.minOfWith(comparator: Comparator, selector: (Int) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun IntBuffer.minOfWithOrNull(comparator: Comparator, selector: (Int) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun IntBuffer.minOrNull(): Int? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun IntBuffer.minWith(comparator: Comparator): Int { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun IntBuffer.minWithOrNull(comparator: Comparator): Int? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun IntBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun IntBuffer.none(predicate: (Int) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun IntBuffer.onEach(action: (Int) -> Unit): IntBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun IntBuffer.onEachIndexed(action: (index: Int, Int) -> Unit): IntBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun IntBuffer.reduce(operation: (acc: Int, Int) -> Int): Int { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun IntBuffer.reduceIndexed(operation: (index: Int, acc: Int, Int) -> Int): Int { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun IntBuffer.reduceIndexedOrNull(operation: (index: Int, acc: Int, Int) -> Int): Int? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun IntBuffer.reduceOrNull(operation: (acc: Int, Int) -> Int): Int? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun IntBuffer.reduceRight(operation: (Int, acc: Int) -> Int): Int { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun IntBuffer.reduceRightIndexed(operation: (index: Int, Int, acc: Int) -> Int): Int { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun IntBuffer.reduceRightIndexedOrNull(operation: (index: Int, Int, acc: Int) -> Int): Int? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun IntBuffer.reduceRightOrNull(operation: (Int, acc: Int) -> Int): Int? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun IntBuffer.partition(predicate: (Int) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun IntBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun IntBuffer.zip(other: Array, transform: (a: Int, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun IntBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun IntBuffer.zip(other: Iterable, transform: (a: Int, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun IntBuffer.zip(other: IntArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun IntBuffer.zip(other: IntArray, transform: (a: Int, b: Int) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun IntBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Int) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun IntBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Int) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun LongBuffer.component1(): Long = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun LongBuffer.component2(): Long = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun LongBuffer.component3(): Long = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun LongBuffer.component4(): Long = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun LongBuffer.component5(): Long = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun LongBuffer.contains(element: Long): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun LongBuffer.elementAt(index: Int): Long = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun LongBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> Long): Long = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun LongBuffer.elementAtOrNull(index: Int): Long? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun LongBuffer.find(predicate: (Long) -> Boolean): Long? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun LongBuffer.findLast(predicate: (Long) -> Boolean): Long? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun LongBuffer.first(): Long { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun LongBuffer.first(predicate: (Long) -> Boolean): Long { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun LongBuffer.firstOrNull(): Long? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun LongBuffer.firstOrNull(predicate: (Long) -> Boolean): Long? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun LongBuffer.getOrElse(index: Int, defaultValue: (Int) -> Long): Long = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun LongBuffer.getOrNull(index: Int): Long? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun LongBuffer.indexOf(element: Long): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun LongBuffer.indexOfFirst(predicate: (Long) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun LongBuffer.indexOfLast(predicate: (Long) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun LongBuffer.last(): Long { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun LongBuffer.last(predicate: (Long) -> Boolean): Long { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun LongBuffer.lastIndexOf(element: Long): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun LongBuffer.lastOrNull(): Long? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun LongBuffer.lastOrNull(predicate: (Long) -> Boolean): Long? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun LongBuffer.single(): Long = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun LongBuffer.single(predicate: (Long) -> Boolean): Long { + var single: Long? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as Long +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun LongBuffer.singleOrNull(): Long? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun LongBuffer.singleOrNull(predicate: (Long) -> Boolean): Long? { + var single: Long? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun LongBuffer.filter(predicate: (Long) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun LongBuffer.filterIndexed(predicate: (index: Int, Long) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > LongBuffer.filterIndexedTo(destination: C, predicate: (index: Int, Long) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun LongBuffer.filterNot(predicate: (Long) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > LongBuffer.filterNotTo(destination: C, predicate: (Long) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > LongBuffer.filterTo(destination: C, predicate: (Long) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun LongBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun LongBuffer.sliceArray(indices: Collection): LongArray { + val result = LongArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun LongBuffer.sortDescending() { + if (rem > 1) { + val array = toLongArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun LongBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun LongBuffer.sortedArray(): LongArray = toLongArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun LongBuffer.sortedArrayDescending(): LongArray = toLongArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > LongBuffer.sortedBy(crossinline selector: (Long) -> R?): List = toLongArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > LongBuffer.sortedByDescending(crossinline selector: (Long) -> R?): List = toLongArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun LongBuffer.sortedDescending(): List = toLongArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun LongBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun LongBuffer.sort() { + if (rem > 1) { + val array = toLongArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun LongBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun LongBuffer.fill(element: Long, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val LongBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun LongBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun LongBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val LongBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun LongBuffer.toLongArray(): LongArray = LongArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun LongBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun LongBuffer.associate(transform: (Long) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun LongBuffer.associateBy(keySelector: (Long) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun LongBuffer.associateBy(keySelector: (Long) -> K, valueTransform: (Long) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > LongBuffer.associateByTo(destination: M, keySelector: (Long) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > LongBuffer.associateByTo(destination: M, keySelector: (Long) -> K, valueTransform: (Long) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > LongBuffer.associateTo(destination: M, transform: (Long) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun LongBuffer.associateWith(valueSelector: (Long) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > LongBuffer.associateWithTo(destination: M, valueSelector: (Long) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > LongBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun LongBuffer.flatMap(transform: (Long) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > LongBuffer.flatMapTo(destination: C, transform: (Long) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun LongBuffer.groupBy(keySelector: (Long) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun LongBuffer.groupBy(keySelector: (Long) -> K, valueTransform: (Long) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> LongBuffer.groupByTo(destination: M, keySelector: (Long) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> LongBuffer.groupByTo(destination: M, keySelector: (Long) -> K, valueTransform: (Long) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun LongBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun LongBuffer.distinctBy(selector: (Long) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun LongBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun LongBuffer.map(transform: (Long) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun LongBuffer.mapIndexed(transform: (index: Int, Long) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > LongBuffer.mapIndexedTo(destination: C, transform: (index: Int, Long) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > LongBuffer.mapTo(destination: C, transform: (Long) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun LongBuffer.all(predicate: (Long) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun LongBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun LongBuffer.any(predicate: (Long) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun LongBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun LongBuffer.count(predicate: (Long) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun LongBuffer.forEach(action: (Long) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun LongBuffer.forEachIndexed(action: (index: Int, Long) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun LongBuffer.max(): Long { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > LongBuffer.maxBy(selector: (Long) -> R): Long { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > LongBuffer.maxByOrNull(selector: (Long) -> R): Long? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun LongBuffer.maxOrNull(): Long? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun LongBuffer.maxWith(comparator: Comparator): Long { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun LongBuffer.maxWithOrNull(comparator: Comparator): Long? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun LongBuffer.min(): Long { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > LongBuffer.minBy(selector: (Long) -> R): Long { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > LongBuffer.minByOrNull(selector: (Long) -> R): Long? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun LongBuffer.minOf(selector: (Long) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun LongBuffer.minOf(selector: (Long) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > LongBuffer.minOf(selector: (Long) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun LongBuffer.minOfOrNull(selector: (Long) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun LongBuffer.minOfOrNull(selector: (Long) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > LongBuffer.minOfOrNull(selector: (Long) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun LongBuffer.minOfWith(comparator: Comparator, selector: (Long) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun LongBuffer.minOfWithOrNull(comparator: Comparator, selector: (Long) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun LongBuffer.minOrNull(): Long? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun LongBuffer.minWith(comparator: Comparator): Long { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun LongBuffer.minWithOrNull(comparator: Comparator): Long? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun LongBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun LongBuffer.none(predicate: (Long) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun LongBuffer.onEach(action: (Long) -> Unit): LongBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun LongBuffer.onEachIndexed(action: (index: Int, Long) -> Unit): LongBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun LongBuffer.reduce(operation: (acc: Long, Long) -> Long): Long { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun LongBuffer.reduceIndexed(operation: (index: Int, acc: Long, Long) -> Long): Long { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun LongBuffer.reduceIndexedOrNull(operation: (index: Int, acc: Long, Long) -> Long): Long? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun LongBuffer.reduceOrNull(operation: (acc: Long, Long) -> Long): Long? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun LongBuffer.reduceRight(operation: (Long, acc: Long) -> Long): Long { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun LongBuffer.reduceRightIndexed(operation: (index: Int, Long, acc: Long) -> Long): Long { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun LongBuffer.reduceRightIndexedOrNull(operation: (index: Int, Long, acc: Long) -> Long): Long? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun LongBuffer.reduceRightOrNull(operation: (Long, acc: Long) -> Long): Long? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun LongBuffer.partition(predicate: (Long) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun LongBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun LongBuffer.zip(other: Array, transform: (a: Long, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun LongBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun LongBuffer.zip(other: Iterable, transform: (a: Long, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun LongBuffer.zip(other: LongArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun LongBuffer.zip(other: LongArray, transform: (a: Long, b: Long) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun LongBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Long) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun LongBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Long) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun UByteBuffer.component1(): UByte = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun UByteBuffer.component2(): UByte = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun UByteBuffer.component3(): UByte = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun UByteBuffer.component4(): UByte = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun UByteBuffer.component5(): UByte = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun UByteBuffer.contains(element: UByte): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun UByteBuffer.elementAt(index: Int): UByte = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun UByteBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> UByte): UByte = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun UByteBuffer.elementAtOrNull(index: Int): UByte? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun UByteBuffer.find(predicate: (UByte) -> Boolean): UByte? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun UByteBuffer.findLast(predicate: (UByte) -> Boolean): UByte? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UByteBuffer.first(): UByte { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun UByteBuffer.first(predicate: (UByte) -> Boolean): UByte { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun UByteBuffer.firstOrNull(): UByte? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun UByteBuffer.firstOrNull(predicate: (UByte) -> Boolean): UByte? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun UByteBuffer.getOrElse(index: Int, defaultValue: (Int) -> UByte): UByte = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun UByteBuffer.getOrNull(index: Int): UByte? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun UByteBuffer.indexOf(element: UByte): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun UByteBuffer.indexOfFirst(predicate: (UByte) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun UByteBuffer.indexOfLast(predicate: (UByte) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UByteBuffer.last(): UByte { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun UByteBuffer.last(predicate: (UByte) -> Boolean): UByte { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun UByteBuffer.lastIndexOf(element: UByte): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun UByteBuffer.lastOrNull(): UByte? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun UByteBuffer.lastOrNull(predicate: (UByte) -> Boolean): UByte? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun UByteBuffer.single(): UByte = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun UByteBuffer.single(predicate: (UByte) -> Boolean): UByte { + var single: UByte? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as UByte +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun UByteBuffer.singleOrNull(): UByte? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun UByteBuffer.singleOrNull(predicate: (UByte) -> Boolean): UByte? { + var single: UByte? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun UByteBuffer.filter(predicate: (UByte) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun UByteBuffer.filterIndexed(predicate: (index: Int, UByte) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > UByteBuffer.filterIndexedTo(destination: C, predicate: (index: Int, UByte) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun UByteBuffer.filterNot(predicate: (UByte) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > UByteBuffer.filterNotTo(destination: C, predicate: (UByte) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > UByteBuffer.filterTo(destination: C, predicate: (UByte) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun UByteBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun UByteBuffer.sliceArray(indices: Collection): UByteArray { + val result = UByteArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun UByteBuffer.sortDescending() { + if (rem > 1) { + val array = toUByteArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun UByteBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun UByteBuffer.sortedArray(): UByteArray = toUByteArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun UByteBuffer.sortedArrayDescending(): UByteArray = toUByteArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > UByteBuffer.sortedBy(crossinline selector: (UByte) -> R?): List = toUByteArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > UByteBuffer.sortedByDescending(crossinline selector: (UByte) -> R?): List = toUByteArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun UByteBuffer.sortedDescending(): List = toUByteArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun UByteBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun UByteBuffer.sort() { + if (rem > 1) { + val array = toUByteArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun UByteBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun UByteBuffer.fill(element: UByte, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val UByteBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun UByteBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun UByteBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val UByteBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun UByteBuffer.toUByteArray(): UByteArray = UByteArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun UByteBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UByteBuffer.associate(transform: (UByte) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UByteBuffer.associateBy(keySelector: (UByte) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UByteBuffer.associateBy(keySelector: (UByte) -> K, valueTransform: (UByte) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > UByteBuffer.associateByTo(destination: M, keySelector: (UByte) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > UByteBuffer.associateByTo(destination: M, keySelector: (UByte) -> K, valueTransform: (UByte) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > UByteBuffer.associateTo(destination: M, transform: (UByte) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UByteBuffer.associateWith(valueSelector: (UByte) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > UByteBuffer.associateWithTo(destination: M, valueSelector: (UByte) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > UByteBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun UByteBuffer.flatMap(transform: (UByte) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > UByteBuffer.flatMapTo(destination: C, transform: (UByte) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun UByteBuffer.groupBy(keySelector: (UByte) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun UByteBuffer.groupBy(keySelector: (UByte) -> K, valueTransform: (UByte) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> UByteBuffer.groupByTo(destination: M, keySelector: (UByte) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> UByteBuffer.groupByTo(destination: M, keySelector: (UByte) -> K, valueTransform: (UByte) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun UByteBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun UByteBuffer.distinctBy(selector: (UByte) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun UByteBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun UByteBuffer.map(transform: (UByte) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun UByteBuffer.mapIndexed(transform: (index: Int, UByte) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > UByteBuffer.mapIndexedTo(destination: C, transform: (index: Int, UByte) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > UByteBuffer.mapTo(destination: C, transform: (UByte) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun UByteBuffer.all(predicate: (UByte) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun UByteBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun UByteBuffer.any(predicate: (UByte) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun UByteBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun UByteBuffer.count(predicate: (UByte) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun UByteBuffer.forEach(action: (UByte) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun UByteBuffer.forEachIndexed(action: (index: Int, UByte) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UByteBuffer.max(): UByte { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > UByteBuffer.maxBy(selector: (UByte) -> R): UByte { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > UByteBuffer.maxByOrNull(selector: (UByte) -> R): UByte? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun UByteBuffer.maxOrNull(): UByte? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UByteBuffer.maxWith(comparator: Comparator): UByte { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun UByteBuffer.maxWithOrNull(comparator: Comparator): UByte? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UByteBuffer.min(): UByte { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > UByteBuffer.minBy(selector: (UByte) -> R): UByte { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > UByteBuffer.minByOrNull(selector: (UByte) -> R): UByte? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun UByteBuffer.minOf(selector: (UByte) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun UByteBuffer.minOf(selector: (UByte) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > UByteBuffer.minOf(selector: (UByte) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun UByteBuffer.minOfOrNull(selector: (UByte) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun UByteBuffer.minOfOrNull(selector: (UByte) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > UByteBuffer.minOfOrNull(selector: (UByte) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun UByteBuffer.minOfWith(comparator: Comparator, selector: (UByte) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun UByteBuffer.minOfWithOrNull(comparator: Comparator, selector: (UByte) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun UByteBuffer.minOrNull(): UByte? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UByteBuffer.minWith(comparator: Comparator): UByte { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun UByteBuffer.minWithOrNull(comparator: Comparator): UByte? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun UByteBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun UByteBuffer.none(predicate: (UByte) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun UByteBuffer.onEach(action: (UByte) -> Unit): UByteBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun UByteBuffer.onEachIndexed(action: (index: Int, UByte) -> Unit): UByteBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun UByteBuffer.reduce(operation: (acc: UByte, UByte) -> UByte): UByte { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun UByteBuffer.reduceIndexed(operation: (index: Int, acc: UByte, UByte) -> UByte): UByte { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun UByteBuffer.reduceIndexedOrNull(operation: (index: Int, acc: UByte, UByte) -> UByte): UByte? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun UByteBuffer.reduceOrNull(operation: (acc: UByte, UByte) -> UByte): UByte? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun UByteBuffer.reduceRight(operation: (UByte, acc: UByte) -> UByte): UByte { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun UByteBuffer.reduceRightIndexed(operation: (index: Int, UByte, acc: UByte) -> UByte): UByte { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun UByteBuffer.reduceRightIndexedOrNull(operation: (index: Int, UByte, acc: UByte) -> UByte): UByte? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun UByteBuffer.reduceRightOrNull(operation: (UByte, acc: UByte) -> UByte): UByte? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun UByteBuffer.partition(predicate: (UByte) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun UByteBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun UByteBuffer.zip(other: Array, transform: (a: UByte, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun UByteBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun UByteBuffer.zip(other: Iterable, transform: (a: UByte, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun UByteBuffer.zip(other: UByteArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun UByteBuffer.zip(other: UByteArray, transform: (a: UByte, b: UByte) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun UByteBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((UByte) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun UByteBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((UByte) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun UShortBuffer.component1(): UShort = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun UShortBuffer.component2(): UShort = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun UShortBuffer.component3(): UShort = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun UShortBuffer.component4(): UShort = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun UShortBuffer.component5(): UShort = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun UShortBuffer.contains(element: UShort): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun UShortBuffer.elementAt(index: Int): UShort = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun UShortBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> UShort): UShort = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun UShortBuffer.elementAtOrNull(index: Int): UShort? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun UShortBuffer.find(predicate: (UShort) -> Boolean): UShort? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun UShortBuffer.findLast(predicate: (UShort) -> Boolean): UShort? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UShortBuffer.first(): UShort { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun UShortBuffer.first(predicate: (UShort) -> Boolean): UShort { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun UShortBuffer.firstOrNull(): UShort? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun UShortBuffer.firstOrNull(predicate: (UShort) -> Boolean): UShort? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun UShortBuffer.getOrElse(index: Int, defaultValue: (Int) -> UShort): UShort = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun UShortBuffer.getOrNull(index: Int): UShort? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun UShortBuffer.indexOf(element: UShort): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun UShortBuffer.indexOfFirst(predicate: (UShort) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun UShortBuffer.indexOfLast(predicate: (UShort) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UShortBuffer.last(): UShort { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun UShortBuffer.last(predicate: (UShort) -> Boolean): UShort { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun UShortBuffer.lastIndexOf(element: UShort): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun UShortBuffer.lastOrNull(): UShort? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun UShortBuffer.lastOrNull(predicate: (UShort) -> Boolean): UShort? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun UShortBuffer.single(): UShort = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun UShortBuffer.single(predicate: (UShort) -> Boolean): UShort { + var single: UShort? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as UShort +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun UShortBuffer.singleOrNull(): UShort? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun UShortBuffer.singleOrNull(predicate: (UShort) -> Boolean): UShort? { + var single: UShort? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun UShortBuffer.filter(predicate: (UShort) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun UShortBuffer.filterIndexed(predicate: (index: Int, UShort) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > UShortBuffer.filterIndexedTo(destination: C, predicate: (index: Int, UShort) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun UShortBuffer.filterNot(predicate: (UShort) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > UShortBuffer.filterNotTo(destination: C, predicate: (UShort) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > UShortBuffer.filterTo(destination: C, predicate: (UShort) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun UShortBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun UShortBuffer.sliceArray(indices: Collection): UShortArray { + val result = UShortArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun UShortBuffer.sortDescending() { + if (rem > 1) { + val array = toUShortArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun UShortBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun UShortBuffer.sortedArray(): UShortArray = toUShortArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun UShortBuffer.sortedArrayDescending(): UShortArray = toUShortArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > UShortBuffer.sortedBy(crossinline selector: (UShort) -> R?): List = toUShortArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > UShortBuffer.sortedByDescending(crossinline selector: (UShort) -> R?): List = toUShortArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun UShortBuffer.sortedDescending(): List = toUShortArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun UShortBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun UShortBuffer.sort() { + if (rem > 1) { + val array = toUShortArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun UShortBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun UShortBuffer.fill(element: UShort, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val UShortBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun UShortBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun UShortBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val UShortBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun UShortBuffer.toUShortArray(): UShortArray = UShortArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun UShortBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UShortBuffer.associate(transform: (UShort) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UShortBuffer.associateBy(keySelector: (UShort) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UShortBuffer.associateBy(keySelector: (UShort) -> K, valueTransform: (UShort) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > UShortBuffer.associateByTo(destination: M, keySelector: (UShort) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > UShortBuffer.associateByTo(destination: M, keySelector: (UShort) -> K, valueTransform: (UShort) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > UShortBuffer.associateTo(destination: M, transform: (UShort) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UShortBuffer.associateWith(valueSelector: (UShort) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > UShortBuffer.associateWithTo(destination: M, valueSelector: (UShort) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > UShortBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun UShortBuffer.flatMap(transform: (UShort) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > UShortBuffer.flatMapTo(destination: C, transform: (UShort) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun UShortBuffer.groupBy(keySelector: (UShort) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun UShortBuffer.groupBy(keySelector: (UShort) -> K, valueTransform: (UShort) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> UShortBuffer.groupByTo(destination: M, keySelector: (UShort) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> UShortBuffer.groupByTo(destination: M, keySelector: (UShort) -> K, valueTransform: (UShort) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun UShortBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun UShortBuffer.distinctBy(selector: (UShort) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun UShortBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun UShortBuffer.map(transform: (UShort) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun UShortBuffer.mapIndexed(transform: (index: Int, UShort) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > UShortBuffer.mapIndexedTo(destination: C, transform: (index: Int, UShort) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > UShortBuffer.mapTo(destination: C, transform: (UShort) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun UShortBuffer.all(predicate: (UShort) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun UShortBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun UShortBuffer.any(predicate: (UShort) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun UShortBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun UShortBuffer.count(predicate: (UShort) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun UShortBuffer.forEach(action: (UShort) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun UShortBuffer.forEachIndexed(action: (index: Int, UShort) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UShortBuffer.max(): UShort { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > UShortBuffer.maxBy(selector: (UShort) -> R): UShort { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > UShortBuffer.maxByOrNull(selector: (UShort) -> R): UShort? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun UShortBuffer.maxOrNull(): UShort? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UShortBuffer.maxWith(comparator: Comparator): UShort { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun UShortBuffer.maxWithOrNull(comparator: Comparator): UShort? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UShortBuffer.min(): UShort { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > UShortBuffer.minBy(selector: (UShort) -> R): UShort { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > UShortBuffer.minByOrNull(selector: (UShort) -> R): UShort? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun UShortBuffer.minOf(selector: (UShort) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun UShortBuffer.minOf(selector: (UShort) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > UShortBuffer.minOf(selector: (UShort) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun UShortBuffer.minOfOrNull(selector: (UShort) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun UShortBuffer.minOfOrNull(selector: (UShort) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > UShortBuffer.minOfOrNull(selector: (UShort) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun UShortBuffer.minOfWith(comparator: Comparator, selector: (UShort) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun UShortBuffer.minOfWithOrNull(comparator: Comparator, selector: (UShort) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun UShortBuffer.minOrNull(): UShort? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UShortBuffer.minWith(comparator: Comparator): UShort { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun UShortBuffer.minWithOrNull(comparator: Comparator): UShort? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun UShortBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun UShortBuffer.none(predicate: (UShort) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun UShortBuffer.onEach(action: (UShort) -> Unit): UShortBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun UShortBuffer.onEachIndexed(action: (index: Int, UShort) -> Unit): UShortBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun UShortBuffer.reduce(operation: (acc: UShort, UShort) -> UShort): UShort { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun UShortBuffer.reduceIndexed(operation: (index: Int, acc: UShort, UShort) -> UShort): UShort { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun UShortBuffer.reduceIndexedOrNull(operation: (index: Int, acc: UShort, UShort) -> UShort): UShort? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun UShortBuffer.reduceOrNull(operation: (acc: UShort, UShort) -> UShort): UShort? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun UShortBuffer.reduceRight(operation: (UShort, acc: UShort) -> UShort): UShort { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun UShortBuffer.reduceRightIndexed(operation: (index: Int, UShort, acc: UShort) -> UShort): UShort { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun UShortBuffer.reduceRightIndexedOrNull(operation: (index: Int, UShort, acc: UShort) -> UShort): UShort? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun UShortBuffer.reduceRightOrNull(operation: (UShort, acc: UShort) -> UShort): UShort? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun UShortBuffer.partition(predicate: (UShort) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun UShortBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun UShortBuffer.zip(other: Array, transform: (a: UShort, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun UShortBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun UShortBuffer.zip(other: Iterable, transform: (a: UShort, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun UShortBuffer.zip(other: UShortArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun UShortBuffer.zip(other: UShortArray, transform: (a: UShort, b: UShort) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun UShortBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((UShort) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun UShortBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((UShort) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun UIntBuffer.component1(): UInt = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun UIntBuffer.component2(): UInt = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun UIntBuffer.component3(): UInt = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun UIntBuffer.component4(): UInt = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun UIntBuffer.component5(): UInt = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun UIntBuffer.contains(element: UInt): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun UIntBuffer.elementAt(index: Int): UInt = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun UIntBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> UInt): UInt = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun UIntBuffer.elementAtOrNull(index: Int): UInt? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun UIntBuffer.find(predicate: (UInt) -> Boolean): UInt? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun UIntBuffer.findLast(predicate: (UInt) -> Boolean): UInt? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UIntBuffer.first(): UInt { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun UIntBuffer.first(predicate: (UInt) -> Boolean): UInt { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun UIntBuffer.firstOrNull(): UInt? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun UIntBuffer.firstOrNull(predicate: (UInt) -> Boolean): UInt? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun UIntBuffer.getOrElse(index: Int, defaultValue: (Int) -> UInt): UInt = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun UIntBuffer.getOrNull(index: Int): UInt? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun UIntBuffer.indexOf(element: UInt): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun UIntBuffer.indexOfFirst(predicate: (UInt) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun UIntBuffer.indexOfLast(predicate: (UInt) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UIntBuffer.last(): UInt { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun UIntBuffer.last(predicate: (UInt) -> Boolean): UInt { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun UIntBuffer.lastIndexOf(element: UInt): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun UIntBuffer.lastOrNull(): UInt? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun UIntBuffer.lastOrNull(predicate: (UInt) -> Boolean): UInt? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun UIntBuffer.single(): UInt = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun UIntBuffer.single(predicate: (UInt) -> Boolean): UInt { + var single: UInt? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as UInt +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun UIntBuffer.singleOrNull(): UInt? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun UIntBuffer.singleOrNull(predicate: (UInt) -> Boolean): UInt? { + var single: UInt? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun UIntBuffer.filter(predicate: (UInt) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun UIntBuffer.filterIndexed(predicate: (index: Int, UInt) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > UIntBuffer.filterIndexedTo(destination: C, predicate: (index: Int, UInt) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun UIntBuffer.filterNot(predicate: (UInt) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > UIntBuffer.filterNotTo(destination: C, predicate: (UInt) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > UIntBuffer.filterTo(destination: C, predicate: (UInt) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun UIntBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun UIntBuffer.sliceArray(indices: Collection): UIntArray { + val result = UIntArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun UIntBuffer.sortDescending() { + if (rem > 1) { + val array = toUIntArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun UIntBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun UIntBuffer.sortedArray(): UIntArray = toUIntArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun UIntBuffer.sortedArrayDescending(): UIntArray = toUIntArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > UIntBuffer.sortedBy(crossinline selector: (UInt) -> R?): List = toUIntArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > UIntBuffer.sortedByDescending(crossinline selector: (UInt) -> R?): List = toUIntArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun UIntBuffer.sortedDescending(): List = toUIntArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun UIntBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun UIntBuffer.sort() { + if (rem > 1) { + val array = toUIntArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun UIntBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun UIntBuffer.fill(element: UInt, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val UIntBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun UIntBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun UIntBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val UIntBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun UIntBuffer.toUIntArray(): UIntArray = UIntArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun UIntBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UIntBuffer.associate(transform: (UInt) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UIntBuffer.associateBy(keySelector: (UInt) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UIntBuffer.associateBy(keySelector: (UInt) -> K, valueTransform: (UInt) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > UIntBuffer.associateByTo(destination: M, keySelector: (UInt) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > UIntBuffer.associateByTo(destination: M, keySelector: (UInt) -> K, valueTransform: (UInt) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > UIntBuffer.associateTo(destination: M, transform: (UInt) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun UIntBuffer.associateWith(valueSelector: (UInt) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > UIntBuffer.associateWithTo(destination: M, valueSelector: (UInt) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > UIntBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun UIntBuffer.flatMap(transform: (UInt) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > UIntBuffer.flatMapTo(destination: C, transform: (UInt) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun UIntBuffer.groupBy(keySelector: (UInt) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun UIntBuffer.groupBy(keySelector: (UInt) -> K, valueTransform: (UInt) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> UIntBuffer.groupByTo(destination: M, keySelector: (UInt) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> UIntBuffer.groupByTo(destination: M, keySelector: (UInt) -> K, valueTransform: (UInt) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun UIntBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun UIntBuffer.distinctBy(selector: (UInt) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun UIntBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun UIntBuffer.map(transform: (UInt) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun UIntBuffer.mapIndexed(transform: (index: Int, UInt) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > UIntBuffer.mapIndexedTo(destination: C, transform: (index: Int, UInt) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > UIntBuffer.mapTo(destination: C, transform: (UInt) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun UIntBuffer.all(predicate: (UInt) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun UIntBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun UIntBuffer.any(predicate: (UInt) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun UIntBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun UIntBuffer.count(predicate: (UInt) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun UIntBuffer.forEach(action: (UInt) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun UIntBuffer.forEachIndexed(action: (index: Int, UInt) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UIntBuffer.max(): UInt { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > UIntBuffer.maxBy(selector: (UInt) -> R): UInt { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > UIntBuffer.maxByOrNull(selector: (UInt) -> R): UInt? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun UIntBuffer.maxOrNull(): UInt? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UIntBuffer.maxWith(comparator: Comparator): UInt { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun UIntBuffer.maxWithOrNull(comparator: Comparator): UInt? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UIntBuffer.min(): UInt { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > UIntBuffer.minBy(selector: (UInt) -> R): UInt { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > UIntBuffer.minByOrNull(selector: (UInt) -> R): UInt? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun UIntBuffer.minOf(selector: (UInt) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun UIntBuffer.minOf(selector: (UInt) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > UIntBuffer.minOf(selector: (UInt) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun UIntBuffer.minOfOrNull(selector: (UInt) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun UIntBuffer.minOfOrNull(selector: (UInt) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > UIntBuffer.minOfOrNull(selector: (UInt) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun UIntBuffer.minOfWith(comparator: Comparator, selector: (UInt) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun UIntBuffer.minOfWithOrNull(comparator: Comparator, selector: (UInt) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun UIntBuffer.minOrNull(): UInt? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun UIntBuffer.minWith(comparator: Comparator): UInt { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun UIntBuffer.minWithOrNull(comparator: Comparator): UInt? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun UIntBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun UIntBuffer.none(predicate: (UInt) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun UIntBuffer.onEach(action: (UInt) -> Unit): UIntBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun UIntBuffer.onEachIndexed(action: (index: Int, UInt) -> Unit): UIntBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun UIntBuffer.reduce(operation: (acc: UInt, UInt) -> UInt): UInt { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun UIntBuffer.reduceIndexed(operation: (index: Int, acc: UInt, UInt) -> UInt): UInt { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun UIntBuffer.reduceIndexedOrNull(operation: (index: Int, acc: UInt, UInt) -> UInt): UInt? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun UIntBuffer.reduceOrNull(operation: (acc: UInt, UInt) -> UInt): UInt? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun UIntBuffer.reduceRight(operation: (UInt, acc: UInt) -> UInt): UInt { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun UIntBuffer.reduceRightIndexed(operation: (index: Int, UInt, acc: UInt) -> UInt): UInt { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun UIntBuffer.reduceRightIndexedOrNull(operation: (index: Int, UInt, acc: UInt) -> UInt): UInt? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun UIntBuffer.reduceRightOrNull(operation: (UInt, acc: UInt) -> UInt): UInt? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun UIntBuffer.partition(predicate: (UInt) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun UIntBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun UIntBuffer.zip(other: Array, transform: (a: UInt, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun UIntBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun UIntBuffer.zip(other: Iterable, transform: (a: UInt, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun UIntBuffer.zip(other: UIntArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun UIntBuffer.zip(other: UIntArray, transform: (a: UInt, b: UInt) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun UIntBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((UInt) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun UIntBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((UInt) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun ULongBuffer.component1(): ULong = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun ULongBuffer.component2(): ULong = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun ULongBuffer.component3(): ULong = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun ULongBuffer.component4(): ULong = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun ULongBuffer.component5(): ULong = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun ULongBuffer.contains(element: ULong): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun ULongBuffer.elementAt(index: Int): ULong = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun ULongBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> ULong): ULong = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun ULongBuffer.elementAtOrNull(index: Int): ULong? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun ULongBuffer.find(predicate: (ULong) -> Boolean): ULong? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun ULongBuffer.findLast(predicate: (ULong) -> Boolean): ULong? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ULongBuffer.first(): ULong { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun ULongBuffer.first(predicate: (ULong) -> Boolean): ULong { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun ULongBuffer.firstOrNull(): ULong? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun ULongBuffer.firstOrNull(predicate: (ULong) -> Boolean): ULong? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun ULongBuffer.getOrElse(index: Int, defaultValue: (Int) -> ULong): ULong = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun ULongBuffer.getOrNull(index: Int): ULong? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun ULongBuffer.indexOf(element: ULong): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun ULongBuffer.indexOfFirst(predicate: (ULong) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun ULongBuffer.indexOfLast(predicate: (ULong) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ULongBuffer.last(): ULong { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun ULongBuffer.last(predicate: (ULong) -> Boolean): ULong { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun ULongBuffer.lastIndexOf(element: ULong): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun ULongBuffer.lastOrNull(): ULong? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun ULongBuffer.lastOrNull(predicate: (ULong) -> Boolean): ULong? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun ULongBuffer.single(): ULong = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun ULongBuffer.single(predicate: (ULong) -> Boolean): ULong { + var single: ULong? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as ULong +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun ULongBuffer.singleOrNull(): ULong? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun ULongBuffer.singleOrNull(predicate: (ULong) -> Boolean): ULong? { + var single: ULong? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun ULongBuffer.filter(predicate: (ULong) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun ULongBuffer.filterIndexed(predicate: (index: Int, ULong) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > ULongBuffer.filterIndexedTo(destination: C, predicate: (index: Int, ULong) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun ULongBuffer.filterNot(predicate: (ULong) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > ULongBuffer.filterNotTo(destination: C, predicate: (ULong) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > ULongBuffer.filterTo(destination: C, predicate: (ULong) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun ULongBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun ULongBuffer.sliceArray(indices: Collection): ULongArray { + val result = ULongArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun ULongBuffer.sortDescending() { + if (rem > 1) { + val array = toULongArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun ULongBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun ULongBuffer.sortedArray(): ULongArray = toULongArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun ULongBuffer.sortedArrayDescending(): ULongArray = toULongArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > ULongBuffer.sortedBy(crossinline selector: (ULong) -> R?): List = toULongArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > ULongBuffer.sortedByDescending(crossinline selector: (ULong) -> R?): List = toULongArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun ULongBuffer.sortedDescending(): List = toULongArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun ULongBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun ULongBuffer.sort() { + if (rem > 1) { + val array = toULongArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun ULongBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun ULongBuffer.fill(element: ULong, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val ULongBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun ULongBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun ULongBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val ULongBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun ULongBuffer.toULongArray(): ULongArray = ULongArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun ULongBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ULongBuffer.associate(transform: (ULong) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ULongBuffer.associateBy(keySelector: (ULong) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ULongBuffer.associateBy(keySelector: (ULong) -> K, valueTransform: (ULong) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > ULongBuffer.associateByTo(destination: M, keySelector: (ULong) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > ULongBuffer.associateByTo(destination: M, keySelector: (ULong) -> K, valueTransform: (ULong) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > ULongBuffer.associateTo(destination: M, transform: (ULong) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun ULongBuffer.associateWith(valueSelector: (ULong) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > ULongBuffer.associateWithTo(destination: M, valueSelector: (ULong) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > ULongBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun ULongBuffer.flatMap(transform: (ULong) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > ULongBuffer.flatMapTo(destination: C, transform: (ULong) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun ULongBuffer.groupBy(keySelector: (ULong) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun ULongBuffer.groupBy(keySelector: (ULong) -> K, valueTransform: (ULong) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> ULongBuffer.groupByTo(destination: M, keySelector: (ULong) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> ULongBuffer.groupByTo(destination: M, keySelector: (ULong) -> K, valueTransform: (ULong) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun ULongBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun ULongBuffer.distinctBy(selector: (ULong) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun ULongBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun ULongBuffer.map(transform: (ULong) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun ULongBuffer.mapIndexed(transform: (index: Int, ULong) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > ULongBuffer.mapIndexedTo(destination: C, transform: (index: Int, ULong) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > ULongBuffer.mapTo(destination: C, transform: (ULong) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun ULongBuffer.all(predicate: (ULong) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun ULongBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun ULongBuffer.any(predicate: (ULong) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun ULongBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun ULongBuffer.count(predicate: (ULong) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun ULongBuffer.forEach(action: (ULong) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun ULongBuffer.forEachIndexed(action: (index: Int, ULong) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ULongBuffer.max(): ULong { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > ULongBuffer.maxBy(selector: (ULong) -> R): ULong { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > ULongBuffer.maxByOrNull(selector: (ULong) -> R): ULong? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun ULongBuffer.maxOrNull(): ULong? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ULongBuffer.maxWith(comparator: Comparator): ULong { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun ULongBuffer.maxWithOrNull(comparator: Comparator): ULong? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ULongBuffer.min(): ULong { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > ULongBuffer.minBy(selector: (ULong) -> R): ULong { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > ULongBuffer.minByOrNull(selector: (ULong) -> R): ULong? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun ULongBuffer.minOf(selector: (ULong) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun ULongBuffer.minOf(selector: (ULong) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > ULongBuffer.minOf(selector: (ULong) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun ULongBuffer.minOfOrNull(selector: (ULong) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun ULongBuffer.minOfOrNull(selector: (ULong) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > ULongBuffer.minOfOrNull(selector: (ULong) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun ULongBuffer.minOfWith(comparator: Comparator, selector: (ULong) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun ULongBuffer.minOfWithOrNull(comparator: Comparator, selector: (ULong) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun ULongBuffer.minOrNull(): ULong? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun ULongBuffer.minWith(comparator: Comparator): ULong { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun ULongBuffer.minWithOrNull(comparator: Comparator): ULong? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun ULongBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun ULongBuffer.none(predicate: (ULong) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun ULongBuffer.onEach(action: (ULong) -> Unit): ULongBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun ULongBuffer.onEachIndexed(action: (index: Int, ULong) -> Unit): ULongBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun ULongBuffer.reduce(operation: (acc: ULong, ULong) -> ULong): ULong { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun ULongBuffer.reduceIndexed(operation: (index: Int, acc: ULong, ULong) -> ULong): ULong { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun ULongBuffer.reduceIndexedOrNull(operation: (index: Int, acc: ULong, ULong) -> ULong): ULong? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun ULongBuffer.reduceOrNull(operation: (acc: ULong, ULong) -> ULong): ULong? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun ULongBuffer.reduceRight(operation: (ULong, acc: ULong) -> ULong): ULong { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun ULongBuffer.reduceRightIndexed(operation: (index: Int, ULong, acc: ULong) -> ULong): ULong { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun ULongBuffer.reduceRightIndexedOrNull(operation: (index: Int, ULong, acc: ULong) -> ULong): ULong? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun ULongBuffer.reduceRightOrNull(operation: (ULong, acc: ULong) -> ULong): ULong? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun ULongBuffer.partition(predicate: (ULong) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun ULongBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun ULongBuffer.zip(other: Array, transform: (a: ULong, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun ULongBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun ULongBuffer.zip(other: Iterable, transform: (a: ULong, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun ULongBuffer.zip(other: ULongArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun ULongBuffer.zip(other: ULongArray, transform: (a: ULong, b: ULong) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun ULongBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((ULong) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun ULongBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((ULong) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun FloatBuffer.component1(): Float = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun FloatBuffer.component2(): Float = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun FloatBuffer.component3(): Float = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun FloatBuffer.component4(): Float = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun FloatBuffer.component5(): Float = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun FloatBuffer.contains(element: Float): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun FloatBuffer.elementAt(index: Int): Float = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun FloatBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> Float): Float = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun FloatBuffer.elementAtOrNull(index: Int): Float? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun FloatBuffer.find(predicate: (Float) -> Boolean): Float? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun FloatBuffer.findLast(predicate: (Float) -> Boolean): Float? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun FloatBuffer.first(): Float { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun FloatBuffer.first(predicate: (Float) -> Boolean): Float { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun FloatBuffer.firstOrNull(): Float? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun FloatBuffer.firstOrNull(predicate: (Float) -> Boolean): Float? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun FloatBuffer.getOrElse(index: Int, defaultValue: (Int) -> Float): Float = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun FloatBuffer.getOrNull(index: Int): Float? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun FloatBuffer.indexOf(element: Float): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun FloatBuffer.indexOfFirst(predicate: (Float) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun FloatBuffer.indexOfLast(predicate: (Float) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun FloatBuffer.last(): Float { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun FloatBuffer.last(predicate: (Float) -> Boolean): Float { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun FloatBuffer.lastIndexOf(element: Float): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun FloatBuffer.lastOrNull(): Float? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun FloatBuffer.lastOrNull(predicate: (Float) -> Boolean): Float? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun FloatBuffer.single(): Float = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun FloatBuffer.single(predicate: (Float) -> Boolean): Float { + var single: Float? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as Float +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun FloatBuffer.singleOrNull(): Float? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun FloatBuffer.singleOrNull(predicate: (Float) -> Boolean): Float? { + var single: Float? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun FloatBuffer.filter(predicate: (Float) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun FloatBuffer.filterIndexed(predicate: (index: Int, Float) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > FloatBuffer.filterIndexedTo(destination: C, predicate: (index: Int, Float) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun FloatBuffer.filterNot(predicate: (Float) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > FloatBuffer.filterNotTo(destination: C, predicate: (Float) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > FloatBuffer.filterTo(destination: C, predicate: (Float) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun FloatBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun FloatBuffer.sliceArray(indices: Collection): FloatArray { + val result = FloatArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun FloatBuffer.sortDescending() { + if (rem > 1) { + val array = toFloatArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun FloatBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun FloatBuffer.sortedArray(): FloatArray = toFloatArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun FloatBuffer.sortedArrayDescending(): FloatArray = toFloatArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > FloatBuffer.sortedBy(crossinline selector: (Float) -> R?): List = toFloatArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > FloatBuffer.sortedByDescending(crossinline selector: (Float) -> R?): List = toFloatArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun FloatBuffer.sortedDescending(): List = toFloatArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun FloatBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun FloatBuffer.sort() { + if (rem > 1) { + val array = toFloatArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun FloatBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun FloatBuffer.fill(element: Float, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val FloatBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun FloatBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun FloatBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val FloatBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun FloatBuffer.toFloatArray(): FloatArray = FloatArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun FloatBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun FloatBuffer.associate(transform: (Float) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun FloatBuffer.associateBy(keySelector: (Float) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun FloatBuffer.associateBy(keySelector: (Float) -> K, valueTransform: (Float) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > FloatBuffer.associateByTo(destination: M, keySelector: (Float) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > FloatBuffer.associateByTo(destination: M, keySelector: (Float) -> K, valueTransform: (Float) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > FloatBuffer.associateTo(destination: M, transform: (Float) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun FloatBuffer.associateWith(valueSelector: (Float) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > FloatBuffer.associateWithTo(destination: M, valueSelector: (Float) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > FloatBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun FloatBuffer.flatMap(transform: (Float) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > FloatBuffer.flatMapTo(destination: C, transform: (Float) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun FloatBuffer.groupBy(keySelector: (Float) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun FloatBuffer.groupBy(keySelector: (Float) -> K, valueTransform: (Float) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> FloatBuffer.groupByTo(destination: M, keySelector: (Float) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> FloatBuffer.groupByTo(destination: M, keySelector: (Float) -> K, valueTransform: (Float) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun FloatBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun FloatBuffer.distinctBy(selector: (Float) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun FloatBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun FloatBuffer.map(transform: (Float) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun FloatBuffer.mapIndexed(transform: (index: Int, Float) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > FloatBuffer.mapIndexedTo(destination: C, transform: (index: Int, Float) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > FloatBuffer.mapTo(destination: C, transform: (Float) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun FloatBuffer.all(predicate: (Float) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun FloatBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun FloatBuffer.any(predicate: (Float) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun FloatBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun FloatBuffer.count(predicate: (Float) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun FloatBuffer.forEach(action: (Float) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun FloatBuffer.forEachIndexed(action: (index: Int, Float) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun FloatBuffer.max(): Float { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > FloatBuffer.maxBy(selector: (Float) -> R): Float { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > FloatBuffer.maxByOrNull(selector: (Float) -> R): Float? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun FloatBuffer.maxOrNull(): Float? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun FloatBuffer.maxWith(comparator: Comparator): Float { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun FloatBuffer.maxWithOrNull(comparator: Comparator): Float? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun FloatBuffer.min(): Float { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > FloatBuffer.minBy(selector: (Float) -> R): Float { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > FloatBuffer.minByOrNull(selector: (Float) -> R): Float? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun FloatBuffer.minOf(selector: (Float) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun FloatBuffer.minOf(selector: (Float) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > FloatBuffer.minOf(selector: (Float) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun FloatBuffer.minOfOrNull(selector: (Float) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun FloatBuffer.minOfOrNull(selector: (Float) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > FloatBuffer.minOfOrNull(selector: (Float) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun FloatBuffer.minOfWith(comparator: Comparator, selector: (Float) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun FloatBuffer.minOfWithOrNull(comparator: Comparator, selector: (Float) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun FloatBuffer.minOrNull(): Float? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun FloatBuffer.minWith(comparator: Comparator): Float { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun FloatBuffer.minWithOrNull(comparator: Comparator): Float? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun FloatBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun FloatBuffer.none(predicate: (Float) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun FloatBuffer.onEach(action: (Float) -> Unit): FloatBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun FloatBuffer.onEachIndexed(action: (index: Int, Float) -> Unit): FloatBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun FloatBuffer.reduce(operation: (acc: Float, Float) -> Float): Float { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun FloatBuffer.reduceIndexed(operation: (index: Int, acc: Float, Float) -> Float): Float { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun FloatBuffer.reduceIndexedOrNull(operation: (index: Int, acc: Float, Float) -> Float): Float? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun FloatBuffer.reduceOrNull(operation: (acc: Float, Float) -> Float): Float? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun FloatBuffer.reduceRight(operation: (Float, acc: Float) -> Float): Float { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun FloatBuffer.reduceRightIndexed(operation: (index: Int, Float, acc: Float) -> Float): Float { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun FloatBuffer.reduceRightIndexedOrNull(operation: (index: Int, Float, acc: Float) -> Float): Float? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun FloatBuffer.reduceRightOrNull(operation: (Float, acc: Float) -> Float): Float? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun FloatBuffer.partition(predicate: (Float) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun FloatBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun FloatBuffer.zip(other: Array, transform: (a: Float, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun FloatBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun FloatBuffer.zip(other: Iterable, transform: (a: Float, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun FloatBuffer.zip(other: FloatArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun FloatBuffer.zip(other: FloatArray, transform: (a: Float, b: Float) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun FloatBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Float) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun FloatBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Float) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun DoubleBuffer.component1(): Double = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun DoubleBuffer.component2(): Double = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun DoubleBuffer.component3(): Double = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun DoubleBuffer.component4(): Double = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun DoubleBuffer.component5(): Double = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun DoubleBuffer.contains(element: Double): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun DoubleBuffer.elementAt(index: Int): Double = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun DoubleBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> Double): Double = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun DoubleBuffer.elementAtOrNull(index: Int): Double? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun DoubleBuffer.find(predicate: (Double) -> Boolean): Double? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun DoubleBuffer.findLast(predicate: (Double) -> Boolean): Double? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun DoubleBuffer.first(): Double { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun DoubleBuffer.first(predicate: (Double) -> Boolean): Double { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun DoubleBuffer.firstOrNull(): Double? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun DoubleBuffer.firstOrNull(predicate: (Double) -> Boolean): Double? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun DoubleBuffer.getOrElse(index: Int, defaultValue: (Int) -> Double): Double = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun DoubleBuffer.getOrNull(index: Int): Double? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun DoubleBuffer.indexOf(element: Double): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun DoubleBuffer.indexOfFirst(predicate: (Double) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun DoubleBuffer.indexOfLast(predicate: (Double) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun DoubleBuffer.last(): Double { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun DoubleBuffer.last(predicate: (Double) -> Boolean): Double { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun DoubleBuffer.lastIndexOf(element: Double): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun DoubleBuffer.lastOrNull(): Double? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun DoubleBuffer.lastOrNull(predicate: (Double) -> Boolean): Double? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun DoubleBuffer.single(): Double = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun DoubleBuffer.single(predicate: (Double) -> Boolean): Double { + var single: Double? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as Double +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun DoubleBuffer.singleOrNull(): Double? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun DoubleBuffer.singleOrNull(predicate: (Double) -> Boolean): Double? { + var single: Double? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun DoubleBuffer.filter(predicate: (Double) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun DoubleBuffer.filterIndexed(predicate: (index: Int, Double) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > DoubleBuffer.filterIndexedTo(destination: C, predicate: (index: Int, Double) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun DoubleBuffer.filterNot(predicate: (Double) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > DoubleBuffer.filterNotTo(destination: C, predicate: (Double) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > DoubleBuffer.filterTo(destination: C, predicate: (Double) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun DoubleBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns an array containing elements of this array at specified [indices]. */ +fun DoubleBuffer.sliceArray(indices: Collection): DoubleArray { + val result = DoubleArray(indices.size) + var targetIndex = 0 + for (sourceIndex in indices) + result[targetIndex++] = this[sourceIndex] + return result +} +/** Sorts elements in the array in-place descending according to their natural sort order. */ +fun DoubleBuffer.sortDescending() { + if (rem > 1) { + val array = toDoubleArray().apply{ sortDescending() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun DoubleBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns an array with all elements of this array sorted according to their natural sort order. */ +fun DoubleBuffer.sortedArray(): DoubleArray = toDoubleArray().apply { sort() } +/** Returns an array with all elements of this array sorted descending according to their natural sort order. */ +fun DoubleBuffer.sortedArrayDescending(): DoubleArray = toDoubleArray().apply { sortDescending() } +/** Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. */ +inline fun > DoubleBuffer.sortedBy(crossinline selector: (Double) -> R?): List = toDoubleArray().sortedWith(compareBy(selector)) +/** Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. */ +inline fun > DoubleBuffer.sortedByDescending(crossinline selector: (Double) -> R?): List = toDoubleArray().sortedWith(compareByDescending(selector)) +/** Returns a list of all elements sorted descending according to their natural sort order. */ +fun DoubleBuffer.sortedDescending(): List = toDoubleArray().apply { sort() }.reversed() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun DoubleBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Sorts the array in-place. */ +fun DoubleBuffer.sort() { + if (rem > 1) { + val array = toDoubleArray().apply{ sort() } + for (i in 0 until rem) + this[pos + i] = array[i] + } +} +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun DoubleBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun DoubleBuffer.fill(element: Double, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val DoubleBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun DoubleBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun DoubleBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val DoubleBuffer.lastIndex: Int + get() = rem - 1 +/** Returns an array of Byte containing all of the elements of this generic array. */ +fun DoubleBuffer.toDoubleArray(): DoubleArray = DoubleArray(rem) { index -> this[index] } +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun DoubleBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun DoubleBuffer.associate(transform: (Double) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun DoubleBuffer.associateBy(keySelector: (Double) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun DoubleBuffer.associateBy(keySelector: (Double) -> K, valueTransform: (Double) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > DoubleBuffer.associateByTo(destination: M, keySelector: (Double) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > DoubleBuffer.associateByTo(destination: M, keySelector: (Double) -> K, valueTransform: (Double) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > DoubleBuffer.associateTo(destination: M, transform: (Double) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun DoubleBuffer.associateWith(valueSelector: (Double) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > DoubleBuffer.associateWithTo(destination: M, valueSelector: (Double) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > DoubleBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun DoubleBuffer.flatMap(transform: (Double) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > DoubleBuffer.flatMapTo(destination: C, transform: (Double) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun DoubleBuffer.groupBy(keySelector: (Double) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun DoubleBuffer.groupBy(keySelector: (Double) -> K, valueTransform: (Double) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> DoubleBuffer.groupByTo(destination: M, keySelector: (Double) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> DoubleBuffer.groupByTo(destination: M, keySelector: (Double) -> K, valueTransform: (Double) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun DoubleBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun DoubleBuffer.distinctBy(selector: (Double) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun DoubleBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun DoubleBuffer.map(transform: (Double) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun DoubleBuffer.mapIndexed(transform: (index: Int, Double) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > DoubleBuffer.mapIndexedTo(destination: C, transform: (index: Int, Double) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > DoubleBuffer.mapTo(destination: C, transform: (Double) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun DoubleBuffer.all(predicate: (Double) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun DoubleBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun DoubleBuffer.any(predicate: (Double) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun DoubleBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun DoubleBuffer.count(predicate: (Double) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun DoubleBuffer.forEach(action: (Double) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun DoubleBuffer.forEachIndexed(action: (index: Int, Double) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun DoubleBuffer.max(): Double { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > DoubleBuffer.maxBy(selector: (Double) -> R): Double { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > DoubleBuffer.maxByOrNull(selector: (Double) -> R): Double? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun DoubleBuffer.maxOrNull(): Double? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun DoubleBuffer.maxWith(comparator: Comparator): Double { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun DoubleBuffer.maxWithOrNull(comparator: Comparator): Double? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun DoubleBuffer.min(): Double { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > DoubleBuffer.minBy(selector: (Double) -> R): Double { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > DoubleBuffer.minByOrNull(selector: (Double) -> R): Double? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun DoubleBuffer.minOf(selector: (Double) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun DoubleBuffer.minOf(selector: (Double) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > DoubleBuffer.minOf(selector: (Double) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun DoubleBuffer.minOfOrNull(selector: (Double) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun DoubleBuffer.minOfOrNull(selector: (Double) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > DoubleBuffer.minOfOrNull(selector: (Double) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun DoubleBuffer.minOfWith(comparator: Comparator, selector: (Double) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun DoubleBuffer.minOfWithOrNull(comparator: Comparator, selector: (Double) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun DoubleBuffer.minOrNull(): Double? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun DoubleBuffer.minWith(comparator: Comparator): Double { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun DoubleBuffer.minWithOrNull(comparator: Comparator): Double? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun DoubleBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun DoubleBuffer.none(predicate: (Double) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun DoubleBuffer.onEach(action: (Double) -> Unit): DoubleBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun DoubleBuffer.onEachIndexed(action: (index: Int, Double) -> Unit): DoubleBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun DoubleBuffer.reduce(operation: (acc: Double, Double) -> Double): Double { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun DoubleBuffer.reduceIndexed(operation: (index: Int, acc: Double, Double) -> Double): Double { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun DoubleBuffer.reduceIndexedOrNull(operation: (index: Int, acc: Double, Double) -> Double): Double? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun DoubleBuffer.reduceOrNull(operation: (acc: Double, Double) -> Double): Double? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun DoubleBuffer.reduceRight(operation: (Double, acc: Double) -> Double): Double { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun DoubleBuffer.reduceRightIndexed(operation: (index: Int, Double, acc: Double) -> Double): Double { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun DoubleBuffer.reduceRightIndexedOrNull(operation: (index: Int, Double, acc: Double) -> Double): Double? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun DoubleBuffer.reduceRightOrNull(operation: (Double, acc: Double) -> Double): Double? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun DoubleBuffer.partition(predicate: (Double) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun DoubleBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun DoubleBuffer.zip(other: Array, transform: (a: Double, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun DoubleBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun DoubleBuffer.zip(other: Iterable, transform: (a: Double, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun DoubleBuffer.zip(other: DoubleArray): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest array. + */ +inline fun DoubleBuffer.zip(other: DoubleArray, transform: (a: Double, b: Double) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun DoubleBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Double) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun DoubleBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Double) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +/** + * Returns 1st *element* from the buffer. + * + * If the size of this array is less than 1, throws an [IndexOutOfBoundsException] + */ +inline operator fun PointerBuffer.component1(): Long = get(0) +/** + * Returns 2nd *element* from the buffer. + * + * If the size of this array is less than 2, throws an [IndexOutOfBoundsException] + */ +inline operator fun PointerBuffer.component2(): Long = get(1) +/** + * Returns 3rd *element* from the buffer. + * + * If the size of this array is less than 3, throws an [IndexOutOfBoundsException] + */ +inline operator fun PointerBuffer.component3(): Long = get(2) +/** + * Returns 4th *element* from the buffer. + * + * If the size of this array is less than 4, throws an [IndexOutOfBoundsException] + */ +inline operator fun PointerBuffer.component4(): Long = get(3) +/** + * Returns 5th *element* from the buffer. + * + * If the size of this array is less than 5, throws an [IndexOutOfBoundsException] + */ +inline operator fun PointerBuffer.component5(): Long = get(4) +/** Returns `true` if [element] is found in the array. */ +operator fun PointerBuffer.contains(element: Long): Boolean = indexOf(element) >= 0 +/** Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. */ +inline fun PointerBuffer.elementAt(index: Int): Long = get(index) +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun PointerBuffer.elementAtOrElse(index: Int, defaultValue: (Int) -> Long): Long = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +inline fun PointerBuffer.elementAtOrNull(index: Int): Long? = this.getOrNull(index) +/** Returns the first element matching the given [predicate], or `null` if no such element was found. */ +inline fun PointerBuffer.find(predicate: (Long) -> Boolean): Long? = firstOrNull(predicate) +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun PointerBuffer.findLast(predicate: (Long) -> Boolean): Long? = lastOrNull(predicate) +/** + * Returns the first element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun PointerBuffer.first(): Long { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[0] +} +/** + * Returns the first element matching the given [predicate]. + * @throws [NoSuchElementException] if no such element is found. + */ +inline fun PointerBuffer.first(predicate: (Long) -> Boolean): Long { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns the first element, or `null` if the array is empty. */ +fun PointerBuffer.firstOrNull(): Long? = if (isEmpty()) null else this[0] +/** Returns the first element matching the given [predicate], or `null` if element was not found. */ +inline fun PointerBuffer.firstOrNull(predicate: (Long) -> Boolean): Long? { + for (element in this) if (predicate(element)) return element + return null +} +/** Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. */ +inline fun PointerBuffer.getOrElse(index: Int, defaultValue: (Int) -> Long): Long = if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +/** Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. */ +fun PointerBuffer.getOrNull(index: Int): Long? = if (index >= 0 && index <= lastIndex) get(index) else null +/** Returns first index of [element], or -1 if the array does not contain element. */ +fun PointerBuffer.indexOf(element: Long): Int { + for (index in indices) + if (element == this[index]) + return index + return -1 +} +/** Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun PointerBuffer.indexOfFirst(predicate: (Long) -> Boolean): Int { + for (index in indices) + if (predicate(this[index])) + return index + return -1 +} +/** Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. */ +inline fun PointerBuffer.indexOfLast(predicate: (Long) -> Boolean): Int { + for (index in indices.reversed()) + if (predicate(this[index])) + return index + return -1 +} +/** + * Returns the last element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun PointerBuffer.last(): Long { + if (isEmpty()) + throw NoSuchElementException("Array is empty.") + return this[lastIndex] +} +/** + * Returns the last element matching the given [predicate]. + * + * @throws NoSuchElementException if no such element is found. + */ +inline fun PointerBuffer.last(predicate: (Long) -> Boolean): Long { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Array contains no element matching the predicate.") +} +/** Returns last index of [element], or -1 if the array does not contain element. */ +fun PointerBuffer.lastIndexOf(element: Long): Int { + for (index in indices.reversed()) + if (element == this[index]) + return index + return -1 +} +/** Returns the last element, or `null` if the array is empty. */ +fun PointerBuffer.lastOrNull(): Long? = if (isEmpty()) null else this[rem - 1] +/** Returns the last element matching the given [predicate], or `null` if no such element was found. */ +inline fun PointerBuffer.lastOrNull(predicate: (Long) -> Boolean): Long? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} +/** Returns the single element, or throws an exception if the array is empty or has more than one element. */ +fun PointerBuffer.single(): Long = when (rem) { + 0 -> throw NoSuchElementException("Array is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Array has more than one element.") +} +/** Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. */ +inline fun PointerBuffer.single(predicate: (Long) -> Boolean): Long { + var single: Long? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) throw IllegalArgumentException("Array contains more than one matching element.") + single = element + found = true + } + if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") + @Suppress("UNCHECKED_CAST") + return single as Long +} +/** Returns single element, or `null` if the array is empty or has more than one element. */ +fun PointerBuffer.singleOrNull(): Long? = if (rem == 1) this[0] else null +/** Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. */ +inline fun PointerBuffer.singleOrNull(predicate: (Long) -> Boolean): Long? { + var single: Long? = null + var found = false + for (element in this) + if (predicate(element)) { + if (found) return null + single = element + found = true + } + if (!found) return null + return single +} +/** Returns a list containing only elements matching the given [predicate]. */ +inline fun PointerBuffer.filter(predicate: (Long) -> Boolean): List = filterTo(ArrayList(), predicate) +/** + * Returns a list containing only elements matching the given [predicate]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun PointerBuffer.filterIndexed(predicate: (index: Int, Long) -> Boolean): List = filterIndexedTo(ArrayList(), predicate) +/** + * Appends all elements matching the given [predicate] to the given [destination]. + * @param [predicate] function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element. + */ +inline fun > PointerBuffer.filterIndexedTo(destination: C, predicate: (index: Int, Long) -> Boolean): C { + forEachIndexed { index, element -> + if (predicate(index, element)) destination.add(element) + } + return destination +} +/** Returns a list containing all elements not matching the given [predicate]. */ +inline fun PointerBuffer.filterNot(predicate: (Long) -> Boolean): List = filterNotTo(ArrayList(), predicate) +/** Appends all elements not matching the given [predicate] to the given [destination]. */ +inline fun > PointerBuffer.filterNotTo(destination: C, predicate: (Long) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} +/** Appends all elements matching the given [predicate] to the given [destination]. */ +inline fun > PointerBuffer.filterTo(destination: C, predicate: (Long) -> Boolean): C { + for (element in this) if (predicate(element)) destination.add(element) + return destination +} +/** Returns a list containing elements at specified [indices]. */ +fun PointerBuffer.slice(indices: Iterable): List { + val size = indices.collectionSizeOrDefault(10) + if (size == 0) return emptyList() + val list = ArrayList(size) + for (index in indices) + list.add(get(index)) + return list +} +/** Returns a list of all elements sorted according to their natural sort order. */ +fun PointerBuffer.sorted(): List = toTypedArray().apply { sort() }.asList() +/** Returns a list of all elements sorted according to the specified [comparator]. */ +fun PointerBuffer.sortedWith(comparator: Comparator): List = toTypedArray().apply { sortWith(comparator) }.asList() +/** Returns a string representation of the contents of the specified array as if it is [List]. */ +fun PointerBuffer.contentToString(): String { + val iMax = lim - 1 + if (iMax == -1) return "[]" + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(get(i)) + if (i == iMax) return b.append(']').toString() + b.append(", ") + i++ + } +} +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +fun PointerBuffer.fill(element: Long, fromIndex: Int = pos, toIndex: Int = rem) { + for (i in fromIndex until toIndex) + this[i] = element +} +/** Returns the range of valid indices for the array. */ +val PointerBuffer.indices: IntRange + get() = IntRange(0, lastIndex) +/** Returns `true` if the array is empty. */ +inline fun PointerBuffer.isEmpty(): Boolean = rem == 0 +/** Returns `true` if the array is not empty. */ +inline fun PointerBuffer.isNotEmpty(): Boolean = !isEmpty() +/** Returns the last valid index for the array. */ +val PointerBuffer.lastIndex: Int + get() = rem - 1 +/** Returns a *typed* object array containing all of the elements of this primitive array. */ +fun PointerBuffer.toTypedArray(): Array = Array(rem) { index -> this[index] } +/** + * Returns a [Map] containing key-value pairs provided by [transform] function applied to elements of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun PointerBuffer.associate(transform: (Long) -> Pair): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateTo(LinkedHashMap(capacity), transform) +} +/** + * Returns a [Map] containing the elements from the given array indexed by the key returned from [keySelector] function applied to each element. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun PointerBuffer.associateBy(keySelector: (Long) -> K): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector) +} +/** + * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun PointerBuffer.associateBy(keySelector: (Long) -> K, valueTransform: (Long) -> V): Map { + val capacity = mapCapacity(rem).coerceAtLeast(16) + return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by + * the [keySelector] function applied to each element of the given array and value is the element itself. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > PointerBuffer.associateByTo(destination: M, keySelector: (Long) -> K): M { + for (element in this) + destination.put(keySelector(element), element) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs, where key is provided by the [keySelector] + * function and and value is provided by the [valueTransform] function applied to elements of the given array. + * + * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. + */ +inline fun > PointerBuffer.associateByTo(destination: M, keySelector: (Long) -> K, valueTransform: (Long) -> V): M { + for (element in this) + destination.put(keySelector(element), valueTransform(element)) + return destination +} +/** + * Populates and returns the [destination] mutable map with key-value pairs provided by [transform] function + * applied to each element of the given array. + * + * If any of two pairs would have the same key the last one gets added to the map. + */ +inline fun > PointerBuffer.associateTo(destination: M, transform: (Long) -> Pair): M { + for (element in this) + destination += transform(element) + return destination +} +/** + * Returns a [Map] where keys are elements from the given array and values are produced by the [valueSelector] function applied to each element. + * + * If any two elements are equal, the last one gets added to the map. + * + * The returned map preserves the entry iteration order of the original array. + */ +inline fun PointerBuffer.associateWith(valueSelector: (Long) -> V): Map { + val result = LinkedHashMap(mapCapacity(rem).coerceAtLeast(16)) + return associateWithTo(result, valueSelector) +} +/** + * Populates and returns the [destination] mutable map with key-value pairs for each element of the given array, + * where key is the element itself and value is provided by the [valueSelector] function applied to that key. + * + * If any two elements are equal, the last one overwrites the former value in the map. + */ +inline fun > PointerBuffer.associateWithTo(destination: M, valueSelector: (Long) -> V): M { + for (element in this) + destination.put(element, valueSelector(element)) + return destination +} +/** Appends all elements to the given [destination] collection. */ +fun > PointerBuffer.toCollection(destination: C): C { + for (item in this) + destination.add(item) + return destination +} +/** Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. */ +inline fun PointerBuffer.flatMap(transform: (Long) -> Iterable): List = flatMapTo(ArrayList(), transform) +/** Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. */ +inline fun > PointerBuffer.flatMapTo(destination: C, transform: (Long) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to + * each element and returns a map where each group key is associated with a list of corresponding elements. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun PointerBuffer.groupBy(keySelector: (Long) -> K): Map> = groupByTo(LinkedHashMap>(), keySelector) +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and returns a map where each group key is associated with a list of corresponding values. + * + * The returned map preserves the entry iteration order of the keys produced from the original array. + */ +inline fun PointerBuffer.groupBy(keySelector: (Long) -> K, valueTransform: (Long) -> V): Map> = groupByTo(LinkedHashMap>(), keySelector, valueTransform) +/** + * Groups elements of the original array by the key returned by the given [keySelector] function applied to each + * element and puts to the [destination] map each group key associated with a list of corresponding elements. + * + * @return The [destination] map. + */ +inline fun >> PointerBuffer.groupByTo(destination: M, keySelector: (Long) -> K): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(element) + } + return destination +} +/** + * Groups values returned by the [valueTransform] function applied to each element of the original array + * by the key returned by the given [keySelector] function applied to the element + * and puts to the [destination] map each group key associated with a list of corresponding values. + * + * @return The [destination] map. + */ +inline fun >> PointerBuffer.groupByTo(destination: M, keySelector: (Long) -> K, valueTransform: (Long) -> V): M { + for (element in this) { + val key = keySelector(element) + val list = destination.getOrPut(key) { ArrayList() } + list.add(valueTransform(element)) + } + return destination +} +/** + * Returns a list containing only distinct elements from the given array. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +fun PointerBuffer.distinct(): List = this.toMutableSet().toList() +/** + * Returns a list containing only elements from the given array having distinct keys returned by the given [selector] function. + * + * The elements in the resulting list are in the same order as they were in the source array. + */ +inline fun PointerBuffer.distinctBy(selector: (Long) -> K): List { + val set = HashSet() + val list = ArrayList() + for (e in this) { + val key = selector(e) + if (set.add(key)) + list.add(e) + } + return list +} +/** + * Returns a new [MutableSet] containing all distinct elements from the given array. + * + * The returned set preserves the element iteration order of the original array. + */ +fun PointerBuffer.toMutableSet(): MutableSet = toCollection(LinkedHashSet(mapCapacity(rem))) +/** Returns a list containing the results of applying the given [transform] function to each element in the original array. */ +inline fun PointerBuffer.map(transform: (Long) -> R): List = mapTo(ArrayList(rem), transform) +/** + * Returns a list containing the results of applying the given [transform] function to each element and its index in the original array. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun PointerBuffer.mapIndexed(transform: (index: Int, Long) -> R): List = mapIndexedTo(ArrayList(rem), transform) +/** + * Applies the given [transform] function to each element and its index in the original array and appends the results to the given [destination]. + * @param [transform] function that takes the index of an element and the element itself and returns the result of the transform applied to the element. + */ +inline fun > PointerBuffer.mapIndexedTo(destination: C, transform: (index: Int, Long) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} +/** Applies the given [transform] function to each element of the original array and appends the results to the given [destination]. */ +inline fun > PointerBuffer.mapTo(destination: C, transform: (Long) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} +/** Returns `true` if all elements match the given [predicate]. */ +inline fun PointerBuffer.all(predicate: (Long) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} +/** Returns `true` if array has at least one element. */ +fun PointerBuffer.any(): Boolean = !isEmpty() +/** Returns `true` if at least one element matches the given [predicate]. */ +inline fun PointerBuffer.any(predicate: (Long) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} +/** Returns the number of elements in this array. */ +inline fun PointerBuffer.count(): Int = rem +/** Returns the number of elements matching the given [predicate]. */ +inline fun PointerBuffer.count(predicate: (Long) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) ++count + return count +} +/** Performs the given [action] on each element. */ +inline fun PointerBuffer.forEach(action: (Long) -> Unit) { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun PointerBuffer.forEachIndexed(action: (index: Int, Long) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} +/** + * Returns the largest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun PointerBuffer.max(): Long { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element yielding the largest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > PointerBuffer.maxBy(selector: (Long) -> R): Long { + if (isEmpty()) throw NoSuchElementException() + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the first element yielding the largest value of the given function or `null` if there are no elements. */ +inline fun > PointerBuffer.maxByOrNull(selector: (Long) -> R): Long? { + if (isEmpty()) return null + var maxElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return maxElem + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} +/** Returns the largest element or `null` if there are no elements. */ +fun PointerBuffer.maxOrNull(): Long? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} +/** + * Returns the first element having the largest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun PointerBuffer.maxWith(comparator: Comparator): Long { + if (isEmpty()) throw NoSuchElementException() + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. */ +fun PointerBuffer.maxWithOrNull(comparator: Comparator): Long? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(max, e) < 0) max = e + } + return max +} +/** + * Returns the smallest element. + * + * @throws NoSuchElementException if the array is empty. + */ +fun PointerBuffer.min(): Long { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} +/** + * Returns the first element yielding the smallest value of the given function. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > PointerBuffer.minBy(selector: (Long) -> R): Long { + if (isEmpty()) throw NoSuchElementException() + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. + * + * @sample samples.collections.Collections.Aggregates.minByOrNull + */ +inline fun > PointerBuffer.minByOrNull(selector: (Long) -> R): Long? { + if (isEmpty()) return null + var minElem = this[0] + val lastIndex = this.lastIndex + if (lastIndex == 0) return minElem + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun PointerBuffer.minOf(selector: (Long) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun PointerBuffer.minOf(selector: (Long) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun > PointerBuffer.minOf(selector: (Long) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun PointerBuffer.minOfOrNull(selector: (Long) -> Double): Double? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** + * Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ +inline fun PointerBuffer.minOfOrNull(selector: (Long) -> Float): Float? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + minValue = minOf(minValue, v) + } + return minValue +} +/** Returns the smallest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ +inline fun > PointerBuffer.minOfOrNull(selector: (Long) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (minValue > v) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ +inline fun PointerBuffer.minOfWith(comparator: Comparator, selector: (Long) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** + * Returns the smallest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ +inline fun PointerBuffer.minOfWithOrNull(comparator: Comparator, selector: (Long) -> R): R? { + if (isEmpty()) return null + var minValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(minValue, v) > 0) + minValue = v + } + return minValue +} +/** Returns the smallest element or `null` if there are no elements. */ +fun PointerBuffer.minOrNull(): Long? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min + } +/** + * Returns the first element having the smallest value according to the provided [comparator]. + * + * @throws NoSuchElementException if the array is empty. + */ +fun PointerBuffer.minWith(comparator: Comparator): Long { + if (isEmpty()) throw NoSuchElementException() + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. */ +fun PointerBuffer.minWithOrNull(comparator: Comparator): Long? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (comparator.compare(min, e) > 0) min = e + } + return min +} +/** Returns `true` if the array has no elements. */ +fun PointerBuffer.none(): Boolean = isEmpty() +/** Returns `true` if no elements match the given [predicate]. */ +inline fun PointerBuffer.none(predicate: (Long) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} +/** Performs the given [action] on each element and returns the array itself afterwards. */ +inline fun PointerBuffer.onEach(action: (Long) -> Unit): PointerBuffer = apply { for (element in this) action(element) } +/** + * Performs the given [action] on each element, providing sequential index with the element, and returns the array itself afterwards. + * @param [action] function that takes the index of an element and the element itself and performs the action on the element. + */ +inline fun PointerBuffer.onEachIndexed(action: (index: Int, Long) -> Unit): PointerBuffer = apply { forEachIndexed(action) } +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun PointerBuffer.reduce(operation: (acc: Long, Long) -> Long): Long { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun PointerBuffer.reduceIndexed(operation: (index: Int, acc: Long, Long) -> Long): Long { + if (isEmpty()) + throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right + * to current accumulator value and each element with its index in the original array. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, current accumulator value and the element itself, + * and calculates the next accumulator value. + */ +inline fun PointerBuffer.reduceIndexedOrNull(operation: (index: Int, acc: Long, Long) -> Long): Long? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(index, accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value. + */ +inline fun PointerBuffer.reduceOrNull(operation: (acc: Long, Long) -> Long): Long? { + if (isEmpty()) + return null + var accumulator = this[0] + for (index in 1..lastIndex) + accumulator = operation(accumulator, this[index]) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun PointerBuffer.reduceRight(operation: (Long, acc: Long) -> Long): Long { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Throws an exception if this array is empty. If the array can be empty in an expected way, + * please use [reduceRightIndexedOrNull] instead. It returns `null` when its receiver is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun PointerBuffer.reduceRightIndexed(operation: (index: Int, Long, acc: Long) -> Long): Long { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left + * to each element with its index in the original array and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes the index of an element, the element itself and current accumulator value, + * and calculates the next accumulator value. + */ +inline fun PointerBuffer.reduceRightIndexedOrNull(operation: (index: Int, Long, acc: Long) -> Long): Long? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(index, get(index), accumulator) + --index + } + return accumulator +} +/** + * Accumulates value starting with the last element and applying [operation] from right to left to each element and current accumulator value. + * + * Returns `null` if the array is empty. + * + * @param [operation] function that takes an element and current accumulator value, and calculates the next accumulator value. + */ +inline fun PointerBuffer.reduceRightOrNull(operation: (Long, acc: Long) -> Long): Long? { + var index = lastIndex + if (index < 0) return null + var accumulator = get(index--) + while (index >= 0) + accumulator = operation(get(index--), accumulator) + return accumulator +} +/** + * Splits the original array into pair of lists, where *first* list contains elements for which [predicate] + * yielded `true`, while *second* list contains elements for which [predicate] yielded `false`. + */ +inline fun PointerBuffer.partition(predicate: (Long) -> Boolean): Pair, List> { + val first = ArrayList() + val second = ArrayList() + for (element in this) + if (predicate(element)) + first.add(element) + else + second.add(element) + return Pair(first, second) +} +/** + * Returns a list of pairs built from the elements of `this` array and the [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun PointerBuffer.zip(other: Array): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] array with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun PointerBuffer.zip(other: Array, transform: (a: Long, b: R) -> V): List { + val size = minOf(rem, other.size) + val list = ArrayList(size) + for (i in 0 until size) + list.add(transform(this[i], other[i])) + return list +} +/** + * Returns a list of pairs built from the elements of `this` collection and [other] array with the same index. + * The returned list has length of the shortest collection. + */ +infix fun PointerBuffer.zip(other: Iterable): List> = zip(other) { t1, t2 -> t1 to t2 } +/** + * Returns a list of values built from the elements of `this` array and the [other] collection with the same index + * using the provided [transform] function applied to each pair of elements. + * The returned list has length of the shortest collection. + */ +inline fun PointerBuffer.zip(other: Iterable, transform: (a: Long, b: R) -> V): List { + val arraySize = rem + val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) + var i = 0 + for (element in other) { + if (i >= arraySize) break + list.add(transform(this[i++], element)) + } + return list +} +/** + * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun PointerBuffer.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Long) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) + if (transform != null) + buffer.append(transform(element)) + else + buffer.append(element.toString()) + else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} +/** + * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. + * + * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] + * elements will be appended, followed by the [truncated] string (which defaults to "..."). + */ +fun PointerBuffer.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Long) -> CharSequence)? = null): String = + joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() diff --git a/src/mainGen/kotlin/kool/builders.kt b/src/mainGen/kotlin/kool/builders.kt new file mode 100644 index 0000000..8b51802 --- /dev/null +++ b/src/mainGen/kotlin/kool/builders.kt @@ -0,0 +1,536 @@ +@file:OptIn(kotlin.experimental.ExperimentalTypeInference::class) +package kool +import kool.ubuffers.asUByteBuffer +import kool.ubuffers.UByteBuffer +import java.nio.LongBuffer +import kool.ubuffers.UShortBuffer +import java.nio.Buffer +import org.lwjgl.system.MemoryStack +import kool.ubuffers.asULongBuffer +import kool.ubuffers.ULongBuffer +import java.nio.IntBuffer +import org.lwjgl.system.Pointer +import java.nio.ByteBuffer +import org.lwjgl.PointerBuffer +import java.nio.ShortBuffer +import org.lwjgl.system.MemoryUtil +import kool.ubuffers.asUIntBuffer +import kool.ubuffers.asUShortBuffer +import java.nio.DoubleBuffer +import java.nio.FloatBuffer +import java.nio.CharBuffer +import kool.ubuffers.UIntBuffer +import kool.adr + +/** Creates a new empty buffer. */ +fun emptyCharBuffer(): CharBuffer = MemoryUtil.memCalloc(0).asCharBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun CharBuffer(size: Int): CharBuffer = MemoryUtil.memCalloc(size * Char.BYTES).asCharBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.CharBuffer(size: Int): CharBuffer = malloc(size * Char.BYTES).asCharBuffer() +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun CharBuffer(size: Int, init: (Int) -> Char): CharBuffer { + val buffer = MemoryUtil.memAlloc(size * Char.BYTES).asCharBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.CharBuffer(size: Int, init: (Int) -> Char): CharBuffer { + val buffer = malloc(size * Char.BYTES).asCharBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyBuffer(): ByteBuffer = MemoryUtil.memAlloc(0) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun Buffer(size: Int): ByteBuffer = MemoryUtil.memCalloc(size) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.Buffer(size: Int): ByteBuffer = calloc(size) +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun Buffer(size: Int, init: (Int) -> Byte): ByteBuffer { + val buffer = MemoryUtil.memAlloc(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.Buffer(size: Int, init: (Int) -> Byte): ByteBuffer { + val buffer = malloc(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyByteBuffer(): ByteBuffer = MemoryUtil.memCalloc(0) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun ByteBuffer(size: Int): ByteBuffer = MemoryUtil.memCalloc(size) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.ByteBuffer(size: Int): ByteBuffer = malloc(size) +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun ByteBuffer(size: Int, init: (Int) -> Byte): ByteBuffer { + val buffer = MemoryUtil.memAlloc(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.ByteBuffer(size: Int, init: (Int) -> Byte): ByteBuffer { + val buffer = malloc(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyShortBuffer(): ShortBuffer = MemoryUtil.memCallocShort(0) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun ShortBuffer(size: Int): ShortBuffer = MemoryUtil.memCallocShort(size) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.ShortBuffer(size: Int): ShortBuffer = mallocShort(size) +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer { + val buffer = MemoryUtil.memAllocShort(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer { + val buffer = mallocShort(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyIntBuffer(): IntBuffer = MemoryUtil.memCallocInt(0) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun IntBuffer(size: Int): IntBuffer = MemoryUtil.memCallocInt(size) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.IntBuffer(size: Int): IntBuffer = mallocInt(size) +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer { + val buffer = MemoryUtil.memAllocInt(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.IntBuffer(size: Int, init: (Int) -> Int): IntBuffer { + val buffer = mallocInt(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyLongBuffer(): LongBuffer = MemoryUtil.memCallocLong(0) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun LongBuffer(size: Int): LongBuffer = MemoryUtil.memCallocLong(size) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.LongBuffer(size: Int): LongBuffer = mallocLong(size) +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer { + val buffer = MemoryUtil.memAllocLong(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.LongBuffer(size: Int, init: (Int) -> Long): LongBuffer { + val buffer = mallocLong(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyUBuffer(): UByteBuffer = MemoryUtil.memAlloc(0).asUByteBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun UBuffer(size: Int): UByteBuffer = MemoryUtil.memCalloc(size).asUByteBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.UBuffer(size: Int): UByteBuffer = calloc(size).asUByteBuffer() +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun UBuffer(size: Int, init: (Int) -> UByte): UByteBuffer { + val buffer = MemoryUtil.memAlloc(size).asUByteBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.UBuffer(size: Int, init: (Int) -> UByte): UByteBuffer { + val buffer = malloc(size).asUByteBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyUByteBuffer(): UByteBuffer = MemoryUtil.memCalloc(0).asUByteBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun UByteBuffer(size: Int): UByteBuffer = MemoryUtil.memCalloc(size).asUByteBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.UByteBuffer(size: Int): UByteBuffer = malloc(size).asUByteBuffer() +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun UByteBuffer(size: Int, init: (Int) -> UByte): UByteBuffer { + val buffer = MemoryUtil.memAlloc(size).asUByteBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.UByteBuffer(size: Int, init: (Int) -> UByte): UByteBuffer { + val buffer = malloc(size).asUByteBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyUShortBuffer(): UShortBuffer = MemoryUtil.memCallocShort(0).asUShortBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun UShortBuffer(size: Int): UShortBuffer = MemoryUtil.memCallocShort(size).asUShortBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.UShortBuffer(size: Int): UShortBuffer = mallocShort(size).asUShortBuffer() +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun UShortBuffer(size: Int, init: (Int) -> UShort): UShortBuffer { + val buffer = MemoryUtil.memAllocShort(size).asUShortBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.UShortBuffer(size: Int, init: (Int) -> UShort): UShortBuffer { + val buffer = mallocShort(size).asUShortBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyUIntBuffer(): UIntBuffer = MemoryUtil.memCallocInt(0).asUIntBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun UIntBuffer(size: Int): UIntBuffer = MemoryUtil.memCallocInt(size).asUIntBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.UIntBuffer(size: Int): UIntBuffer = mallocInt(size).asUIntBuffer() +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun UIntBuffer(size: Int, init: (Int) -> UInt): UIntBuffer { + val buffer = MemoryUtil.memAllocInt(size).asUIntBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.UIntBuffer(size: Int, init: (Int) -> UInt): UIntBuffer { + val buffer = mallocInt(size).asUIntBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyULongBuffer(): ULongBuffer = MemoryUtil.memCallocLong(0).asULongBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun ULongBuffer(size: Int): ULongBuffer = MemoryUtil.memCallocLong(size).asULongBuffer() +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.ULongBuffer(size: Int): ULongBuffer = mallocLong(size).asULongBuffer() +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun ULongBuffer(size: Int, init: (Int) -> ULong): ULongBuffer { + val buffer = MemoryUtil.memAllocLong(size).asULongBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.ULongBuffer(size: Int, init: (Int) -> ULong): ULongBuffer { + val buffer = mallocLong(size).asULongBuffer() + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyFloatBuffer(): FloatBuffer = MemoryUtil.memCallocFloat(0) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun FloatBuffer(size: Int): FloatBuffer = MemoryUtil.memCallocFloat(size) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.FloatBuffer(size: Int): FloatBuffer = mallocFloat(size) +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun FloatBuffer(size: Int, init: (Int) -> Float): FloatBuffer { + val buffer = MemoryUtil.memAllocFloat(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.FloatBuffer(size: Int, init: (Int) -> Float): FloatBuffer { + val buffer = mallocFloat(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyDoubleBuffer(): DoubleBuffer = MemoryUtil.memCallocDouble(0) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun DoubleBuffer(size: Int): DoubleBuffer = MemoryUtil.memCallocDouble(size) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.DoubleBuffer(size: Int): DoubleBuffer = mallocDouble(size) +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun DoubleBuffer(size: Int, init: (Int) -> Double): DoubleBuffer { + val buffer = MemoryUtil.memAllocDouble(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +inline fun MemoryStack.DoubleBuffer(size: Int, init: (Int) -> Double): DoubleBuffer { + val buffer = mallocDouble(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** Creates a new empty buffer. */ +fun emptyPointerBuffer(): PointerBuffer = MemoryUtil.memCallocPointer(0) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun PointerBuffer(size: Int): PointerBuffer = MemoryUtil.memCallocPointer(size) +/** Creates a new buffer of the specified [size], with all elements initialized to zero. */ +fun MemoryStack.PointerBuffer(size: Int): PointerBuffer = mallocPointer(size) +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +@OverloadResolutionByLambdaReturnType +@kotlin.jvm.JvmName("PointerBufferLong") +inline fun PointerBuffer(size: Int, init: (Int) -> Long): PointerBuffer { + val buffer = MemoryUtil.memAllocPointer(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +@OverloadResolutionByLambdaReturnType +@kotlin.jvm.JvmName("PointerBufferLong") +inline fun MemoryStack.PointerBuffer(size: Int, init: (Int) -> Long): PointerBuffer { + val buffer = mallocPointer(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +@OverloadResolutionByLambdaReturnType +@kotlin.jvm.JvmName("PointerBufferPointer") +inline fun PointerBuffer(size: Int, init: (Int) -> Pointer): PointerBuffer { + val buffer = MemoryUtil.memAllocPointer(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +@OverloadResolutionByLambdaReturnType +@kotlin.jvm.JvmName("PointerBufferPointer") +inline fun MemoryStack.PointerBuffer(size: Int, init: (Int) -> Pointer): PointerBuffer { + val buffer = mallocPointer(size) + for (i in 0 until size) + buffer[i] = init(i) + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +@OverloadResolutionByLambdaReturnType +@kotlin.jvm.JvmName("PointerBufferBuffer") +inline fun PointerBuffer(size: Int, init: (Int) -> Buffer): PointerBuffer { + val buffer = MemoryUtil.memAllocPointer(size) + for (i in 0 until size) + buffer[i] = init(i).adr + return buffer +} +/** + * Creates a new array of the specified [size], where each element is calculated by calling + * the specified [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ +@OverloadResolutionByLambdaReturnType +@kotlin.jvm.JvmName("PointerBufferBuffer") +inline fun MemoryStack.PointerBuffer(size: Int, init: (Int) -> Buffer): PointerBuffer { + val buffer = mallocPointer(size) + for (i in 0 until size) + buffer[i] = init(i).adr + return buffer +} diff --git a/src/mainGen/kotlin/kool/conversions.kt b/src/mainGen/kotlin/kool/conversions.kt new file mode 100644 index 0000000..111304e --- /dev/null +++ b/src/mainGen/kotlin/kool/conversions.kt @@ -0,0 +1,508 @@ +@file:OptIn(kotlin.ExperimentalUnsignedTypes::class) +package kool +import kool.ubuffers.UByteBuffer +import java.nio.LongBuffer +import kool.ubuffers.UShortBuffer +import kool.ubuffers.asULongBuffer +import kool.sliceAs +import org.lwjgl.PointerBuffer +import kool.free +import org.lwjgl.system.MemoryUtil +import kool.ubuffers.asUIntBuffer +import java.nio.DoubleBuffer +import java.nio.CharBuffer +import kool.adr +import kool.ubuffers.asUByteBuffer +import org.lwjgl.system.MemoryStack +import java.nio.Buffer +import kool.ubuffers.ULongBuffer +import java.nio.IntBuffer +import org.lwjgl.system.Pointer +import kool.rem +import java.nio.ByteBuffer +import java.nio.ShortBuffer +import kool.ubuffers.asUShortBuffer +import kool.cap +import java.nio.FloatBuffer +import kool.pos +import kool.ubuffers.UIntBuffer +import kool.Adr + +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun CharArray.toBuffer(): ByteBuffer { + val res = MemoryUtil.memAlloc(size * Char.BYTES) + for (i in indices) + res.putChar(i * Char.BYTES, get(i)) + return res +} +fun CharArray.toBuffer(stack: MemoryStack): ByteBuffer { + val res = stack.malloc(size * Char.BYTES) + for (i in indices) + res.putChar(i * Char.BYTES, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun CharArray.toByteBuffer(): ByteBuffer = toBuffer() +fun CharArray.toByteBuffer(stack: MemoryStack): ByteBuffer = toBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun CharArray.toCharBuffer(): CharBuffer = CharBuffer(size) { get(it) } +fun CharArray.toCharBuffer(stack: MemoryStack): CharBuffer = stack.CharBuffer(size) { get(it) } +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun ByteArray.toBuffer(): ByteBuffer { + val res = MemoryUtil.memAlloc(size) + for (i in indices) + res.put(i, get(i)) + return res +} +fun ByteArray.toBuffer(stack: MemoryStack): ByteBuffer { + val res = stack.malloc(size) + for (i in indices) + res.put(i, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun ByteArray.toByteBuffer(): ByteBuffer = toBuffer() +fun ByteArray.toByteBuffer(stack: MemoryStack): ByteBuffer = toBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun ShortArray.toBuffer(): ByteBuffer { + val res = MemoryUtil.memAlloc(size * Short.BYTES) + for (i in indices) + res.putShort(i * Short.BYTES, get(i)) + return res +} +fun ShortArray.toBuffer(stack: MemoryStack): ByteBuffer { + val res = stack.malloc(size * Short.BYTES) + for (i in indices) + res.putShort(i * Short.BYTES, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun ShortArray.toByteBuffer(): ByteBuffer = toBuffer() +fun ShortArray.toByteBuffer(stack: MemoryStack): ByteBuffer = toBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun ShortArray.toShortBuffer(): ShortBuffer = ShortBuffer(size) { get(it) } +fun ShortArray.toShortBuffer(stack: MemoryStack): ShortBuffer = stack.ShortBuffer(size) { get(it) } +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun IntArray.toBuffer(): ByteBuffer { + val res = MemoryUtil.memAlloc(size * Int.BYTES) + for (i in indices) + res.putInt(i * Int.BYTES, get(i)) + return res +} +fun IntArray.toBuffer(stack: MemoryStack): ByteBuffer { + val res = stack.malloc(size * Int.BYTES) + for (i in indices) + res.putInt(i * Int.BYTES, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun IntArray.toByteBuffer(): ByteBuffer = toBuffer() +fun IntArray.toByteBuffer(stack: MemoryStack): ByteBuffer = toBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun IntArray.toIntBuffer(): IntBuffer = IntBuffer(size) { get(it) } +fun IntArray.toIntBuffer(stack: MemoryStack): IntBuffer = stack.IntBuffer(size) { get(it) } +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun LongArray.toBuffer(): ByteBuffer { + val res = MemoryUtil.memAlloc(size * Long.BYTES) + for (i in indices) + res.putLong(i * Long.BYTES, get(i)) + return res +} +fun LongArray.toBuffer(stack: MemoryStack): ByteBuffer { + val res = stack.malloc(size * Long.BYTES) + for (i in indices) + res.putLong(i * Long.BYTES, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun LongArray.toByteBuffer(): ByteBuffer = toBuffer() +fun LongArray.toByteBuffer(stack: MemoryStack): ByteBuffer = toBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun LongArray.toLongBuffer(): LongBuffer = LongBuffer(size) { get(it) } +fun LongArray.toLongBuffer(stack: MemoryStack): LongBuffer = stack.LongBuffer(size) { get(it) } +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun UByteArray.toBuffer(): UByteBuffer { + val res = MemoryUtil.memAlloc(size).asUByteBuffer() + for (i in indices) + res.put(i, get(i)) + return res +} +fun UByteArray.toBuffer(stack: MemoryStack): UByteBuffer { + val res = stack.malloc(size).asUByteBuffer() + for (i in indices) + res.put(i, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun UByteArray.toByteBuffer(): UByteBuffer = toBuffer() +fun UByteArray.toByteBuffer(stack: MemoryStack): UByteBuffer = toBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun UShortArray.toUBuffer(): UByteBuffer { + val res = MemoryUtil.memAlloc(size * UShort.BYTES).asUByteBuffer() + for (i in indices) + res.putUShort(i * UShort.BYTES, get(i)) + return res +} +fun UShortArray.toUBuffer(stack: MemoryStack): UByteBuffer { + val res = stack.malloc(size * UShort.BYTES).asUByteBuffer() + for (i in indices) + res.putUShort(i * UShort.BYTES, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun UShortArray.toUByteBuffer(): UByteBuffer = toUBuffer() +fun UShortArray.toUByteBuffer(stack: MemoryStack): UByteBuffer = toUBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun UShortArray.toUShortBuffer(): UShortBuffer = UShortBuffer(size) { get(it) } +fun UShortArray.toUShortBuffer(stack: MemoryStack): UShortBuffer = stack.UShortBuffer(size) { get(it) } +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun UIntArray.toUBuffer(): UByteBuffer { + val res = MemoryUtil.memAlloc(size * UInt.BYTES).asUByteBuffer() + for (i in indices) + res.putUInt(i * UInt.BYTES, get(i)) + return res +} +fun UIntArray.toUBuffer(stack: MemoryStack): UByteBuffer { + val res = stack.malloc(size * UInt.BYTES).asUByteBuffer() + for (i in indices) + res.putUInt(i * UInt.BYTES, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun UIntArray.toUByteBuffer(): UByteBuffer = toUBuffer() +fun UIntArray.toUByteBuffer(stack: MemoryStack): UByteBuffer = toUBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun UIntArray.toUIntBuffer(): UIntBuffer = UIntBuffer(size) { get(it) } +fun UIntArray.toUIntBuffer(stack: MemoryStack): UIntBuffer = stack.UIntBuffer(size) { get(it) } +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun ULongArray.toUBuffer(): UByteBuffer { + val res = MemoryUtil.memAlloc(size * ULong.BYTES).asUByteBuffer() + for (i in indices) + res.putULong(i * ULong.BYTES, get(i)) + return res +} +fun ULongArray.toUBuffer(stack: MemoryStack): UByteBuffer { + val res = stack.malloc(size * ULong.BYTES).asUByteBuffer() + for (i in indices) + res.putULong(i * ULong.BYTES, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun ULongArray.toUByteBuffer(): UByteBuffer = toUBuffer() +fun ULongArray.toUByteBuffer(stack: MemoryStack): UByteBuffer = toUBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun ULongArray.toULongBuffer(): ULongBuffer = ULongBuffer(size) { get(it) } +fun ULongArray.toULongBuffer(stack: MemoryStack): ULongBuffer = stack.ULongBuffer(size) { get(it) } +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun FloatArray.toBuffer(): ByteBuffer { + val res = MemoryUtil.memAlloc(size * Float.BYTES) + for (i in indices) + res.putFloat(i * Float.BYTES, get(i)) + return res +} +fun FloatArray.toBuffer(stack: MemoryStack): ByteBuffer { + val res = stack.malloc(size * Float.BYTES) + for (i in indices) + res.putFloat(i * Float.BYTES, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun FloatArray.toByteBuffer(): ByteBuffer = toBuffer() +fun FloatArray.toByteBuffer(stack: MemoryStack): ByteBuffer = toBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun FloatArray.toFloatBuffer(): FloatBuffer = FloatBuffer(size) { get(it) } +fun FloatArray.toFloatBuffer(stack: MemoryStack): FloatBuffer = stack.FloatBuffer(size) { get(it) } +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun DoubleArray.toBuffer(): ByteBuffer { + val res = MemoryUtil.memAlloc(size * Double.BYTES) + for (i in indices) + res.putDouble(i * Double.BYTES, get(i)) + return res +} +fun DoubleArray.toBuffer(stack: MemoryStack): ByteBuffer { + val res = stack.malloc(size * Double.BYTES) + for (i in indices) + res.putDouble(i * Double.BYTES, get(i)) + return res +} +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun DoubleArray.toByteBuffer(): ByteBuffer = toBuffer() +fun DoubleArray.toByteBuffer(stack: MemoryStack): ByteBuffer = toBuffer(stack) +/** + * Allocates a block of memory for the array and copy the data from the array to the new allocated memory. + * @param: size the number of elements to allocate. + * @return on success, the buffer representing the memory block allocated by the function + * @throws `OutOfMemoryError` if the function failed to allocate the requested block of memory + */ +fun DoubleArray.toDoubleBuffer(): DoubleBuffer = DoubleBuffer(size) { get(it) } +fun DoubleArray.toDoubleBuffer(stack: MemoryStack): DoubleBuffer = stack.DoubleBuffer(size) { get(it) } +fun ByteArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun ByteArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun ShortArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun ShortArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun IntArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun IntArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun LongArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun LongArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun UByteArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun UByteArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun UShortArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun UShortArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun UIntArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun UIntArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun ULongArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun ULongArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun FloatArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun FloatArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun DoubleArray.toPtr(): Ptr { + val res = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} +fun DoubleArray.toPtr(stack: MemoryStack): Ptr { + val res = stack.nmalloc(size).toPtr() + for (i in indices) + res[i] = get(i) + return res.toPtr() +} diff --git a/src/mainGen/kotlin/kool/extensions.kt b/src/mainGen/kotlin/kool/extensions.kt new file mode 100644 index 0000000..7ce6227 --- /dev/null +++ b/src/mainGen/kotlin/kool/extensions.kt @@ -0,0 +1,579 @@ +@file:Suppress("NOTHING_TO_INLINE") +package kool +import java.nio.ByteBuffer +import org.lwjgl.PointerBuffer +import java.nio.LongBuffer +import java.nio.ShortBuffer +import org.lwjgl.system.MemoryUtil +import java.nio.DoubleBuffer +import java.nio.Buffer +import java.nio.FloatBuffer +import java.nio.IntBuffer +import java.nio.CharBuffer + +/** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ +fun CharBuffer.sliceAs(offset: Int, size: Int = lim - offset): CharBuffer { + val backupPos = pos + val backupLim = lim + pos = offset + lim = offset + size + val res = slice() + pos = backupPos + lim = backupLim + return res +} +/** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ +inline fun CharBuffer.free() = MemoryUtil.memFree(this) +/** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ +inline val CharBuffer.adr: Adr + get() = MemoryUtil.memAddress(this).toULong() +/** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ +inline var CharBuffer.pos: Int + get() = position() + set(value) { position(value) } +/** Returns this buffer's capacity. */ +inline val CharBuffer.cap: Int + get() = capacity() +/** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ +inline val CharBuffer.rem: Int + get() = remaining() +/** Returns the total size in Bytes between the current position and the limit. */ +inline val CharBuffer.remByte: Int + get() = rem * Char.BYTES +/** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ +inline var CharBuffer.lim: Int + get() = limit() + set(value) { limit(value) } +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param char The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun CharBuffer.set(index: Int, char: Char): CharBuffer = put(index, char) +/** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ +fun ByteBuffer.sliceAs(offset: Int, size: Int = lim - offset): ByteBuffer { + val backupPos = pos + val backupLim = lim + pos = offset + lim = offset + size + val res = slice() + pos = backupPos + lim = backupLim + return res +} +/** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ +inline fun ByteBuffer.free() = MemoryUtil.memFree(this) +/** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ +inline val ByteBuffer.adr: Adr + get() = MemoryUtil.memAddress(this).toULong() +/** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ +inline var ByteBuffer.pos: Int + get() = position() + set(value) { position(value) } +/** Returns this buffer's capacity. */ +inline val ByteBuffer.cap: Int + get() = capacity() +/** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ +inline val ByteBuffer.rem: Int + get() = remaining() +/** Returns the total size in Bytes between the current position and the limit. */ +inline val ByteBuffer.remByte: Int + get() = rem * Byte.BYTES +/** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ +inline var ByteBuffer.lim: Int + get() = limit() + set(value) { limit(value) } +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param byte The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun ByteBuffer.set(index: Int, byte: Byte): ByteBuffer = put(index, byte) +/** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ +fun ShortBuffer.sliceAs(offset: Int, size: Int = lim - offset): ShortBuffer { + val backupPos = pos + val backupLim = lim + pos = offset + lim = offset + size + val res = slice() + pos = backupPos + lim = backupLim + return res +} +/** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ +inline fun ShortBuffer.free() = MemoryUtil.memFree(this) +/** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ +inline val ShortBuffer.adr: Adr + get() = MemoryUtil.memAddress(this).toULong() +/** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ +inline var ShortBuffer.pos: Int + get() = position() + set(value) { position(value) } +/** Returns this buffer's capacity. */ +inline val ShortBuffer.cap: Int + get() = capacity() +/** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ +inline val ShortBuffer.rem: Int + get() = remaining() +/** Returns the total size in Bytes between the current position and the limit. */ +inline val ShortBuffer.remByte: Int + get() = rem * Short.BYTES +/** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ +inline var ShortBuffer.lim: Int + get() = limit() + set(value) { limit(value) } +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param short The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun ShortBuffer.set(index: Int, short: Short): ShortBuffer = put(index, short) +/** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ +fun IntBuffer.sliceAs(offset: Int, size: Int = lim - offset): IntBuffer { + val backupPos = pos + val backupLim = lim + pos = offset + lim = offset + size + val res = slice() + pos = backupPos + lim = backupLim + return res +} +/** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ +inline fun IntBuffer.free() = MemoryUtil.memFree(this) +/** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ +inline val IntBuffer.adr: Adr + get() = MemoryUtil.memAddress(this).toULong() +/** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ +inline var IntBuffer.pos: Int + get() = position() + set(value) { position(value) } +/** Returns this buffer's capacity. */ +inline val IntBuffer.cap: Int + get() = capacity() +/** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ +inline val IntBuffer.rem: Int + get() = remaining() +/** Returns the total size in Bytes between the current position and the limit. */ +inline val IntBuffer.remByte: Int + get() = rem * Int.BYTES +/** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ +inline var IntBuffer.lim: Int + get() = limit() + set(value) { limit(value) } +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param int The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun IntBuffer.set(index: Int, int: Int): IntBuffer = put(index, int) +/** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ +fun LongBuffer.sliceAs(offset: Int, size: Int = lim - offset): LongBuffer { + val backupPos = pos + val backupLim = lim + pos = offset + lim = offset + size + val res = slice() + pos = backupPos + lim = backupLim + return res +} +/** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ +inline fun LongBuffer.free() = MemoryUtil.memFree(this) +/** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ +inline val LongBuffer.adr: Adr + get() = MemoryUtil.memAddress(this).toULong() +/** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ +inline var LongBuffer.pos: Int + get() = position() + set(value) { position(value) } +/** Returns this buffer's capacity. */ +inline val LongBuffer.cap: Int + get() = capacity() +/** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ +inline val LongBuffer.rem: Int + get() = remaining() +/** Returns the total size in Bytes between the current position and the limit. */ +inline val LongBuffer.remByte: Int + get() = rem * Long.BYTES +/** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ +inline var LongBuffer.lim: Int + get() = limit() + set(value) { limit(value) } +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param long The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun LongBuffer.set(index: Int, long: Long): LongBuffer = put(index, long) +/** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ +fun FloatBuffer.sliceAs(offset: Int, size: Int = lim - offset): FloatBuffer { + val backupPos = pos + val backupLim = lim + pos = offset + lim = offset + size + val res = slice() + pos = backupPos + lim = backupLim + return res +} +/** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ +inline fun FloatBuffer.free() = MemoryUtil.memFree(this) +/** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ +inline val FloatBuffer.adr: Adr + get() = MemoryUtil.memAddress(this).toULong() +/** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ +inline var FloatBuffer.pos: Int + get() = position() + set(value) { position(value) } +/** Returns this buffer's capacity. */ +inline val FloatBuffer.cap: Int + get() = capacity() +/** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ +inline val FloatBuffer.rem: Int + get() = remaining() +/** Returns the total size in Bytes between the current position and the limit. */ +inline val FloatBuffer.remByte: Int + get() = rem * Float.BYTES +/** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ +inline var FloatBuffer.lim: Int + get() = limit() + set(value) { limit(value) } +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param float The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun FloatBuffer.set(index: Int, float: Float): FloatBuffer = put(index, float) +/** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ +fun DoubleBuffer.sliceAs(offset: Int, size: Int = lim - offset): DoubleBuffer { + val backupPos = pos + val backupLim = lim + pos = offset + lim = offset + size + val res = slice() + pos = backupPos + lim = backupLim + return res +} +/** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ +inline fun DoubleBuffer.free() = MemoryUtil.memFree(this) +/** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ +inline val DoubleBuffer.adr: Adr + get() = MemoryUtil.memAddress(this).toULong() +/** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ +inline var DoubleBuffer.pos: Int + get() = position() + set(value) { position(value) } +/** Returns this buffer's capacity. */ +inline val DoubleBuffer.cap: Int + get() = capacity() +/** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ +inline val DoubleBuffer.rem: Int + get() = remaining() +/** Returns the total size in Bytes between the current position and the limit. */ +inline val DoubleBuffer.remByte: Int + get() = rem * Double.BYTES +/** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ +inline var DoubleBuffer.lim: Int + get() = limit() + set(value) { limit(value) } +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param double The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun DoubleBuffer.set(index: Int, double: Double): DoubleBuffer = put(index, double) +/** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ +fun PointerBuffer.sliceAs(offset: Int, size: Int = lim - offset): PointerBuffer { + val backupPos = pos + val backupLim = lim + pos = offset + lim = offset + size + val res = slice() + pos = backupPos + lim = backupLim + return res +} +/** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ +/** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ +inline val PointerBuffer.adr: Adr + get() = MemoryUtil.memAddress(this).toULong() +/** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ +inline var PointerBuffer.pos: Int + get() = position() + set(value) { position(value) } +/** Returns this buffer's capacity. */ +inline val PointerBuffer.cap: Int + get() = capacity() +/** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ +inline val PointerBuffer.rem: Int + get() = remaining() +/** Returns the total size in Bytes between the current position and the limit. */ +inline val PointerBuffer.remByte: Int + get() = rem * org.lwjgl.system.Pointer.POINTER_SIZE +/** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ +inline var PointerBuffer.lim: Int + get() = limit() + set(value) { limit(value) } +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param pointer The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param pointer The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun PointerBuffer.set(index: Int, pointer: org.lwjgl.system.Pointer): PointerBuffer = put(index, pointer) +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param pointer The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun PointerBuffer.set(index: Int, pointer: Pointer): PointerBuffer = put(index, pointer.toLong()) +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param pointer The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun PointerBuffer.set(index: Int, buffer: Buffer): PointerBuffer = put(index, buffer.adr.toLong()) +/** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param pointer The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ +operator fun PointerBuffer.set(index: Int, pointer: Long): PointerBuffer = put(index, pointer) diff --git a/src/mainGen/kotlin/kool/iterators.kt b/src/mainGen/kotlin/kool/iterators.kt new file mode 100644 index 0000000..4050553 --- /dev/null +++ b/src/mainGen/kotlin/kool/iterators.kt @@ -0,0 +1,99 @@ +package kool +import kool.ubuffers.UByteBuffer +import java.nio.LongBuffer +import kool.ubuffers.UShortBuffer +import kool.ubuffers.ULongBuffer +import java.nio.IntBuffer +import java.nio.ByteBuffer +import org.lwjgl.PointerBuffer +import java.nio.ShortBuffer +import java.nio.DoubleBuffer +import java.nio.FloatBuffer +import java.nio.CharBuffer +import kool.pos +import kool.ubuffers.UIntBuffer + +operator fun CharBuffer.iterator(): CharBufferIterator = CharBufferIterator(this) + +class CharBufferIterator(private val buffer: CharBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): Char = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun ByteBuffer.iterator(): ByteBufferIterator = ByteBufferIterator(this) + +class ByteBufferIterator(private val buffer: ByteBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): Byte = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun ShortBuffer.iterator(): ShortBufferIterator = ShortBufferIterator(this) + +class ShortBufferIterator(private val buffer: ShortBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): Short = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun IntBuffer.iterator(): IntBufferIterator = IntBufferIterator(this) + +class IntBufferIterator(private val buffer: IntBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): Int = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun LongBuffer.iterator(): LongBufferIterator = LongBufferIterator(this) + +class LongBufferIterator(private val buffer: LongBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): Long = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun UByteBuffer.iterator(): UByteBufferIterator = UByteBufferIterator(this) + +class UByteBufferIterator(private val buffer: UByteBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): UByte = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun UShortBuffer.iterator(): UShortBufferIterator = UShortBufferIterator(this) + +class UShortBufferIterator(private val buffer: UShortBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): UShort = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun UIntBuffer.iterator(): UIntBufferIterator = UIntBufferIterator(this) + +class UIntBufferIterator(private val buffer: UIntBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): UInt = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun ULongBuffer.iterator(): ULongBufferIterator = ULongBufferIterator(this) + +class ULongBufferIterator(private val buffer: ULongBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): ULong = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun FloatBuffer.iterator(): FloatBufferIterator = FloatBufferIterator(this) + +class FloatBufferIterator(private val buffer: FloatBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): Float = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun DoubleBuffer.iterator(): DoubleBufferIterator = DoubleBufferIterator(this) + +class DoubleBufferIterator(private val buffer: DoubleBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): Double = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} +operator fun PointerBuffer.iterator(): PointerBufferIterator = PointerBufferIterator(this) + +class PointerBufferIterator(private val buffer: PointerBuffer) : Iterator { + private var position: Int = buffer.pos + override fun next(): Long = buffer[position++] + override fun hasNext(): Boolean = position < buffer.lim +} diff --git a/src/mainGen/kotlin/kool/pointers.kt b/src/mainGen/kotlin/kool/pointers.kt new file mode 100644 index 0000000..4bf9f6a --- /dev/null +++ b/src/mainGen/kotlin/kool/pointers.kt @@ -0,0 +1,544 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:OptIn(kotlin.experimental.ExperimentalTypeInference::class) +package kool +import kool.ubuffers.asUByteBuffer +import kool.ubuffers.UByteBuffer +import java.nio.LongBuffer +import kool.ubuffers.UShortBuffer +import java.nio.Buffer +import org.lwjgl.system.MemoryStack +import kool.ubuffers.asULongBuffer +import kool.ubuffers.ULongBuffer +import java.nio.IntBuffer +import org.lwjgl.system.Pointer +import java.nio.ByteBuffer +import org.lwjgl.PointerBuffer +import java.nio.ShortBuffer +import org.lwjgl.system.MemoryUtil +import kool.ubuffers.asUIntBuffer +import kool.ubuffers.asUShortBuffer +import java.nio.DoubleBuffer +import java.nio.FloatBuffer +import kool.ubuffers.UIntBuffer +import kool.adr + +inline infix operator fun Ptr.get(index: Int): Byte = get(index.toULong()) +inline infix operator fun Ptr.get(index: UInt): Byte = get(index.toULong()) +inline infix operator fun Ptr.get(index: Long): Byte = get(index.toULong()) +inline fun Ptr.get(): Byte = get(0uL) +inline infix operator fun Ptr.get(index: ULong): Byte = unsafe.getByte(adr + index) +inline infix operator fun Ptr.invoke(index: Int): Byte = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: UInt): Byte = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: Long): Byte = invoke(index.toULong()) +inline operator fun Ptr.invoke(): Byte = get(0uL) +inline infix operator fun Ptr.invoke(index: ULong): Byte = get(index) +@JvmName("plusByteInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusByteUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusByteLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusByteULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * Byte.BYTES.toULong()) +@JvmName("minusByteInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusByteUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusByteLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusByteULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * Byte.BYTES.toUInt()) +@JvmName("incByte") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decByte") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, byte: Byte) = set(index.toULong(), byte) +inline operator fun Ptr.set(index: UInt, byte: Byte) = set(index.toULong(), byte) +inline operator fun Ptr.set(index: Long, byte: Byte) = set(index.toULong(), byte) +inline operator fun Ptr.set(index: ULong, byte: Byte) = unsafe.set(adr + index, byte) +inline fun PtrByte(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), Byte.BYTES.toLong()).toPtr() +inline fun PtrByte(size: Int = 1, init: (Int) -> Byte): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrByte(size: Int = 1): Ptr = Ptr(ncalloc(Byte.BYTES, size, Byte.BYTES)) +inline fun MemoryStack.PtrByte(size: Int = 1, init: (Int) -> Byte): Ptr { + val ptr = nmalloc(Byte.BYTES, size).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline infix operator fun Ptr.get(index: Int): Short = get(index.toULong()) +inline infix operator fun Ptr.get(index: UInt): Short = get(index.toULong()) +inline infix operator fun Ptr.get(index: Long): Short = get(index.toULong()) +inline fun Ptr.get(): Short = get(0uL) +inline infix operator fun Ptr.get(index: ULong): Short = unsafe.getShort(adr + index * Short.BYTES.toULong()) +inline infix operator fun Ptr.invoke(index: Int): Short = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: UInt): Short = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: Long): Short = invoke(index.toULong()) +inline operator fun Ptr.invoke(): Short = get(0uL) +inline infix operator fun Ptr.invoke(index: ULong): Short = get(index) +@JvmName("plusShortInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusShortUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusShortLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusShortULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * Short.BYTES.toULong()) +@JvmName("minusShortInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusShortUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusShortLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusShortULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * Short.BYTES.toUInt()) +@JvmName("incShort") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decShort") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, short: Short) = set(index.toULong(), short) +inline operator fun Ptr.set(index: UInt, short: Short) = set(index.toULong(), short) +inline operator fun Ptr.set(index: Long, short: Short) = set(index.toULong(), short) +inline operator fun Ptr.set(index: ULong, short: Short) = unsafe.set(adr + index * Short.BYTES.toULong(), short) +inline fun PtrShort(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), Short.BYTES.toLong()).toPtr() +inline fun PtrShort(size: Int = 1, init: (Int) -> Short): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong() * Short.BYTES.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrShort(size: Int = 1): Ptr = Ptr(ncalloc(Short.BYTES, size, Short.BYTES)) +inline fun MemoryStack.PtrShort(size: Int = 1, init: (Int) -> Short): Ptr { + val ptr = nmalloc(Short.BYTES, size * Short.BYTES).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline infix operator fun Ptr.get(index: Int): Int = get(index.toULong()) +inline infix operator fun Ptr.get(index: UInt): Int = get(index.toULong()) +inline infix operator fun Ptr.get(index: Long): Int = get(index.toULong()) +inline fun Ptr.get(): Int = get(0uL) +inline infix operator fun Ptr.get(index: ULong): Int = unsafe.getInt(adr + index * Int.BYTES.toULong()) +inline infix operator fun Ptr.invoke(index: Int): Int = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: UInt): Int = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: Long): Int = invoke(index.toULong()) +inline operator fun Ptr.invoke(): Int = get(0uL) +inline infix operator fun Ptr.invoke(index: ULong): Int = get(index) +@JvmName("plusIntInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusIntUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusIntLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusIntULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * Int.BYTES.toULong()) +@JvmName("minusIntInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusIntUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusIntLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusIntULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * Int.BYTES.toUInt()) +@JvmName("incInt") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decInt") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, int: Int) = set(index.toULong(), int) +inline operator fun Ptr.set(index: UInt, int: Int) = set(index.toULong(), int) +inline operator fun Ptr.set(index: Long, int: Int) = set(index.toULong(), int) +inline operator fun Ptr.set(index: ULong, int: Int) = unsafe.set(adr + index * Int.BYTES.toULong(), int) +inline fun PtrInt(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), Int.BYTES.toLong()).toPtr() +inline fun PtrInt(size: Int = 1, init: (Int) -> Int): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong() * Int.BYTES.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrInt(size: Int = 1): Ptr = Ptr(ncalloc(Int.BYTES, size, Int.BYTES)) +inline fun MemoryStack.PtrInt(size: Int = 1, init: (Int) -> Int): Ptr { + val ptr = nmalloc(Int.BYTES, size * Int.BYTES).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline infix operator fun Ptr.get(index: Int): Long = get(index.toULong()) +inline infix operator fun Ptr.get(index: UInt): Long = get(index.toULong()) +inline infix operator fun Ptr.get(index: Long): Long = get(index.toULong()) +inline fun Ptr.get(): Long = get(0uL) +inline infix operator fun Ptr.get(index: ULong): Long = unsafe.getLong(adr + index * Long.BYTES.toULong()) +inline infix operator fun Ptr.invoke(index: Int): Long = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: UInt): Long = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: Long): Long = invoke(index.toULong()) +inline operator fun Ptr.invoke(): Long = get(0uL) +inline infix operator fun Ptr.invoke(index: ULong): Long = get(index) +@JvmName("plusLongInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusLongUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusLongLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusLongULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * Long.BYTES.toULong()) +@JvmName("minusLongInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusLongUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusLongLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusLongULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * Long.BYTES.toUInt()) +@JvmName("incLong") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decLong") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, long: Long) = set(index.toULong(), long) +inline operator fun Ptr.set(index: UInt, long: Long) = set(index.toULong(), long) +inline operator fun Ptr.set(index: Long, long: Long) = set(index.toULong(), long) +inline operator fun Ptr.set(index: ULong, long: Long) = unsafe.set(adr + index * Long.BYTES.toULong(), long) +inline fun PtrLong(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), Long.BYTES.toLong()).toPtr() +inline fun PtrLong(size: Int = 1, init: (Int) -> Long): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong() * Long.BYTES.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrLong(size: Int = 1): Ptr = Ptr(ncalloc(Long.BYTES, size, Long.BYTES)) +inline fun MemoryStack.PtrLong(size: Int = 1, init: (Int) -> Long): Ptr { + val ptr = nmalloc(Long.BYTES, size * Long.BYTES).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +@JvmName("getInt") +inline operator infix fun Ptr.get(index: Int): UByte = get(index.toULong()) +@JvmName("getUInt") +inline infix operator fun Ptr.get(index: UInt): UByte = get(index.toULong()) +@JvmName("getLong") +inline infix operator fun Ptr.get(index: Long): UByte = get(index.toULong()) +@JvmName("getULong") +inline fun Ptr.get(): UByte = get(0uL) +@JvmName("getULong") +inline infix operator fun Ptr.get(index: ULong): UByte = unsafe.getByte(adr + index).toUByte() +@JvmName("invokeInt") +inline infix operator fun Ptr.invoke(index: Int): UByte = invoke(index.toULong()) +@JvmName("invokeUInt") +inline infix operator fun Ptr.invoke(index: UInt): UByte = invoke(index.toULong()) +@JvmName("invokeLong") +inline infix operator fun Ptr.invoke(index: Long): UByte = invoke(index.toULong()) +@JvmName("invokeULong") +inline operator fun Ptr.invoke(): UByte = get(0uL) +@JvmName("invokeULong") +inline infix operator fun Ptr.invoke(index: ULong): UByte = get(index) +@JvmName("plusUByteInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusUByteUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusUByteLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusUByteULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * UByte.BYTES.toULong()) +@JvmName("minusUByteInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusUByteUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusUByteLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusUByteULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * UByte.BYTES.toULong()) +@JvmName("incUByte") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decUByte") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, uByte: UByte) = set(index.toULong(), uByte) +inline operator fun Ptr.set(index: UInt, uByte: UByte) = set(index.toULong(), uByte) +inline operator fun Ptr.set(index: Long, uByte: UByte) = set(index.toULong(), uByte) +inline operator fun Ptr.set(index: ULong, uByte: UByte) = unsafe.set(adr + index, uByte.toByte()) +inline fun PtrUByte(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), UByte.BYTES.toLong()).toPtr() +inline fun PtrUByte(size: Int = 1, init: (Int) -> UByte): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrUByte(size: Int = 1): Ptr = Ptr(ncalloc(UByte.BYTES, size, UByte.BYTES)) +inline fun MemoryStack.PtrUByte(size: Int = 1, init: (Int) -> UByte): Ptr { + val ptr = nmalloc(UByte.BYTES, size).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +@JvmName("getInt") +inline operator infix fun Ptr.get(index: Int): UShort = get(index.toULong()) +@JvmName("getUInt") +inline infix operator fun Ptr.get(index: UInt): UShort = get(index.toULong()) +@JvmName("getLong") +inline infix operator fun Ptr.get(index: Long): UShort = get(index.toULong()) +@JvmName("getULong") +inline fun Ptr.get(): UShort = get(0uL) +@JvmName("getULong") +inline infix operator fun Ptr.get(index: ULong): UShort = unsafe.getShort(adr + index * UShort.BYTES.toULong()).toUShort() +@JvmName("invokeInt") +inline infix operator fun Ptr.invoke(index: Int): UShort = invoke(index.toULong()) +@JvmName("invokeUInt") +inline infix operator fun Ptr.invoke(index: UInt): UShort = invoke(index.toULong()) +@JvmName("invokeLong") +inline infix operator fun Ptr.invoke(index: Long): UShort = invoke(index.toULong()) +@JvmName("invokeULong") +inline operator fun Ptr.invoke(): UShort = get(0uL) +@JvmName("invokeULong") +inline infix operator fun Ptr.invoke(index: ULong): UShort = get(index) +@JvmName("plusUShortInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusUShortUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusUShortLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusUShortULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * UShort.BYTES.toULong()) +@JvmName("minusUShortInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusUShortUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusUShortLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusUShortULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * UShort.BYTES.toULong()) +@JvmName("incUShort") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decUShort") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, uShort: UShort) = set(index.toULong(), uShort) +inline operator fun Ptr.set(index: UInt, uShort: UShort) = set(index.toULong(), uShort) +inline operator fun Ptr.set(index: Long, uShort: UShort) = set(index.toULong(), uShort) +inline operator fun Ptr.set(index: ULong, uShort: UShort) = unsafe.set(adr + index * UShort.BYTES.toULong(), uShort.toShort()) +inline fun PtrUShort(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), UShort.BYTES.toLong()).toPtr() +inline fun PtrUShort(size: Int = 1, init: (Int) -> UShort): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong() * UShort.BYTES.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrUShort(size: Int = 1): Ptr = Ptr(ncalloc(UShort.BYTES, size, UShort.BYTES)) +inline fun MemoryStack.PtrUShort(size: Int = 1, init: (Int) -> UShort): Ptr { + val ptr = nmalloc(UShort.BYTES, size * UShort.BYTES).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +@JvmName("getInt") +inline operator infix fun Ptr.get(index: Int): UInt = get(index.toULong()) +@JvmName("getUInt") +inline infix operator fun Ptr.get(index: UInt): UInt = get(index.toULong()) +@JvmName("getLong") +inline infix operator fun Ptr.get(index: Long): UInt = get(index.toULong()) +@JvmName("getULong") +inline fun Ptr.get(): UInt = get(0uL) +@JvmName("getULong") +inline infix operator fun Ptr.get(index: ULong): UInt = unsafe.getInt(adr + index * UInt.BYTES.toULong()).toUInt() +@JvmName("invokeInt") +inline infix operator fun Ptr.invoke(index: Int): UInt = invoke(index.toULong()) +@JvmName("invokeUInt") +inline infix operator fun Ptr.invoke(index: UInt): UInt = invoke(index.toULong()) +@JvmName("invokeLong") +inline infix operator fun Ptr.invoke(index: Long): UInt = invoke(index.toULong()) +@JvmName("invokeULong") +inline operator fun Ptr.invoke(): UInt = get(0uL) +@JvmName("invokeULong") +inline infix operator fun Ptr.invoke(index: ULong): UInt = get(index) +@JvmName("plusUIntInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusUIntUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusUIntLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusUIntULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * UInt.BYTES.toULong()) +@JvmName("minusUIntInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusUIntUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusUIntLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusUIntULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * UInt.BYTES.toULong()) +@JvmName("incUInt") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decUInt") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, uInt: UInt) = set(index.toULong(), uInt) +inline operator fun Ptr.set(index: UInt, uInt: UInt) = set(index.toULong(), uInt) +inline operator fun Ptr.set(index: Long, uInt: UInt) = set(index.toULong(), uInt) +inline operator fun Ptr.set(index: ULong, uInt: UInt) = unsafe.set(adr + index * UInt.BYTES.toULong(), uInt.toInt()) +inline fun PtrUInt(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), UInt.BYTES.toLong()).toPtr() +inline fun PtrUInt(size: Int = 1, init: (Int) -> UInt): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong() * UInt.BYTES.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrUInt(size: Int = 1): Ptr = Ptr(ncalloc(UInt.BYTES, size, UInt.BYTES)) +inline fun MemoryStack.PtrUInt(size: Int = 1, init: (Int) -> UInt): Ptr { + val ptr = nmalloc(UInt.BYTES, size * UInt.BYTES).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +@JvmName("getInt") +inline operator infix fun Ptr.get(index: Int): ULong = get(index.toULong()) +@JvmName("getUInt") +inline infix operator fun Ptr.get(index: UInt): ULong = get(index.toULong()) +@JvmName("getLong") +inline infix operator fun Ptr.get(index: Long): ULong = get(index.toULong()) +@JvmName("getULong") +inline fun Ptr.get(): ULong = get(0uL) +@JvmName("getULong") +inline infix operator fun Ptr.get(index: ULong): ULong = unsafe.getLong(adr + index * ULong.BYTES.toULong()).toULong() +@JvmName("invokeInt") +inline infix operator fun Ptr.invoke(index: Int): ULong = invoke(index.toULong()) +@JvmName("invokeUInt") +inline infix operator fun Ptr.invoke(index: UInt): ULong = invoke(index.toULong()) +@JvmName("invokeLong") +inline infix operator fun Ptr.invoke(index: Long): ULong = invoke(index.toULong()) +@JvmName("invokeULong") +inline operator fun Ptr.invoke(): ULong = get(0uL) +@JvmName("invokeULong") +inline infix operator fun Ptr.invoke(index: ULong): ULong = get(index) +@JvmName("plusULongInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusULongUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusULongLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusULongULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * ULong.BYTES.toULong()) +@JvmName("minusULongInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusULongUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusULongLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusULongULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * ULong.BYTES.toULong()) +@JvmName("incULong") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decULong") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, uLong: ULong) = set(index.toULong(), uLong) +inline operator fun Ptr.set(index: UInt, uLong: ULong) = set(index.toULong(), uLong) +inline operator fun Ptr.set(index: Long, uLong: ULong) = set(index.toULong(), uLong) +inline operator fun Ptr.set(index: ULong, uLong: ULong) = unsafe.set(adr + index * ULong.BYTES.toULong(), uLong.toLong()) +inline fun PtrULong(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), ULong.BYTES.toLong()).toPtr() +inline fun PtrULong(size: Int = 1, init: (Int) -> ULong): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong() * ULong.BYTES.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrULong(size: Int = 1): Ptr = Ptr(ncalloc(ULong.BYTES, size, ULong.BYTES)) +inline fun MemoryStack.PtrULong(size: Int = 1, init: (Int) -> ULong): Ptr { + val ptr = nmalloc(ULong.BYTES, size * ULong.BYTES).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline infix operator fun Ptr.get(index: Int): Float = get(index.toULong()) +inline infix operator fun Ptr.get(index: UInt): Float = get(index.toULong()) +inline infix operator fun Ptr.get(index: Long): Float = get(index.toULong()) +inline fun Ptr.get(): Float = get(0uL) +inline infix operator fun Ptr.get(index: ULong): Float = unsafe.getFloat(adr + index * Float.BYTES.toULong()) +inline infix operator fun Ptr.invoke(index: Int): Float = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: UInt): Float = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: Long): Float = invoke(index.toULong()) +inline operator fun Ptr.invoke(): Float = get(0uL) +inline infix operator fun Ptr.invoke(index: ULong): Float = get(index) +@JvmName("plusFloatInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusFloatUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusFloatLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusFloatULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * Float.BYTES.toULong()) +@JvmName("minusFloatInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusFloatUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusFloatLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusFloatULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * Float.BYTES.toUInt()) +@JvmName("incFloat") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decFloat") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, float: Float) = set(index.toULong(), float) +inline operator fun Ptr.set(index: UInt, float: Float) = set(index.toULong(), float) +inline operator fun Ptr.set(index: Long, float: Float) = set(index.toULong(), float) +inline operator fun Ptr.set(index: ULong, float: Float) = unsafe.set(adr + index * Float.BYTES.toULong(), float) +inline fun PtrFloat(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), Float.BYTES.toLong()).toPtr() +inline fun PtrFloat(size: Int = 1, init: (Int) -> Float): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong() * Float.BYTES.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrFloat(size: Int = 1): Ptr = Ptr(ncalloc(Float.BYTES, size, Float.BYTES)) +inline fun MemoryStack.PtrFloat(size: Int = 1, init: (Int) -> Float): Ptr { + val ptr = nmalloc(Float.BYTES, size * Float.BYTES).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline infix operator fun Ptr.get(index: Int): Double = get(index.toULong()) +inline infix operator fun Ptr.get(index: UInt): Double = get(index.toULong()) +inline infix operator fun Ptr.get(index: Long): Double = get(index.toULong()) +inline fun Ptr.get(): Double = get(0uL) +inline infix operator fun Ptr.get(index: ULong): Double = unsafe.getDouble(adr + index * Double.BYTES.toULong()) +inline infix operator fun Ptr.invoke(index: Int): Double = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: UInt): Double = invoke(index.toULong()) +inline infix operator fun Ptr.invoke(index: Long): Double = invoke(index.toULong()) +inline operator fun Ptr.invoke(): Double = get(0uL) +inline infix operator fun Ptr.invoke(index: ULong): Double = get(index) +@JvmName("plusDoubleInt") +inline infix operator fun Ptr.plus(offset: Int): Ptr = plus(offset.toULong()) +@JvmName("plusDoubleUInt") +inline infix operator fun Ptr.plus(offset: UInt): Ptr = plus(offset.toULong()) +@JvmName("plusDoubleLong") +inline infix operator fun Ptr.plus(offset: Long): Ptr = plus(offset.toULong()) +@JvmName("plusDoubleULong") +inline infix operator fun Ptr.plus(offset: ULong): Ptr = Ptr(address + offset * Double.BYTES.toULong()) +@JvmName("minusDoubleInt") +inline infix operator fun Ptr.minus(offset: Int): Ptr = minus(offset.toULong()) +@JvmName("minusDoubleUInt") +inline infix operator fun Ptr.minus(offset: UInt): Ptr = minus(offset.toULong()) +@JvmName("minusDoubleLong") +inline infix operator fun Ptr.minus(offset: Long): Ptr = minus(offset.toULong()) +@JvmName("minusDoubleULong") +inline infix operator fun Ptr.minus(offset: ULong): Ptr = Ptr(address - offset * Double.BYTES.toUInt()) +@JvmName("incDouble") +inline operator fun Ptr.inc(): Ptr = plus(1) +@JvmName("decDouble") +inline operator fun Ptr.dec(): Ptr = minus(1) +inline operator fun Ptr.set(index: Int, double: Double) = set(index.toULong(), double) +inline operator fun Ptr.set(index: UInt, double: Double) = set(index.toULong(), double) +inline operator fun Ptr.set(index: Long, double: Double) = set(index.toULong(), double) +inline operator fun Ptr.set(index: ULong, double: Double) = unsafe.set(adr + index * Double.BYTES.toULong(), double) +inline fun PtrDouble(size: Int = 1): Ptr = MemoryUtil.nmemCalloc(size.toLong(), Double.BYTES.toLong()).toPtr() +inline fun PtrDouble(size: Int = 1, init: (Int) -> Double): Ptr { + val ptr = MemoryUtil.nmemAlloc(size.toLong() * Double.BYTES.toLong()).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} +inline fun MemoryStack.PtrDouble(size: Int = 1): Ptr = Ptr(ncalloc(Double.BYTES, size, Double.BYTES)) +inline fun MemoryStack.PtrDouble(size: Int = 1, init: (Int) -> Double): Ptr { + val ptr = nmalloc(Double.BYTES, size * Double.BYTES).toPtr() + for (i in 0 until size) + ptr[i] = init(i) + return ptr +} diff --git a/src/mainGen/kotlin/kool/stack.kt b/src/mainGen/kotlin/kool/stack.kt new file mode 100644 index 0000000..4ebe3f4 --- /dev/null +++ b/src/mainGen/kotlin/kool/stack.kt @@ -0,0 +1,216 @@ +@file:OptIn(kotlin.contracts.ExperimentalContracts::class) +package kool +import kool.ubuffers.asUByteBuffer +import kool.ubuffers.UByteBuffer +import java.nio.LongBuffer +import kool.ubuffers.UShortBuffer +import java.nio.Buffer +import org.lwjgl.system.MemoryStack +import kool.ubuffers.asULongBuffer +import kool.ubuffers.ULongBuffer +import java.nio.IntBuffer +import java.nio.ByteBuffer +import java.nio.ShortBuffer +import org.lwjgl.system.MemoryUtil +import kool.ubuffers.asUIntBuffer +import kool.ubuffers.asUShortBuffer +import java.nio.DoubleBuffer +import java.nio.FloatBuffer +import kool.ubuffers.UIntBuffer + +object stack { + // --------------------------------------------- getters --------------------------------------------- + + inline fun read(block: (Adr) -> R): T = when (T::class.java) { + Byte::class.java -> readByteFromAdr(block) + UByte::class.java -> readUByteFromAdr(block) + Short::class.java -> readShortFromAdr(block) + UShort::class.java -> readUShortFromAdr(block) + Int::class.java -> readIntFromAdr(block) + UInt::class.java -> readUIntFromAdr(block) + Long::class.java -> readLongFromAdr(block) + ULong::class.java -> readULongFromAdr(block) + Float::class.java -> readFloatFromAdr(block) + Double::class.java -> readDoubleFromAdr(block) + else -> error("") + } as T + /*inline fun read(block: (ByteBuffer) -> R): T = when (T::class.java) { + Byte::class.java -> readByte(block) + UByte::class.java -> readUByte(block) + Short::class.java -> readShort(block) + UShort::class.java -> readUShort(block) + Int::class.java -> readInt(block) + UInt::class.java -> readUInt(block) + Long::class.java -> readLong(block) + ULong::class.java -> readULong(block) + Float::class.java -> readFloat(block) + Double::class.java -> readDouble(block) + else -> error("") + } as T*/ + inline fun readByteFromAdr(block: (Adr) -> R): Byte = with { PtrByte().apply { block(adr) }.invoke() } + + inline fun readByteFromBuf(block: (ByteBuffer) -> R): Byte = with { + val buf = malloc(1) + block(buf) + buf[0] + } + inline fun readShortFromAdr(block: (Adr) -> R): Short = with { PtrShort().apply { block(adr) }.invoke() } + + inline fun readShortFromBuf(block: (ShortBuffer) -> R): Short = with { + val buf = mallocShort(1) + block(buf) + buf[0] + } + inline fun readIntFromAdr(block: (Adr) -> R): Int = with { PtrInt().apply { block(adr) }.invoke() } + + inline fun readIntFromBuf(block: (IntBuffer) -> R): Int = with { + val buf = mallocInt(1) + block(buf) + buf[0] + } + inline fun readLongFromAdr(block: (Adr) -> R): Long = with { PtrLong().apply { block(adr) }.invoke() } + + inline fun readLongFromBuf(block: (LongBuffer) -> R): Long = with { + val buf = mallocLong(1) + block(buf) + buf[0] + } + inline fun readUByteFromAdr(block: (Adr) -> R): UByte = with { PtrUByte().apply { block(adr) }.invoke() } + + inline fun readUByteFromBuf(block: (UByteBuffer) -> R): UByte = with { + val buf = malloc(1).asUByteBuffer() + block(buf) + buf[0] + } + inline fun readUShortFromAdr(block: (Adr) -> R): UShort = with { PtrUShort().apply { block(adr) }.invoke() } + + inline fun readUShortFromBuf(block: (UShortBuffer) -> R): UShort = with { + val buf = mallocShort(1).asUShortBuffer() + block(buf) + buf[0] + } + inline fun readUIntFromAdr(block: (Adr) -> R): UInt = with { PtrUInt().apply { block(adr) }.invoke() } + + inline fun readUIntFromBuf(block: (UIntBuffer) -> R): UInt = with { + val buf = mallocInt(1).asUIntBuffer() + block(buf) + buf[0] + } + inline fun readULongFromAdr(block: (Adr) -> R): ULong = with { PtrULong().apply { block(adr) }.invoke() } + + inline fun readULongFromBuf(block: (ULongBuffer) -> R): ULong = with { + val buf = mallocLong(1).asULongBuffer() + block(buf) + buf[0] + } + inline fun readFloatFromAdr(block: (Adr) -> R): Float = with { PtrFloat().apply { block(adr) }.invoke() } + + inline fun readFloatFromBuf(block: (FloatBuffer) -> R): Float = with { + val buf = mallocFloat(1) + block(buf) + buf[0] + } + inline fun readDoubleFromAdr(block: (Adr) -> R): Double = with { PtrDouble().apply { block(adr) }.invoke() } + + inline fun readDoubleFromBuf(block: (DoubleBuffer) -> R): Double = with { + val buf = mallocDouble(1) + block(buf) + buf[0] + } + /** It mallocs, passes the address and reads the null terminated string */ + inline fun readAsciiFromAdr(maxSize: Int, block: (Adr) -> R): String = with { + val adr = nmalloc(1, maxSize) + block(adr.toULong()) + return MemoryUtil.memASCII(adr, strlen64NT1(adr, maxSize)) + } + + /** It mallocs the buffer, passes it and reads the null terminated string */ + inline fun readAsciiFromBuf(maxSize: Int, block: (ByteBuffer) -> R): String = with { + val buf = malloc(1, maxSize) + block(buf) + return MemoryUtil.memASCII(buf.adr.toLong(), maxSize) + } + /** It mallocs, passes the address and reads the null terminated string */ + inline fun readUtf8FromAdr(maxSize: Int, block: (Adr) -> R): String = with { + val adr = nmalloc(1, maxSize) + block(adr.toULong()) + return MemoryUtil.memUTF8(adr, strlen64NT1(adr, maxSize)) + } + + /** It mallocs the buffer, passes it and reads the null terminated string */ + inline fun readUtf8FromBuf(maxSize: Int, block: (ByteBuffer) -> R): String = with { + val buf = malloc(1, maxSize) + block(buf) + return MemoryUtil.memUTF8(buf.adr.toLong(), maxSize) + } + /** It mallocs, passes the address and reads the null terminated string */ + inline fun readUtf16FromAdr(maxSize: Int, block: (Adr) -> R): String = with { + val adr = nmalloc(1, maxSize) + block(adr.toULong()) + return MemoryUtil.memUTF16(adr, strlen64NT1(adr, maxSize)) + } + + /** It mallocs the buffer, passes it and reads the null terminated string */ + inline fun readUtf16FromBuf(maxSize: Int, block: (ByteBuffer) -> R): String = with { + val buf = malloc(1, maxSize) + block(buf) + return MemoryUtil.memUTF16(buf.adr.toLong(), maxSize) + } + // TODO, when limitation is lifted on contracts in members, implement it + // @OptIn(ExperimentalContracts::class) + inline operator fun invoke(block: (MemoryStack) -> R): R = with(block) + + // --------------------------------------------- setters --------------------------------------------- + inline fun writeToAdr(byte: Byte, block: (Adr) -> R): R = with { block(ptrOf(byte).adr) } + inline fun writeToBuf(byte: Byte, block: (ByteBuffer) -> R): R = with { block(bufferOf(byte)) } + inline fun writeToAdr(short: Short, block: (Adr) -> R): R = with { block(ptrOf(short).adr) } + inline fun writeToBuf(short: Short, block: (ShortBuffer) -> R): R = with { block(bufferOf(short)) } + inline fun writeToAdr(int: Int, block: (Adr) -> R): R = with { block(ptrOf(int).adr) } + inline fun writeToBuf(int: Int, block: (IntBuffer) -> R): R = with { block(bufferOf(int)) } + inline fun writeToAdr(long: Long, block: (Adr) -> R): R = with { block(ptrOf(long).adr) } + inline fun writeToBuf(long: Long, block: (LongBuffer) -> R): R = with { block(bufferOf(long)) } + inline fun writeToAdr(ubyte: UByte, block: (Adr) -> R): R = with { block(ptrOf(ubyte).adr) } + inline fun writeToBuf(ubyte: UByte, block: (UByteBuffer) -> R): R = with { block(bufferOf(ubyte)) } + inline fun writeToAdr(ushort: UShort, block: (Adr) -> R): R = with { block(ptrOf(ushort).adr) } + inline fun writeToBuf(ushort: UShort, block: (UShortBuffer) -> R): R = with { block(bufferOf(ushort)) } + inline fun writeToAdr(uint: UInt, block: (Adr) -> R): R = with { block(ptrOf(uint).adr) } + inline fun writeToBuf(uint: UInt, block: (UIntBuffer) -> R): R = with { block(bufferOf(uint)) } + inline fun writeToAdr(ulong: ULong, block: (Adr) -> R): R = with { block(ptrOf(ulong).adr) } + inline fun writeToBuf(ulong: ULong, block: (ULongBuffer) -> R): R = with { block(bufferOf(ulong)) } + inline fun writeToAdr(float: Float, block: (Adr) -> R): R = with { block(ptrOf(float).adr) } + inline fun writeToBuf(float: Float, block: (FloatBuffer) -> R): R = with { block(bufferOf(float)) } + inline fun writeToAdr(double: Double, block: (Adr) -> R): R = with { block(ptrOf(double).adr) } + inline fun writeToBuf(double: Double, block: (DoubleBuffer) -> R): R = with { block(bufferOf(double)) } + inline fun writeAsciiToAdr(chars: CharSequence, nullTerminated: Boolean = true, block: (Adr) -> R): R = + with { + nASCII(chars, nullTerminated) + block(pointerAddress.toULong()) + } + + inline fun writeAsciiToBuf(chars: CharSequence, nullTerminated: Boolean = true, block: (ByteBuffer) -> R): R = + with { block(ASCII(chars, nullTerminated)) } + inline fun writeUtf8ToAdr(chars: CharSequence, nullTerminated: Boolean = true, block: (Adr) -> R): R = + with { + nUTF8(chars, nullTerminated) + block(pointerAddress.toULong()) + } + + inline fun writeUtf8ToBuf(chars: CharSequence, nullTerminated: Boolean = true, block: (ByteBuffer) -> R): R = + with { block(UTF8(chars, nullTerminated)) } + inline fun writeUtf16ToAdr(chars: CharSequence, nullTerminated: Boolean = true, block: (Adr) -> R): R = + with { + nUTF16(chars, nullTerminated) + block(pointerAddress.toULong()) + } + + inline fun writeUtf16ToBuf(chars: CharSequence, nullTerminated: Boolean = true, block: (ByteBuffer) -> R): R = + with { block(UTF16(chars, nullTerminated)) } +} +inline fun stack.with(block: MemoryStack.() -> R): R { + kotlin.contracts.contract { callsInPlace(block, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } + val stack = MemoryStack.stackGet() + val ptr = stack.pointer + return block(stack).also { + stack.pointer = ptr + } +} diff --git a/src/mainGen/kotlin/kool/stackExts.kt b/src/mainGen/kotlin/kool/stackExts.kt new file mode 100644 index 0000000..230e86c --- /dev/null +++ b/src/mainGen/kotlin/kool/stackExts.kt @@ -0,0 +1,868 @@ +@file:OptIn(kotlin.ExperimentalUnsignedTypes::class) +package kool +import kool.ubuffers.UByteBuffer +import java.nio.LongBuffer +import kool.ubuffers.UShortBuffer +import java.nio.Buffer +import org.lwjgl.system.MemoryStack +import kool.ubuffers.ULongBuffer +import java.nio.IntBuffer +import org.lwjgl.system.Pointer +import java.nio.ByteBuffer +import org.lwjgl.PointerBuffer +import java.nio.ShortBuffer +import org.lwjgl.system.MemoryUtil +import java.nio.DoubleBuffer +import java.nio.FloatBuffer +import kool.ubuffers.UIntBuffer + +fun MemoryStack.ptrOf(b1: Byte): Ptr { + val ptr = PtrByte(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: Byte): ByteBuffer { + val buf = ByteBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: Byte, b2: Byte): Ptr { + val ptr = PtrByte(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: Byte, b2: Byte): ByteBuffer { + val buf = ByteBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: Byte, b2: Byte, b3: Byte): Ptr { + val ptr = PtrByte(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: Byte, b2: Byte, b3: Byte): ByteBuffer { + val buf = ByteBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: Byte, b2: Byte, b3: Byte, b4: Byte): Ptr { + val ptr = PtrByte(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: Byte, b2: Byte, b3: Byte, b4: Byte): ByteBuffer { + val buf = ByteBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: Byte, b2: Byte, b3: Byte, b4: Byte, b5: Byte): Ptr { + val ptr = PtrByte(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: Byte, b2: Byte, b3: Byte, b4: Byte, b5: Byte): ByteBuffer { + val buf = ByteBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg bytes: Byte): Ptr { + val ptr = PtrByte(bytes.size) + for (i in bytes.indices) + ptr[i] = bytes[i] + return ptr +} +fun MemoryStack.ptrOf(b1: Short): Ptr { + val ptr = PtrShort(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: Short): ShortBuffer { + val buf = ShortBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: Short, b2: Short): Ptr { + val ptr = PtrShort(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: Short, b2: Short): ShortBuffer { + val buf = ShortBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: Short, b2: Short, b3: Short): Ptr { + val ptr = PtrShort(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: Short, b2: Short, b3: Short): ShortBuffer { + val buf = ShortBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: Short, b2: Short, b3: Short, b4: Short): Ptr { + val ptr = PtrShort(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: Short, b2: Short, b3: Short, b4: Short): ShortBuffer { + val buf = ShortBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: Short, b2: Short, b3: Short, b4: Short, b5: Short): Ptr { + val ptr = PtrShort(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: Short, b2: Short, b3: Short, b4: Short, b5: Short): ShortBuffer { + val buf = ShortBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg shorts: Short): Ptr { + val ptr = PtrShort(shorts.size) + for (i in shorts.indices) + ptr[i] = shorts[i] + return ptr +} +fun MemoryStack.ptrOf(b1: Int): Ptr { + val ptr = PtrInt(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: Int): IntBuffer { + val buf = IntBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: Int, b2: Int): Ptr { + val ptr = PtrInt(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: Int, b2: Int): IntBuffer { + val buf = IntBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: Int, b2: Int, b3: Int): Ptr { + val ptr = PtrInt(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: Int, b2: Int, b3: Int): IntBuffer { + val buf = IntBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: Int, b2: Int, b3: Int, b4: Int): Ptr { + val ptr = PtrInt(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: Int, b2: Int, b3: Int, b4: Int): IntBuffer { + val buf = IntBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: Int, b2: Int, b3: Int, b4: Int, b5: Int): Ptr { + val ptr = PtrInt(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: Int, b2: Int, b3: Int, b4: Int, b5: Int): IntBuffer { + val buf = IntBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg ints: Int): Ptr { + val ptr = PtrInt(ints.size) + for (i in ints.indices) + ptr[i] = ints[i] + return ptr +} +fun MemoryStack.ptrOf(b1: Long): Ptr { + val ptr = PtrLong(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: Long): LongBuffer { + val buf = LongBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: Long, b2: Long): Ptr { + val ptr = PtrLong(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: Long, b2: Long): LongBuffer { + val buf = LongBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: Long, b2: Long, b3: Long): Ptr { + val ptr = PtrLong(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: Long, b2: Long, b3: Long): LongBuffer { + val buf = LongBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: Long, b2: Long, b3: Long, b4: Long): Ptr { + val ptr = PtrLong(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: Long, b2: Long, b3: Long, b4: Long): LongBuffer { + val buf = LongBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: Long, b2: Long, b3: Long, b4: Long, b5: Long): Ptr { + val ptr = PtrLong(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: Long, b2: Long, b3: Long, b4: Long, b5: Long): LongBuffer { + val buf = LongBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg longs: Long): Ptr { + val ptr = PtrLong(longs.size) + for (i in longs.indices) + ptr[i] = longs[i] + return ptr +} +fun MemoryStack.ptrOf(b1: UByte): Ptr { + val ptr = PtrUByte(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: UByte): UByteBuffer { + val buf = UByteBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: UByte, b2: UByte): Ptr { + val ptr = PtrUByte(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: UByte, b2: UByte): UByteBuffer { + val buf = UByteBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: UByte, b2: UByte, b3: UByte): Ptr { + val ptr = PtrUByte(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: UByte, b2: UByte, b3: UByte): UByteBuffer { + val buf = UByteBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: UByte, b2: UByte, b3: UByte, b4: UByte): Ptr { + val ptr = PtrUByte(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: UByte, b2: UByte, b3: UByte, b4: UByte): UByteBuffer { + val buf = UByteBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: UByte, b2: UByte, b3: UByte, b4: UByte, b5: UByte): Ptr { + val ptr = PtrUByte(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: UByte, b2: UByte, b3: UByte, b4: UByte, b5: UByte): UByteBuffer { + val buf = UByteBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg ubytes: UByte): Ptr { + val ptr = PtrUByte(ubytes.size) + for (i in ubytes.indices) + ptr[i] = ubytes[i] + return ptr +} +fun MemoryStack.ptrOf(b1: UShort): Ptr { + val ptr = PtrUShort(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: UShort): UShortBuffer { + val buf = UShortBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: UShort, b2: UShort): Ptr { + val ptr = PtrUShort(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: UShort, b2: UShort): UShortBuffer { + val buf = UShortBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: UShort, b2: UShort, b3: UShort): Ptr { + val ptr = PtrUShort(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: UShort, b2: UShort, b3: UShort): UShortBuffer { + val buf = UShortBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: UShort, b2: UShort, b3: UShort, b4: UShort): Ptr { + val ptr = PtrUShort(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: UShort, b2: UShort, b3: UShort, b4: UShort): UShortBuffer { + val buf = UShortBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: UShort, b2: UShort, b3: UShort, b4: UShort, b5: UShort): Ptr { + val ptr = PtrUShort(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: UShort, b2: UShort, b3: UShort, b4: UShort, b5: UShort): UShortBuffer { + val buf = UShortBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg ushorts: UShort): Ptr { + val ptr = PtrUShort(ushorts.size) + for (i in ushorts.indices) + ptr[i] = ushorts[i] + return ptr +} +fun MemoryStack.ptrOf(b1: UInt): Ptr { + val ptr = PtrUInt(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: UInt): UIntBuffer { + val buf = UIntBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: UInt, b2: UInt): Ptr { + val ptr = PtrUInt(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: UInt, b2: UInt): UIntBuffer { + val buf = UIntBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: UInt, b2: UInt, b3: UInt): Ptr { + val ptr = PtrUInt(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: UInt, b2: UInt, b3: UInt): UIntBuffer { + val buf = UIntBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: UInt, b2: UInt, b3: UInt, b4: UInt): Ptr { + val ptr = PtrUInt(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: UInt, b2: UInt, b3: UInt, b4: UInt): UIntBuffer { + val buf = UIntBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: UInt, b2: UInt, b3: UInt, b4: UInt, b5: UInt): Ptr { + val ptr = PtrUInt(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: UInt, b2: UInt, b3: UInt, b4: UInt, b5: UInt): UIntBuffer { + val buf = UIntBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg uints: UInt): Ptr { + val ptr = PtrUInt(uints.size) + for (i in uints.indices) + ptr[i] = uints[i] + return ptr +} +fun MemoryStack.ptrOf(b1: ULong): Ptr { + val ptr = PtrULong(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: ULong): ULongBuffer { + val buf = ULongBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: ULong, b2: ULong): Ptr { + val ptr = PtrULong(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: ULong, b2: ULong): ULongBuffer { + val buf = ULongBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: ULong, b2: ULong, b3: ULong): Ptr { + val ptr = PtrULong(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: ULong, b2: ULong, b3: ULong): ULongBuffer { + val buf = ULongBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: ULong, b2: ULong, b3: ULong, b4: ULong): Ptr { + val ptr = PtrULong(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: ULong, b2: ULong, b3: ULong, b4: ULong): ULongBuffer { + val buf = ULongBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: ULong, b2: ULong, b3: ULong, b4: ULong, b5: ULong): Ptr { + val ptr = PtrULong(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: ULong, b2: ULong, b3: ULong, b4: ULong, b5: ULong): ULongBuffer { + val buf = ULongBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg ulongs: ULong): Ptr { + val ptr = PtrULong(ulongs.size) + for (i in ulongs.indices) + ptr[i] = ulongs[i] + return ptr +} +fun MemoryStack.ptrOf(b1: Float): Ptr { + val ptr = PtrFloat(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: Float): FloatBuffer { + val buf = FloatBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: Float, b2: Float): Ptr { + val ptr = PtrFloat(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: Float, b2: Float): FloatBuffer { + val buf = FloatBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: Float, b2: Float, b3: Float): Ptr { + val ptr = PtrFloat(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: Float, b2: Float, b3: Float): FloatBuffer { + val buf = FloatBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: Float, b2: Float, b3: Float, b4: Float): Ptr { + val ptr = PtrFloat(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: Float, b2: Float, b3: Float, b4: Float): FloatBuffer { + val buf = FloatBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: Float, b2: Float, b3: Float, b4: Float, b5: Float): Ptr { + val ptr = PtrFloat(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: Float, b2: Float, b3: Float, b4: Float, b5: Float): FloatBuffer { + val buf = FloatBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg floats: Float): Ptr { + val ptr = PtrFloat(floats.size) + for (i in floats.indices) + ptr[i] = floats[i] + return ptr +} +fun MemoryStack.ptrOf(b1: Double): Ptr { + val ptr = PtrDouble(1) + ptr[0] = b1 + return ptr +} +fun MemoryStack.bufferOf(b1: Double): DoubleBuffer { + val buf = DoubleBuffer(1) + buf[0] = b1 + return buf +} +fun MemoryStack.ptrOf(b1: Double, b2: Double): Ptr { + val ptr = PtrDouble(2) + ptr[0] = b1 + ptr[1] = b2 + return ptr +} +fun MemoryStack.bufferOf(b1: Double, b2: Double): DoubleBuffer { + val buf = DoubleBuffer(2) + buf[0] = b1 + buf[1] = b2 + return buf +} +fun MemoryStack.ptrOf(b1: Double, b2: Double, b3: Double): Ptr { + val ptr = PtrDouble(3) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + return ptr +} +fun MemoryStack.bufferOf(b1: Double, b2: Double, b3: Double): DoubleBuffer { + val buf = DoubleBuffer(3) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + return buf +} +fun MemoryStack.ptrOf(b1: Double, b2: Double, b3: Double, b4: Double): Ptr { + val ptr = PtrDouble(4) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + return ptr +} +fun MemoryStack.bufferOf(b1: Double, b2: Double, b3: Double, b4: Double): DoubleBuffer { + val buf = DoubleBuffer(4) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + return buf +} +fun MemoryStack.ptrOf(b1: Double, b2: Double, b3: Double, b4: Double, b5: Double): Ptr { + val ptr = PtrDouble(5) + ptr[0] = b1 + ptr[1] = b2 + ptr[2] = b3 + ptr[3] = b4 + ptr[4] = b5 + return ptr +} +fun MemoryStack.bufferOf(b1: Double, b2: Double, b3: Double, b4: Double, b5: Double): DoubleBuffer { + val buf = DoubleBuffer(5) + buf[0] = b1 + buf[1] = b2 + buf[2] = b3 + buf[3] = b4 + buf[4] = b5 + return buf +} +fun MemoryStack.ptrOf(vararg doubles: Double): Ptr { + val ptr = PtrDouble(doubles.size) + for (i in doubles.indices) + ptr[i] = doubles[i] + return ptr +} +// --------------------------------------------- getters --------------------------------------------- +inline fun MemoryStack.read(block: (Adr) -> R): T = when (T::class.java) { + Byte::class.java -> readByteFromAdr(block) + UByte::class.java -> readUByteFromAdr(block) + Short::class.java -> readShortFromAdr(block) + UShort::class.java -> readUShortFromAdr(block) + Int::class.java -> readIntFromAdr(block) + UInt::class.java -> readUIntFromAdr(block) + Long::class.java -> readLongFromAdr(block) + ULong::class.java -> readULongFromAdr(block) + Float::class.java -> readFloatFromAdr(block) + Double::class.java -> readDoubleFromAdr(block) + else -> error("") +} as T +inline fun MemoryStack.readByteFromAdr(block: (Adr) -> R): Byte = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readByteFromBuf(block: (ByteBuffer) -> R): Byte = ByteBuffer(1).also { block(it) }[0] +inline fun MemoryStack.readShortFromAdr(block: (Adr) -> R): Short = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readShortFromBuf(block: (ShortBuffer) -> R): Short = ShortBuffer(1).also { block(it) }[0] +inline fun MemoryStack.readIntFromAdr(block: (Adr) -> R): Int = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readIntFromBuf(block: (IntBuffer) -> R): Int = IntBuffer(1).also { block(it) }[0] +inline fun MemoryStack.readLongFromAdr(block: (Adr) -> R): Long = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readLongFromBuf(block: (LongBuffer) -> R): Long = LongBuffer(1).also { block(it) }[0] +inline fun MemoryStack.readUByteFromAdr(block: (Adr) -> R): UByte = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readUByteFromBuf(block: (UByteBuffer) -> R): UByte = UByteBuffer(1).also { block(it) }[0] +inline fun MemoryStack.readUShortFromAdr(block: (Adr) -> R): UShort = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readUShortFromBuf(block: (UShortBuffer) -> R): UShort = UShortBuffer(1).also { block(it) }[0] +inline fun MemoryStack.readUIntFromAdr(block: (Adr) -> R): UInt = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readUIntFromBuf(block: (UIntBuffer) -> R): UInt = UIntBuffer(1).also { block(it) }[0] +inline fun MemoryStack.readULongFromAdr(block: (Adr) -> R): ULong = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readULongFromBuf(block: (ULongBuffer) -> R): ULong = ULongBuffer(1).also { block(it) }[0] +inline fun MemoryStack.readFloatFromAdr(block: (Adr) -> R): Float = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readFloatFromBuf(block: (FloatBuffer) -> R): Float = FloatBuffer(1).also { block(it) }[0] +inline fun MemoryStack.readDoubleFromAdr(block: (Adr) -> R): Double = Ptr().apply { block(adr) }.invoke() +inline fun MemoryStack.readDoubleFromBuf(block: (DoubleBuffer) -> R): Double = DoubleBuffer(1).also { block(it) }[0] +/*inline fun MemoryStack.pointerAdr(block: (Adr) -> R): Ptr { + val ptr = PointerPtr() + block(ptr.adr) + return ptr() +}*/ +inline fun MemoryStack.pointerBuffer(block: (PointerBuffer) -> R): Long { + val buf = mallocPointer(1) + block(buf) + return buf[0] +} +/** It mallocs, passes the address and reads the null terminated string */ +inline fun MemoryStack.readAsciiFromAdr(maxSize: Int, block: (Adr) -> R): String { + val adr = nmalloc(1, maxSize) + block(adr.toULong()) + return MemoryUtil.memASCII(adr, strlen64NT1(adr, maxSize)) +} + +/** It mallocs the buffer, passes it and reads the null terminated string */ +inline fun MemoryStack.readAsciiFromBuf(maxSize: Int, block: (ByteBuffer) -> R): String { + val buf = malloc(1, maxSize) + block(buf) + return MemoryUtil.memASCII(buf.adr.toLong(), maxSize) +} +/** It mallocs, passes the address and reads the null terminated string */ +inline fun MemoryStack.readUtf8FromAdr(maxSize: Int, block: (Adr) -> R): String { + val adr = nmalloc(1, maxSize) + block(adr.toULong()) + return MemoryUtil.memUTF8(adr, strlen64NT1(adr, maxSize)) +} + +/** It mallocs the buffer, passes it and reads the null terminated string */ +inline fun MemoryStack.readUtf8FromBuf(maxSize: Int, block: (ByteBuffer) -> R): String { + val buf = malloc(1, maxSize) + block(buf) + return MemoryUtil.memUTF8(buf.adr.toLong(), maxSize) +} +/** It mallocs, passes the address and reads the null terminated string */ +inline fun MemoryStack.readUtf16FromAdr(maxSize: Int, block: (Adr) -> R): String { + val adr = nmalloc(1, maxSize) + block(adr.toULong()) + return MemoryUtil.memUTF16(adr, strlen64NT1(adr, maxSize)) +} + +/** It mallocs the buffer, passes it and reads the null terminated string */ +inline fun MemoryStack.readUtf16FromBuf(maxSize: Int, block: (ByteBuffer) -> R): String { + val buf = malloc(1, maxSize) + block(buf) + return MemoryUtil.memUTF16(buf.adr.toLong(), maxSize) +} +// --------------------------------------------- setters --------------------------------------------- +fun MemoryStack.writeAsciiToAdr(chars: CharSequence, nullTerminated: Boolean = true): Adr = nASCII(chars, nullTerminated).let { pointerAddress }.toULong() +fun MemoryStack.writeAsciiToBuffer(chars: CharSequence, nullTerminated: Boolean = true): ByteBuffer = ASCII(chars, nullTerminated) +fun MemoryStack.writeUtf8ToAdr(chars: CharSequence, nullTerminated: Boolean = true): Adr = nUTF8(chars, nullTerminated).let { pointerAddress }.toULong() +fun MemoryStack.writeUtf8ToBuffer(chars: CharSequence, nullTerminated: Boolean = true): ByteBuffer = UTF8(chars, nullTerminated) +fun MemoryStack.writeUtf16ToAdr(chars: CharSequence, nullTerminated: Boolean = true): Adr = nUTF16(chars, nullTerminated).let { pointerAddress }.toULong() +fun MemoryStack.writeUtf16ToBuffer(chars: CharSequence, nullTerminated: Boolean = true): ByteBuffer = UTF16(chars, nullTerminated) diff --git a/src/mainGen/kotlin/kool/ubuffers/UByteBuffer.kt b/src/mainGen/kotlin/kool/ubuffers/UByteBuffer.kt new file mode 100644 index 0000000..d83f944 --- /dev/null +++ b/src/mainGen/kotlin/kool/ubuffers/UByteBuffer.kt @@ -0,0 +1,782 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:OptIn(kotlin.experimental.ExperimentalTypeInference::class, kotlin.ExperimentalUnsignedTypes::class) +package kool.ubuffers +import kool.ubuffers.UByteBuffer +import kool.isEmpty +import kool.sliceAs +import kool.BYTES +import java.nio.ByteOrder +import kool.lastIndex +import kool.rem +import java.nio.ByteBuffer +import kool.free +import kool.iterator +import kool.cap +import kool.pos +import kool.forEachIndexed +import kool.adr +import kool.Adr + +@JvmInline +value class UByteBuffer(val buffer: ByteBuffer) { + /** + * Relative get method. Reads the ubyte at this buffer's current position, and then increments the position. + * @return The ubyte at the buffer's current position + * @throws `BufferUnderflowException` If the buffer's current position is not smaller than its limit + */ + fun get(): UByte = buffer.get().toUByte() + /** + * Absolute get method. Reads the ubyte at the given index. + * @param index The index from which the ubyte will be read + * @return The ubyte at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit + */ + infix operator fun get(index: Int): UByte = buffer[index].toUByte() + /** + * Relative bulk get method. + * This method transfers ubytes from this buffer into the given destination array. An invocation of this method + * of the form `src.get(a)` behaves in exactly the same way as the invocation + * `src.get(a, 0, a.length)` + * @param dst The destination array + * @return This buffer + * @throws `BufferUnderflowException` If there are fewer than length ubytes remaining in this buffer + */ + infix operator fun get(array: UByteArray): UByteBuffer = UByteBuffer(buffer[array.asByteArray()]) + /** + * Relative bulk get method. + * This method transfers ubytes from this buffer into the given destination array. If there are fewer ubytes + * remaining in the buffer than are required to satisfy the request, that is, if `length > remaining`, then no + * ubytes are transferred and a `BufferUnderflowException` is thrown. + * Otherwise, this method copies length ubytes from this buffer into the given array, starting at the current + * position of this buffer and at the given offset in the array. + * The position of this buffer is then incremented by length. + * In other words, an invocation of this method of the form `src.get(dst, off, len)` has exactly the same + * effect as the loop + * ``` + * for (i in off until off + len) + * dst[i] = src.get() + * ``` + * except that it first checks that there are sufficient ubytes in this buffer and it is potentially much more efficient. + * @param dst The array into which ubytes are to be written + * @param offset The offset within the array of the first ubyte to be written; must be non-negative and no larger than `dst.length` + * @param length The maximum number of ubytes to be written to the given array; must be non-negative and no larger than `dst.length - offset` + * @return This buffer + * @throws `BufferUnderflowException` If there are fewer than length ubytes remaining in this buffer + * @throws `IndexOutOfBoundsException` If the preconditions on the offset and length parameters do not hold + */ + operator fun get(dst: UByteArray, offset: Int, length: Int): UByteBuffer = UByteBuffer(buffer[dst.toByteArray(), offset, length]) + /** + * Absolute get method for reading a char value. + * Reads two bytes at the given index, composing them into a char value according to the current byte order. + * @param index The index from which the bytes will be read + * @return The char value at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + */ + infix fun getChar(index: Int): Char = buffer.getChar(index) + /** + * Relative get method for reading/writing a char value. + * Reads the next two bytes at this buffer's current position, composing them into a char value according to the + * current byte order, and then increments the position by two. + * Returns: The char value at the buffer's current position + * Throws: `BufferUnderflowException` If there are fewer than two bytes remaining in this buffer + * + * Writes two bytes containing the given char value, in the current byte order, into this buffer at the current position, + * and then increments the position by two. + * Parameters: + * - value, The char value to be written + * Returns: This buffer + * Throws: + * `BufferOverflowException` If there are fewer than two bytes remaining in this buffer + * `ReadOnlyBufferException` If this buffer is read-only + */ + var char: Char + get() = buffer.char + set(value) { buffer.putChar(value) } + /** + * Absolute put method for writing a char value (optional operation). + * Writes two bytes containing the given char value, in the current byte order, into this buffer at the given index. + * @param index The index at which the bytes will be written + * @param value The char value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + * @throws `ReadOnlyBufferException` - If this buffer is read-only + */ + fun putChar(index: Int, value: Char): UByteBuffer = buffer.putChar(index, value).asUByteBuffer() + /** + * Absolute get method for reading a short value. + * Reads two bytes at the given index, composing them into a short value according to the current byte order. + * @param index The index from which the bytes will be read + * @return The short value at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + */ + infix fun getShort(index: Int): Short = buffer.getShort(index) + /** + * Absolute get method for reading an ushort value. + * Reads two bytes at the given index, composing them into an ushort value according to the current byte order. + * @param index The index from which the bytes will be read + * @return The ushort value at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + */ + infix fun getUShort(index: Int): UShort = buffer.getShort(index).toUShort() + /** + * Relative get method for reading/writing a short value. + * Reads the next two bytes at this buffer's current position, composing them into a short value according to the + * current byte order, and then increments the position by two. + * Returns: The short value at the buffer's current position + * Throws: `BufferUnderflowException` If there are fewer than two bytes remaining in this buffer + * + * Writes two bytes containing the given short value, in the current byte order, into this buffer at the current position, + * and then increments the position by two. + * Parameters: + * - value, The short value to be written + * Returns: This buffer + * Throws: + * `BufferOverflowException` If there are fewer than two bytes remaining in this buffer + * `ReadOnlyBufferException` If this buffer is read-only + */ + var short: Short + get() = buffer.short + set(value) { buffer.putShort(value) } + /** + * Relative get method for reading an ushort value. + * Reads the next two bytes at this buffer's current position, composing them into an ushort value according to the + * current byte order, and then increments the position by two. + * Returns: The short value at the buffer's current position + * Throws: `BufferUnderflowException` If there are fewer than two bytes remaining in this buffer + * + * Writes two bytes containing the given ushort value, in the current byte order, into this buffer at the current position, + * and then increments the position by two. + * Parameters: + * - value, The ushort value to be written + * Returns: This buffer + * Throws: + * `BufferOverflowException` If there are fewer than two bytes remaining in this buffer + * `ReadOnlyBufferException` If this buffer is read-only + */ + var ushort: UShort + get() = buffer.short.toUShort() + set(value) { buffer.putShort(value.toShort()) } + /** + * Absolute put method for writing a short value (optional operation). + * Writes two bytes containing the given short value, in the current byte order, into this buffer at the given index. + * @param index The index at which the bytes will be written + * @param value The short value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + * @throws `ReadOnlyBufferException` - If this buffer is read-only + */ + fun putShort(index: Int, value: Short): UByteBuffer = buffer.putShort(index, value).asUByteBuffer() + /** + * Absolute put method for writing an ushort value (optional operation). + * Writes two bytes containing the given ushort value, in the current byte order, into this buffer at the given index. + * @param index The index at which the bytes will be written + * @param value The ushort value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + * @throws `ReadOnlyBufferException` - If this buffer is read-only + */ + fun putUShort(index: Int, value: UShort): UByteBuffer = buffer.putShort(index, value.toShort()).asUByteBuffer() + /** + * Absolute get method for reading an int value. + * Reads four bytes at the given index, composing them into an int value according to the current byte order. + * @param index The index from which the bytes will be read + * @return The int value at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + */ + infix fun getInt(index: Int): Int = buffer.getInt(index) + /** + * Absolute get method for reading an uint value. + * Reads four bytes at the given index, composing them into an uint value according to the current byte order. + * @param index The index from which the bytes will be read + * @return The uint value at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + */ + infix fun getUInt(index: Int): UInt = buffer.getInt(index).toUInt() + /** + * Relative get method for reading/writing an int value. + * Reads the next four bytes at this buffer's current position, composing them into an int value according to the + * current byte order, and then increments the position by four. + * Returns: The int value at the buffer's current position + * Throws: `BufferUnderflowException` If there are fewer than four bytes remaining in this buffer + * + * Writes four bytes containing the given int value, in the current byte order, into this buffer at the current position, + * and then increments the position by four. + * Parameters: + * - value, The int value to be written + * Returns: This buffer + * Throws: + * `BufferOverflowException` If there are fewer than four bytes remaining in this buffer + * `ReadOnlyBufferException` If this buffer is read-only + */ + var int: Int + get() = buffer.int + set(value) { buffer.putInt(value) } + /** + * Relative get method for reading an uint value. + * Reads the next four bytes at this buffer's current position, composing them into an uint value according to the + * current byte order, and then increments the position by four. + * Returns: The int value at the buffer's current position + * Throws: `BufferUnderflowException` If there are fewer than four bytes remaining in this buffer + * + * Writes four bytes containing the given uint value, in the current byte order, into this buffer at the current position, + * and then increments the position by four. + * Parameters: + * - value, The uint value to be written + * Returns: This buffer + * Throws: + * `BufferOverflowException` If there are fewer than four bytes remaining in this buffer + * `ReadOnlyBufferException` If this buffer is read-only + */ + var uint: UInt + get() = buffer.int.toUInt() + set(value) { buffer.putInt(value.toInt()) } + /** + * Absolute put method for writing an int value (optional operation). + * Writes four bytes containing the given int value, in the current byte order, into this buffer at the given index. + * @param index The index at which the bytes will be written + * @param value The int value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + * @throws `ReadOnlyBufferException` - If this buffer is read-only + */ + fun putInt(index: Int, value: Int): UByteBuffer = buffer.putInt(index, value).asUByteBuffer() + /** + * Absolute put method for writing an uint value (optional operation). + * Writes four bytes containing the given uint value, in the current byte order, into this buffer at the given index. + * @param index The index at which the bytes will be written + * @param value The uint value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + * @throws `ReadOnlyBufferException` - If this buffer is read-only + */ + fun putUInt(index: Int, value: UInt): UByteBuffer = buffer.putInt(index, value.toInt()).asUByteBuffer() + /** + * Absolute get method for reading a long value. + * Reads eight bytes at the given index, composing them into a long value according to the current byte order. + * @param index The index from which the bytes will be read + * @return The long value at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + */ + infix fun getLong(index: Int): Long = buffer.getLong(index) + /** + * Absolute get method for reading an ulong value. + * Reads eight bytes at the given index, composing them into an ulong value according to the current byte order. + * @param index The index from which the bytes will be read + * @return The ulong value at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + */ + infix fun getULong(index: Int): ULong = buffer.getLong(index).toULong() + /** + * Relative get method for reading/writing a long value. + * Reads the next eight bytes at this buffer's current position, composing them into a long value according to the + * current byte order, and then increments the position by eight. + * Returns: The long value at the buffer's current position + * Throws: `BufferUnderflowException` If there are fewer than eight bytes remaining in this buffer + * + * Writes eight bytes containing the given long value, in the current byte order, into this buffer at the current position, + * and then increments the position by eight. + * Parameters: + * - value, The long value to be written + * Returns: This buffer + * Throws: + * `BufferOverflowException` If there are fewer than eight bytes remaining in this buffer + * `ReadOnlyBufferException` If this buffer is read-only + */ + var long: Long + get() = buffer.long + set(value) { buffer.putLong(value) } + /** + * Relative get method for reading an ulong value. + * Reads the next eight bytes at this buffer's current position, composing them into an ulong value according to the + * current byte order, and then increments the position by eight. + * Returns: The long value at the buffer's current position + * Throws: `BufferUnderflowException` If there are fewer than eight bytes remaining in this buffer + * + * Writes eight bytes containing the given ulong value, in the current byte order, into this buffer at the current position, + * and then increments the position by eight. + * Parameters: + * - value, The ulong value to be written + * Returns: This buffer + * Throws: + * `BufferOverflowException` If there are fewer than eight bytes remaining in this buffer + * `ReadOnlyBufferException` If this buffer is read-only + */ + var ulong: ULong + get() = buffer.long.toULong() + set(value) { buffer.putLong(value.toLong()) } + /** + * Absolute put method for writing a long value (optional operation). + * Writes eight bytes containing the given long value, in the current byte order, into this buffer at the given index. + * @param index The index at which the bytes will be written + * @param value The long value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + * @throws `ReadOnlyBufferException` - If this buffer is read-only + */ + fun putLong(index: Int, value: Long): UByteBuffer = buffer.putLong(index, value).asUByteBuffer() + /** + * Absolute put method for writing an ulong value (optional operation). + * Writes eight bytes containing the given ulong value, in the current byte order, into this buffer at the given index. + * @param index The index at which the bytes will be written + * @param value The ulong value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + * @throws `ReadOnlyBufferException` - If this buffer is read-only + */ + fun putULong(index: Int, value: ULong): UByteBuffer = buffer.putLong(index, value.toLong()).asUByteBuffer() + /** + * Absolute get method for reading a float value. + * Reads four bytes at the given index, composing them into a float value according to the current byte order. + * @param index The index from which the bytes will be read + * @return The float value at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + */ + infix fun getFloat(index: Int): Float = buffer.getFloat(index) + /** + * Relative get method for reading/writing a float value. + * Reads the next four bytes at this buffer's current position, composing them into a float value according to the + * current byte order, and then increments the position by four. + * Returns: The float value at the buffer's current position + * Throws: `BufferUnderflowException` If there are fewer than four bytes remaining in this buffer + * + * Writes four bytes containing the given float value, in the current byte order, into this buffer at the current position, + * and then increments the position by four. + * Parameters: + * - value, The float value to be written + * Returns: This buffer + * Throws: + * `BufferOverflowException` If there are fewer than four bytes remaining in this buffer + * `ReadOnlyBufferException` If this buffer is read-only + */ + var float: Float + get() = buffer.float + set(value) { buffer.putFloat(value) } + /** + * Absolute put method for writing a float value (optional operation). + * Writes four bytes containing the given float value, in the current byte order, into this buffer at the given index. + * @param index The index at which the bytes will be written + * @param value The float value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + * @throws `ReadOnlyBufferException` - If this buffer is read-only + */ + fun putFloat(index: Int, value: Float): UByteBuffer = buffer.putFloat(index, value).asUByteBuffer() + /** + * Absolute get method for reading a double value. + * Reads eight bytes at the given index, composing them into a double value according to the current byte order. + * @param index The index from which the bytes will be read + * @return The double value at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + */ + infix fun getDouble(index: Int): Double = buffer.getDouble(index) + /** + * Relative get method for reading/writing a double value. + * Reads the next eight bytes at this buffer's current position, composing them into a double value according to the + * current byte order, and then increments the position by eight. + * Returns: The double value at the buffer's current position + * Throws: `BufferUnderflowException` If there are fewer than eight bytes remaining in this buffer + * + * Writes eight bytes containing the given double value, in the current byte order, into this buffer at the current position, + * and then increments the position by eight. + * Parameters: + * - value, The double value to be written + * Returns: This buffer + * Throws: + * `BufferOverflowException` If there are fewer than eight bytes remaining in this buffer + * `ReadOnlyBufferException` If this buffer is read-only + */ + var double: Double + get() = buffer.double + set(value) { buffer.putDouble(value) } + /** + * Absolute put method for writing a double value (optional operation). + * Writes eight bytes containing the given double value, in the current byte order, into this buffer at the given index. + * @param index The index at which the bytes will be written + * @param value The double value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit, minus one + * @throws `ReadOnlyBufferException` - If this buffer is read-only + */ + fun putDouble(index: Int, value: Double): UByteBuffer = buffer.putDouble(index, value).asUByteBuffer() + /** + * Compacts this buffer (optional operation). + * The ubytes between the buffer's current position and its limit, if any, are copied to the beginning of the buffer. + * That is, the ubyte at index `p = position` is copied to index zero, the ubyte at index `p + 1` is copied to index + * one, and so forth until the ubyte at index `limit - 1` is copied to index `n = limit - 1 - p`. + * The buffer's position is then set to `n+1` and its limit is set to its capacity. The mark, if defined, is discarded. + * The buffer's position is set to the number of ubytes copied, rather than to zero, so that an invocation of this + * method can be followed immediately by an invocation of another relative put method. + * @return This buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun compact(): UByteBuffer = UByteBuffer(buffer.compact()) + /** + * Creates a new ubyte buffer that shares this buffer's content. + * The content of the new buffer will be that of this buffer. Changes to this buffer's content will be visible in + * the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, + * this buffer is read-only. + * @return The new ubyte buffer + */ + fun duplicate(): UByteBuffer = UByteBuffer(buffer.duplicate()) + /** + * Retrieves this buffer's byte order. + * The byte order of an ubyte buffer created by allocation or by wrapping an existing ubyte array is the native order + * of the underlying hardware. The byte order of an ubyte buffer created as a view of an ubyte buffer is that of the + * ubyte buffer at the moment that the view is created. + * @return This buffer's byte order + */ + val order: ByteOrder + get() = buffer.order() + /** + * Relative put method (optional operation). + * Writes the given ubyte into this buffer at the current position, and then increments the position. + * @param uByte The ubyte to be written + * @return This buffer + * @throws `BufferOverflowException` If this buffer's current position is not smaller than its limit + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(uByte: UByte): UByteBuffer = UByteBuffer(buffer.put(uByte.toByte())) + /** + * Absolute put method (optional operation). + * Writes the given ubyte into this buffer at the given index. + * @param index The index at which the ubyte will be written + * @param uByte The ubyte value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun put(index: Int, uByte: UByte): UByteBuffer = UByteBuffer(buffer.put(index, uByte.toByte())) + /** + * Relative bulk put method (optional operation). + * This method transfers the entire content of the given source ubyte array into this buffer. An invocation of this + * method of the form `dst.put(a)` behaves in exactly the same way as the invocation + * `dst.put(a, 0, a.length)` + * @param src The source array + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(src: UByteArray): UByteBuffer = UByteBuffer(buffer.put(src.toByteArray())) + /** + * Relative bulk put method (optional operation). + * This method transfers the ubytes remaining in the given source buffer into this buffer. If there are more ubytes + * remaining in the source buffer than in this buffer, that is, if `src.remaining > remaining`, then no ubytes are + * transferred and a `BufferOverflowException` is thrown. + * Otherwise, this method copies `n = src.remaining` ubytes from the given buffer into this buffer, starting at each + * buffer's current position. The positions of both buffers are then incremented by `n`. + * In other words, an invocation of this method of the form `dst.put(src)` has exactly the same effect as the loop + * ``` + * while (src.hasRemaining) + * dst.put(src.get()); + * ``` + * except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient. + * @param src The source buffer from which ubytes are to be read; must not be this buffer + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer for the remaining ubytes in the source buffer + * @throws `IllegalArgumentException` If the source buffer is this buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(src: UByteBuffer): UByteBuffer = UByteBuffer(buffer.put(src.buffer)) + /** + * Relative bulk put method (optional operation). + * This method transfers ubytes into this buffer from the given source array. If there are more ubytes to be copied + * from the array than remain in this buffer, that is, if `length > remaining`, then no ubytes are transferred and + * a `BufferOverflowException` is thrown. + * Otherwise, this method copies length ubytes from the given array into this buffer, starting at the given offset in + * the array and at the current position of this buffer. The position of this buffer is then incremented by length. + * In other words, an invocation of this method of the form `dst.put(src, off, len)` has exactly the same effect as + * the loop + * ``` + * for (i in off until off + len) + * dst.put(a[i]) + * `` + * except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient. + * @param src The array from which ubytes are to be read + * @param offset The offset within the array of the first ubyte to be read; must be non-negative and no larger than `array.length` + * @param length The number of ubytes to be read from the given array; must be non-negative and no larger than `array.length - offset` + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer + * @throws `IndexOutOfBoundsException` If the preconditions on the offset and length parameters do not hold + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun put(src: UByteArray, offset: Int, length: Int): UByteBuffer = UByteBuffer(buffer.put(src.toByteArray(), offset, length)) + /** + * Creates a new, read-only ubyte buffer that shares this buffer's content. + * The content of the new buffer will be that of this buffer. Changes to this buffer's content will be visible in + * the new buffer; the new buffer itself, however, will be read-only and will not allow the shared content to be + * modified. The two buffers' position, limit, and mark values will be independent. + * The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer. + * If this buffer is itself read-only then this method behaves in exactly the same way as the duplicate method. + * @return The new, read-only ubyte buffer + */ + fun asReadOnlyBuffer(): UByteBuffer = UByteBuffer(buffer.asReadOnlyBuffer()) + /** + * Creates a new ubyte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content will + * be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of ubytes remaining in this + * buffer, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer is direct, + * and it will be read-only if, and only if, this buffer is read-only. + * @return The new ubyte buffer + */ + fun slice(): UByteBuffer = UByteBuffer(buffer.slice()) + /** + * Tells whether or not this buffer is read-only. + * @return `true` if, and only if, this buffer is read-only + */ + fun isReadOnly(): Boolean = buffer.isReadOnly() + /** + * Tells whether or not this buffer is backed by an accessible byte array. + * If this method returns true then the array and arrayOffset methods may safely be invoked. + * Specified by: + * `hasArray` in class `Buffer` + * @return `true` if, and only if, this buffer is backed by an array and is not read-only + */ + fun hasArray(): Boolean = buffer.hasArray() + /** + * Returns the byte array that backs this buffer (optional operation). + * Modifications to this buffer's content will cause the returned array's content to be modified, and vice versa. + * Invoke the hasArray method before invoking this method in order to ensure that this buffer has an accessible backing array. + * Specified by: + * `array` in class `Buffer` + * @return The array that backs this buffer + * @throws `ReadOnlyBufferException` If this buffer is backed by an array but is read-only + * @throws `UnsupportedOperationException` If this buffer is not backed by an accessible array + */ + fun array(): Any = buffer.array() + /** + * Returns the offset within this buffer's backing array of the first element of the buffer (optional operation). + * If this buffer is backed by an array then buffer position p corresponds to array index p + arrayOffset(). + * Invoke the hasArray method before invoking this method in order to ensure that this buffer has an accessible backing array. + * Specified by: + * `arrayOffset` in class `Buffer` + * @return The offset within this buffer's array of the first element of the buffer + * @throws `ReadOnlyBufferException` If this buffer is backed by an array but is read-only + * @throws `UnsupportedOperationException` If this buffer is not backed by an accessible array + */ + fun arrayOffset(): Int = buffer.arrayOffset() + /** + * Tells whether or not this byte buffer is direct. + * Specified by: + * `isDirect` in class `Buffer` + * @return `true` if, and only if, this buffer is direct + */ + fun isDirect(): Boolean = buffer.isDirect() + /** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ + fun sliceAs(offset: Int, size: Int = lim - offset): UByteBuffer = UByteBuffer(buffer.sliceAs(offset, size)) + /** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ + inline fun free() = buffer.free() + /** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ + inline val adr: Adr + get() = buffer.adr + /** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ + inline var pos: Int + get() = buffer.pos + set(value) { buffer.pos = value } + /** Returns this buffer's capacity. */ + inline val cap: Int + get() = buffer.cap + /** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ + inline val rem: Int + get() = buffer.rem + /** Returns the total size in Bytes between the current position and the limit. */ + inline val remByte: Int + get() = rem * UByte.BYTES + /** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ + inline var lim: Int + get() = buffer.limit() + set(value) { buffer.limit(value) } + /** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param uByte The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ + operator fun set(index: Int, uByte: UByte): UByteBuffer = put(index, uByte) + /** Returns a single list of all elements yielded from results of [transform] function being invoked on each element and its index in the original array. */ + inline fun flatMapIndexed(transform: (index: Int, UByte) -> Iterable): List = flatMapIndexedTo(ArrayList(), transform) + /** Appends all elements yielded from results of [transform] function being invoked on each element and its index in the original array, to the given [destination]. */ + inline fun > flatMapIndexedTo(destination: C, transform: (index: Int, UByte) -> Iterable): C { + var index = 0 + for (element in this) { + val list = transform(index++, element) + destination.addAll(list) + } + return destination + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOf(selector: (UByte) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOf(selector: (UByte) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun > maxOf(selector: (UByte) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (maxValue < v) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ + inline fun maxOfOrNull(selector: (UByte) -> Double): Double? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** Returns the largest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ + inline fun > maxOfOrNull(selector: (UByte) -> R): R? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (maxValue < v) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOfWith(comparator: Comparator, selector: (UByte) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(maxValue, v) < 0) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ + inline fun maxOfWithOrNull(comparator: Comparator, selector: (UByte) -> R): R? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(maxValue, v) < 0) + maxValue = v + } + return maxValue + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UByte) -> Double): Double { + var sum: Double = 0.toDouble() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UByte) -> Int): Int { + var sum: Int = 0.toInt() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UByte) -> Long): Long { + var sum: Long = 0.toLong() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UByte) -> UInt): UInt { + var sum: UInt = 0.toUInt() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UByte) -> ULong): ULong { + var sum: ULong = 0.toULong() + for (element in this) + sum += selector(element) + return sum + } +} +/** + * Creates a view of this byte buffer as a ubyte buffer. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content + * will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be + * independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this + * buffer divided by eight, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer + * is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return A new ubyte buffer + */ +fun ByteBuffer.asUByteBuffer(): UByteBuffer = UByteBuffer(this) diff --git a/src/mainGen/kotlin/kool/ubuffers/UIntBuffer.kt b/src/mainGen/kotlin/kool/ubuffers/UIntBuffer.kt new file mode 100644 index 0000000..9a96900 --- /dev/null +++ b/src/mainGen/kotlin/kool/ubuffers/UIntBuffer.kt @@ -0,0 +1,461 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:OptIn(kotlin.experimental.ExperimentalTypeInference::class, kotlin.ExperimentalUnsignedTypes::class) +package kool.ubuffers +import kool.isEmpty +import java.nio.IntBuffer +import kool.sliceAs +import kool.BYTES +import java.nio.ByteOrder +import kool.lastIndex +import kool.rem +import java.nio.ByteBuffer +import kool.free +import kool.iterator +import kool.cap +import kool.pos +import kool.ubuffers.UIntBuffer +import kool.forEachIndexed +import kool.adr +import kool.Adr + +@JvmInline +value class UIntBuffer(val buffer: IntBuffer) { + /** + * Relative get method. Reads the uint at this buffer's current position, and then increments the position. + * @return The uint at the buffer's current position + * @throws `BufferUnderflowException` If the buffer's current position is not smaller than its limit + */ + fun get(): UInt = buffer.get().toUInt() + /** + * Absolute get method. Reads the uint at the given index. + * @param index The index from which the uint will be read + * @return The uint at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit + */ + infix operator fun get(index: Int): UInt = buffer[index].toUInt() + /** + * Relative bulk get method. + * This method transfers uints from this buffer into the given destination array. An invocation of this method + * of the form `src.get(a)` behaves in exactly the same way as the invocation + * `src.get(a, 0, a.length)` + * @param dst The destination array + * @return This buffer + * @throws `BufferUnderflowException` If there are fewer than length uints remaining in this buffer + */ + infix operator fun get(array: UIntArray): UIntBuffer = UIntBuffer(buffer[array.asIntArray()]) + /** + * Relative bulk get method. + * This method transfers uints from this buffer into the given destination array. If there are fewer uints + * remaining in the buffer than are required to satisfy the request, that is, if `length > remaining`, then no + * uints are transferred and a `BufferUnderflowException` is thrown. + * Otherwise, this method copies length uints from this buffer into the given array, starting at the current + * position of this buffer and at the given offset in the array. + * The position of this buffer is then incremented by length. + * In other words, an invocation of this method of the form `src.get(dst, off, len)` has exactly the same + * effect as the loop + * ``` + * for (i in off until off + len) + * dst[i] = src.get() + * ``` + * except that it first checks that there are sufficient uints in this buffer and it is potentially much more efficient. + * @param dst The array into which uints are to be written + * @param offset The offset within the array of the first uint to be written; must be non-negative and no larger than `dst.length` + * @param length The maximum number of uints to be written to the given array; must be non-negative and no larger than `dst.length - offset` + * @return This buffer + * @throws `BufferUnderflowException` If there are fewer than length uints remaining in this buffer + * @throws `IndexOutOfBoundsException` If the preconditions on the offset and length parameters do not hold + */ + operator fun get(dst: UIntArray, offset: Int, length: Int): UIntBuffer = UIntBuffer(buffer[dst.toIntArray(), offset, length]) + /** + * Compacts this buffer (optional operation). + * The uints between the buffer's current position and its limit, if any, are copied to the beginning of the buffer. + * That is, the uint at index `p = position` is copied to index zero, the uint at index `p + 1` is copied to index + * one, and so forth until the uint at index `limit - 1` is copied to index `n = limit - 1 - p`. + * The buffer's position is then set to `n+1` and its limit is set to its capacity. The mark, if defined, is discarded. + * The buffer's position is set to the number of ubytes copied, rather than to zero, so that an invocation of this + * method can be followed immediately by an invocation of another relative put method. + * @return This buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun compact(): UIntBuffer = UIntBuffer(buffer.compact()) + /** + * Creates a new uint buffer that shares this buffer's content. + * The content of the new buffer will be that of this buffer. Changes to this buffer's content will be visible in + * the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, + * this buffer is read-only. + * @return The new ubyte buffer + */ + fun duplicate(): UIntBuffer = UIntBuffer(buffer.duplicate()) + /** + * Retrieves this buffer's byte order. + * The byte order of an uint buffer created by allocation or by wrapping an existing uint array is the native order + * of the underlying hardware. The byte order of an uint buffer created as a view of an uint buffer is that of the + * uint buffer at the moment that the view is created. + * @return This buffer's byte order + */ + val order: ByteOrder + get() = buffer.order() + /** + * Relative put method (optional operation). + * Writes the given uint into this buffer at the current position, and then increments the position. + * @param uInt The uint to be written + * @return This buffer + * @throws `BufferOverflowException` If this buffer's current position is not smaller than its limit + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(uInt: UInt): UIntBuffer = UIntBuffer(buffer.put(uInt.toInt())) + /** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param uInt The uint value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun put(index: Int, uInt: UInt): UIntBuffer = UIntBuffer(buffer.put(index, uInt.toInt())) + /** + * Relative bulk put method (optional operation). + * This method transfers the entire content of the given source uint array into this buffer. An invocation of this + * method of the form `dst.put(a)` behaves in exactly the same way as the invocation + * `dst.put(a, 0, a.length)` + * @param src The source array + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(src: UIntArray): UIntBuffer = UIntBuffer(buffer.put(src.toIntArray())) + /** + * Relative bulk put method (optional operation). + * This method transfers the uints remaining in the given source buffer into this buffer. If there are more uints + * remaining in the source buffer than in this buffer, that is, if `src.remaining > remaining`, then no uints are + * transferred and a `BufferOverflowException` is thrown. + * Otherwise, this method copies `n = src.remaining` uints from the given buffer into this buffer, starting at each + * buffer's current position. The positions of both buffers are then incremented by `n`. + * In other words, an invocation of this method of the form `dst.put(src)` has exactly the same effect as the loop + * ``` + * while (src.hasRemaining) + * dst.put(src.get()); + * ``` + * except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient. + * @param src The source buffer from which uints are to be read; must not be this buffer + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer for the remaining uints in the source buffer + * @throws `IllegalArgumentException` If the source buffer is this buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(src: UIntBuffer): UIntBuffer = UIntBuffer(buffer.put(src.buffer)) + /** + * Relative bulk put method (optional operation). + * This method transfers uints into this buffer from the given source array. If there are more uints to be copied + * from the array than remain in this buffer, that is, if `length > remaining`, then no uints are transferred and + * a `BufferOverflowException` is thrown. + * Otherwise, this method copies length uints from the given array into this buffer, starting at the given offset in + * the array and at the current position of this buffer. The position of this buffer is then incremented by length. + * In other words, an invocation of this method of the form `dst.put(src, off, len)` has exactly the same effect as + * the loop + * ``` + * for (i in off until off + len) + * dst.put(a[i]) + * `` + * except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient. + * @param src The array from which uints are to be read + * @param offset The offset within the array of the first uint to be read; must be non-negative and no larger than `array.length` + * @param length The number of uints to be read from the given array; must be non-negative and no larger than `array.length - offset` + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer + * @throws `IndexOutOfBoundsException` If the preconditions on the offset and length parameters do not hold + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun put(src: UIntArray, offset: Int, length: Int): UIntBuffer = UIntBuffer(buffer.put(src.toIntArray(), offset, length)) + /** + * Creates a new, read-only uint buffer that shares this buffer's content. + * The content of the new buffer will be that of this buffer. Changes to this buffer's content will be visible in + * the new buffer; the new buffer itself, however, will be read-only and will not allow the shared content to be + * modified. The two buffers' position, limit, and mark values will be independent. + * The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer. + * If this buffer is itself read-only then this method behaves in exactly the same way as the duplicate method. + * @return The new, read-only uint buffer + */ + fun asReadOnlyBuffer(): UIntBuffer = UIntBuffer(buffer.asReadOnlyBuffer()) + /** + * Creates a new uint buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content will + * be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of uints remaining in this + * buffer, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer is direct, + * and it will be read-only if, and only if, this buffer is read-only. + * @return The new uint buffer + */ + fun slice(): UIntBuffer = UIntBuffer(buffer.slice()) + /** + * Tells whether or not this buffer is read-only. + * @return `true` if, and only if, this buffer is read-only + */ + fun isReadOnly(): Boolean = buffer.isReadOnly() + /** + * Tells whether or not this buffer is backed by an accessible byte array. + * If this method returns true then the array and arrayOffset methods may safely be invoked. + * Specified by: + * `hasArray` in class `Buffer` + * @return `true` if, and only if, this buffer is backed by an array and is not read-only + */ + fun hasArray(): Boolean = buffer.hasArray() + /** + * Returns the byte array that backs this buffer (optional operation). + * Modifications to this buffer's content will cause the returned array's content to be modified, and vice versa. + * Invoke the hasArray method before invoking this method in order to ensure that this buffer has an accessible backing array. + * Specified by: + * `array` in class `Buffer` + * @return The array that backs this buffer + * @throws `ReadOnlyBufferException` If this buffer is backed by an array but is read-only + * @throws `UnsupportedOperationException` If this buffer is not backed by an accessible array + */ + fun array(): Any = buffer.array() + /** + * Returns the offset within this buffer's backing array of the first element of the buffer (optional operation). + * If this buffer is backed by an array then buffer position p corresponds to array index p + arrayOffset(). + * Invoke the hasArray method before invoking this method in order to ensure that this buffer has an accessible backing array. + * Specified by: + * `arrayOffset` in class `Buffer` + * @return The offset within this buffer's array of the first element of the buffer + * @throws `ReadOnlyBufferException` If this buffer is backed by an array but is read-only + * @throws `UnsupportedOperationException` If this buffer is not backed by an accessible array + */ + fun arrayOffset(): Int = buffer.arrayOffset() + /** + * Tells whether or not this byte buffer is direct. + * Specified by: + * `isDirect` in class `Buffer` + * @return `true` if, and only if, this buffer is direct + */ + fun isDirect(): Boolean = buffer.isDirect() + /** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ + fun sliceAs(offset: Int, size: Int = lim - offset): UIntBuffer = UIntBuffer(buffer.sliceAs(offset, size)) + /** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ + inline fun free() = buffer.free() + /** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ + inline val adr: Adr + get() = buffer.adr + /** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ + inline var pos: Int + get() = buffer.pos + set(value) { buffer.pos = value } + /** Returns this buffer's capacity. */ + inline val cap: Int + get() = buffer.cap + /** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ + inline val rem: Int + get() = buffer.rem + /** Returns the total size in Bytes between the current position and the limit. */ + inline val remByte: Int + get() = rem * UInt.BYTES + /** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ + inline var lim: Int + get() = buffer.limit() + set(value) { buffer.limit(value) } + /** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param uInt The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ + operator fun set(index: Int, uInt: UInt): UIntBuffer = put(index, uInt) + /** Returns a single list of all elements yielded from results of [transform] function being invoked on each element and its index in the original array. */ + inline fun flatMapIndexed(transform: (index: Int, UInt) -> Iterable): List = flatMapIndexedTo(ArrayList(), transform) + /** Appends all elements yielded from results of [transform] function being invoked on each element and its index in the original array, to the given [destination]. */ + inline fun > flatMapIndexedTo(destination: C, transform: (index: Int, UInt) -> Iterable): C { + var index = 0 + for (element in this) { + val list = transform(index++, element) + destination.addAll(list) + } + return destination + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOf(selector: (UInt) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOf(selector: (UInt) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun > maxOf(selector: (UInt) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (maxValue < v) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ + inline fun maxOfOrNull(selector: (UInt) -> Double): Double? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** Returns the largest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ + inline fun > maxOfOrNull(selector: (UInt) -> R): R? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (maxValue < v) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOfWith(comparator: Comparator, selector: (UInt) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(maxValue, v) < 0) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ + inline fun maxOfWithOrNull(comparator: Comparator, selector: (UInt) -> R): R? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(maxValue, v) < 0) + maxValue = v + } + return maxValue + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UInt) -> Double): Double { + var sum: Double = 0.toDouble() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UInt) -> Int): Int { + var sum: Int = 0.toInt() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UInt) -> Long): Long { + var sum: Long = 0.toLong() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UInt) -> UInt): UInt { + var sum: UInt = 0.toUInt() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UInt) -> ULong): ULong { + var sum: ULong = 0.toULong() + for (element in this) + sum += selector(element) + return sum + } +} +/** + * Creates a view of this byte buffer as a uint buffer. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content + * will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be + * independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this + * buffer divided by eight, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer + * is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return A new uint buffer + */ +fun IntBuffer.asUIntBuffer(): UIntBuffer = UIntBuffer(this) +/** + * Creates a view of this byte buffer as a uint buffer. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content + * will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be + * independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this + * buffer divided by eight, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer + * is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return A new uint buffer + */ +fun ByteBuffer.asUIntBuffer(): UIntBuffer = UIntBuffer(asIntBuffer()) diff --git a/src/mainGen/kotlin/kool/ubuffers/ULongBuffer.kt b/src/mainGen/kotlin/kool/ubuffers/ULongBuffer.kt new file mode 100644 index 0000000..e8091fa --- /dev/null +++ b/src/mainGen/kotlin/kool/ubuffers/ULongBuffer.kt @@ -0,0 +1,461 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:OptIn(kotlin.experimental.ExperimentalTypeInference::class, kotlin.ExperimentalUnsignedTypes::class) +package kool.ubuffers +import java.nio.LongBuffer +import kool.isEmpty +import kool.ubuffers.ULongBuffer +import kool.sliceAs +import kool.BYTES +import java.nio.ByteOrder +import kool.lastIndex +import kool.rem +import java.nio.ByteBuffer +import kool.free +import kool.iterator +import kool.cap +import kool.pos +import kool.forEachIndexed +import kool.adr +import kool.Adr + +@JvmInline +value class ULongBuffer(val buffer: LongBuffer) { + /** + * Relative get method. Reads the ulong at this buffer's current position, and then increments the position. + * @return The ulong at the buffer's current position + * @throws `BufferUnderflowException` If the buffer's current position is not smaller than its limit + */ + fun get(): ULong = buffer.get().toULong() + /** + * Absolute get method. Reads the ulong at the given index. + * @param index The index from which the ulong will be read + * @return The ulong at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit + */ + infix operator fun get(index: Int): ULong = buffer[index].toULong() + /** + * Relative bulk get method. + * This method transfers ulongs from this buffer into the given destination array. An invocation of this method + * of the form `src.get(a)` behaves in exactly the same way as the invocation + * `src.get(a, 0, a.length)` + * @param dst The destination array + * @return This buffer + * @throws `BufferUnderflowException` If there are fewer than length ulongs remaining in this buffer + */ + infix operator fun get(array: ULongArray): ULongBuffer = ULongBuffer(buffer[array.asLongArray()]) + /** + * Relative bulk get method. + * This method transfers ulongs from this buffer into the given destination array. If there are fewer ulongs + * remaining in the buffer than are required to satisfy the request, that is, if `length > remaining`, then no + * ulongs are transferred and a `BufferUnderflowException` is thrown. + * Otherwise, this method copies length ulongs from this buffer into the given array, starting at the current + * position of this buffer and at the given offset in the array. + * The position of this buffer is then incremented by length. + * In other words, an invocation of this method of the form `src.get(dst, off, len)` has exactly the same + * effect as the loop + * ``` + * for (i in off until off + len) + * dst[i] = src.get() + * ``` + * except that it first checks that there are sufficient ulongs in this buffer and it is potentially much more efficient. + * @param dst The array into which ulongs are to be written + * @param offset The offset within the array of the first ulong to be written; must be non-negative and no larger than `dst.length` + * @param length The maximum number of ulongs to be written to the given array; must be non-negative and no larger than `dst.length - offset` + * @return This buffer + * @throws `BufferUnderflowException` If there are fewer than length ulongs remaining in this buffer + * @throws `IndexOutOfBoundsException` If the preconditions on the offset and length parameters do not hold + */ + operator fun get(dst: ULongArray, offset: Int, length: Int): ULongBuffer = ULongBuffer(buffer[dst.toLongArray(), offset, length]) + /** + * Compacts this buffer (optional operation). + * The ulongs between the buffer's current position and its limit, if any, are copied to the beginning of the buffer. + * That is, the ulong at index `p = position` is copied to index zero, the ulong at index `p + 1` is copied to index + * one, and so forth until the ulong at index `limit - 1` is copied to index `n = limit - 1 - p`. + * The buffer's position is then set to `n+1` and its limit is set to its capacity. The mark, if defined, is discarded. + * The buffer's position is set to the number of ubytes copied, rather than to zero, so that an invocation of this + * method can be followed immediately by an invocation of another relative put method. + * @return This buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun compact(): ULongBuffer = ULongBuffer(buffer.compact()) + /** + * Creates a new ulong buffer that shares this buffer's content. + * The content of the new buffer will be that of this buffer. Changes to this buffer's content will be visible in + * the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, + * this buffer is read-only. + * @return The new ubyte buffer + */ + fun duplicate(): ULongBuffer = ULongBuffer(buffer.duplicate()) + /** + * Retrieves this buffer's byte order. + * The byte order of an ulong buffer created by allocation or by wrapping an existing ulong array is the native order + * of the underlying hardware. The byte order of an ulong buffer created as a view of an ulong buffer is that of the + * ulong buffer at the moment that the view is created. + * @return This buffer's byte order + */ + val order: ByteOrder + get() = buffer.order() + /** + * Relative put method (optional operation). + * Writes the given ulong into this buffer at the current position, and then increments the position. + * @param uLong The ulong to be written + * @return This buffer + * @throws `BufferOverflowException` If this buffer's current position is not smaller than its limit + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(uLong: ULong): ULongBuffer = ULongBuffer(buffer.put(uLong.toLong())) + /** + * Absolute put method (optional operation). + * Writes the given ulong into this buffer at the given index. + * @param index The index at which the ulong will be written + * @param uLong The ulong value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun put(index: Int, uLong: ULong): ULongBuffer = ULongBuffer(buffer.put(index, uLong.toLong())) + /** + * Relative bulk put method (optional operation). + * This method transfers the entire content of the given source ulong array into this buffer. An invocation of this + * method of the form `dst.put(a)` behaves in exactly the same way as the invocation + * `dst.put(a, 0, a.length)` + * @param src The source array + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(src: ULongArray): ULongBuffer = ULongBuffer(buffer.put(src.toLongArray())) + /** + * Relative bulk put method (optional operation). + * This method transfers the ulongs remaining in the given source buffer into this buffer. If there are more ulongs + * remaining in the source buffer than in this buffer, that is, if `src.remaining > remaining`, then no ulongs are + * transferred and a `BufferOverflowException` is thrown. + * Otherwise, this method copies `n = src.remaining` ulongs from the given buffer into this buffer, starting at each + * buffer's current position. The positions of both buffers are then incremented by `n`. + * In other words, an invocation of this method of the form `dst.put(src)` has exactly the same effect as the loop + * ``` + * while (src.hasRemaining) + * dst.put(src.get()); + * ``` + * except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient. + * @param src The source buffer from which ulongs are to be read; must not be this buffer + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer for the remaining ulongs in the source buffer + * @throws `IllegalArgumentException` If the source buffer is this buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(src: ULongBuffer): ULongBuffer = ULongBuffer(buffer.put(src.buffer)) + /** + * Relative bulk put method (optional operation). + * This method transfers ulongs into this buffer from the given source array. If there are more ulongs to be copied + * from the array than remain in this buffer, that is, if `length > remaining`, then no ulongs are transferred and + * a `BufferOverflowException` is thrown. + * Otherwise, this method copies length ulongs from the given array into this buffer, starting at the given offset in + * the array and at the current position of this buffer. The position of this buffer is then incremented by length. + * In other words, an invocation of this method of the form `dst.put(src, off, len)` has exactly the same effect as + * the loop + * ``` + * for (i in off until off + len) + * dst.put(a[i]) + * `` + * except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient. + * @param src The array from which ulongs are to be read + * @param offset The offset within the array of the first ulong to be read; must be non-negative and no larger than `array.length` + * @param length The number of ulongs to be read from the given array; must be non-negative and no larger than `array.length - offset` + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer + * @throws `IndexOutOfBoundsException` If the preconditions on the offset and length parameters do not hold + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun put(src: ULongArray, offset: Int, length: Int): ULongBuffer = ULongBuffer(buffer.put(src.toLongArray(), offset, length)) + /** + * Creates a new, read-only ulong buffer that shares this buffer's content. + * The content of the new buffer will be that of this buffer. Changes to this buffer's content will be visible in + * the new buffer; the new buffer itself, however, will be read-only and will not allow the shared content to be + * modified. The two buffers' position, limit, and mark values will be independent. + * The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer. + * If this buffer is itself read-only then this method behaves in exactly the same way as the duplicate method. + * @return The new, read-only ulong buffer + */ + fun asReadOnlyBuffer(): ULongBuffer = ULongBuffer(buffer.asReadOnlyBuffer()) + /** + * Creates a new ulong buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content will + * be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of ulongs remaining in this + * buffer, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer is direct, + * and it will be read-only if, and only if, this buffer is read-only. + * @return The new ulong buffer + */ + fun slice(): ULongBuffer = ULongBuffer(buffer.slice()) + /** + * Tells whether or not this buffer is read-only. + * @return `true` if, and only if, this buffer is read-only + */ + fun isReadOnly(): Boolean = buffer.isReadOnly() + /** + * Tells whether or not this buffer is backed by an accessible byte array. + * If this method returns true then the array and arrayOffset methods may safely be invoked. + * Specified by: + * `hasArray` in class `Buffer` + * @return `true` if, and only if, this buffer is backed by an array and is not read-only + */ + fun hasArray(): Boolean = buffer.hasArray() + /** + * Returns the byte array that backs this buffer (optional operation). + * Modifications to this buffer's content will cause the returned array's content to be modified, and vice versa. + * Invoke the hasArray method before invoking this method in order to ensure that this buffer has an accessible backing array. + * Specified by: + * `array` in class `Buffer` + * @return The array that backs this buffer + * @throws `ReadOnlyBufferException` If this buffer is backed by an array but is read-only + * @throws `UnsupportedOperationException` If this buffer is not backed by an accessible array + */ + fun array(): Any = buffer.array() + /** + * Returns the offset within this buffer's backing array of the first element of the buffer (optional operation). + * If this buffer is backed by an array then buffer position p corresponds to array index p + arrayOffset(). + * Invoke the hasArray method before invoking this method in order to ensure that this buffer has an accessible backing array. + * Specified by: + * `arrayOffset` in class `Buffer` + * @return The offset within this buffer's array of the first element of the buffer + * @throws `ReadOnlyBufferException` If this buffer is backed by an array but is read-only + * @throws `UnsupportedOperationException` If this buffer is not backed by an accessible array + */ + fun arrayOffset(): Int = buffer.arrayOffset() + /** + * Tells whether or not this byte buffer is direct. + * Specified by: + * `isDirect` in class `Buffer` + * @return `true` if, and only if, this buffer is direct + */ + fun isDirect(): Boolean = buffer.isDirect() + /** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ + fun sliceAs(offset: Int, size: Int = lim - offset): ULongBuffer = ULongBuffer(buffer.sliceAs(offset, size)) + /** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ + inline fun free() = buffer.free() + /** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ + inline val adr: Adr + get() = buffer.adr + /** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ + inline var pos: Int + get() = buffer.pos + set(value) { buffer.pos = value } + /** Returns this buffer's capacity. */ + inline val cap: Int + get() = buffer.cap + /** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ + inline val rem: Int + get() = buffer.rem + /** Returns the total size in Bytes between the current position and the limit. */ + inline val remByte: Int + get() = rem * ULong.BYTES + /** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ + inline var lim: Int + get() = buffer.limit() + set(value) { buffer.limit(value) } + /** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param uLong The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ + operator fun set(index: Int, uLong: ULong): ULongBuffer = put(index, uLong) + /** Returns a single list of all elements yielded from results of [transform] function being invoked on each element and its index in the original array. */ + inline fun flatMapIndexed(transform: (index: Int, ULong) -> Iterable): List = flatMapIndexedTo(ArrayList(), transform) + /** Appends all elements yielded from results of [transform] function being invoked on each element and its index in the original array, to the given [destination]. */ + inline fun > flatMapIndexedTo(destination: C, transform: (index: Int, ULong) -> Iterable): C { + var index = 0 + for (element in this) { + val list = transform(index++, element) + destination.addAll(list) + } + return destination + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOf(selector: (ULong) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOf(selector: (ULong) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun > maxOf(selector: (ULong) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (maxValue < v) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ + inline fun maxOfOrNull(selector: (ULong) -> Double): Double? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** Returns the largest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ + inline fun > maxOfOrNull(selector: (ULong) -> R): R? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (maxValue < v) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOfWith(comparator: Comparator, selector: (ULong) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(maxValue, v) < 0) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ + inline fun maxOfWithOrNull(comparator: Comparator, selector: (ULong) -> R): R? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(maxValue, v) < 0) + maxValue = v + } + return maxValue + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (ULong) -> Double): Double { + var sum: Double = 0.toDouble() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (ULong) -> Int): Int { + var sum: Int = 0.toInt() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (ULong) -> Long): Long { + var sum: Long = 0.toLong() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (ULong) -> UInt): UInt { + var sum: UInt = 0.toUInt() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (ULong) -> ULong): ULong { + var sum: ULong = 0.toULong() + for (element in this) + sum += selector(element) + return sum + } +} +/** + * Creates a view of this byte buffer as a ulong buffer. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content + * will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be + * independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this + * buffer divided by eight, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer + * is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return A new ulong buffer + */ +fun LongBuffer.asULongBuffer(): ULongBuffer = ULongBuffer(this) +/** + * Creates a view of this byte buffer as a ulong buffer. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content + * will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be + * independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this + * buffer divided by eight, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer + * is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return A new ulong buffer + */ +fun ByteBuffer.asULongBuffer(): ULongBuffer = ULongBuffer(asLongBuffer()) diff --git a/src/mainGen/kotlin/kool/ubuffers/UShortBuffer.kt b/src/mainGen/kotlin/kool/ubuffers/UShortBuffer.kt new file mode 100644 index 0000000..30c8c58 --- /dev/null +++ b/src/mainGen/kotlin/kool/ubuffers/UShortBuffer.kt @@ -0,0 +1,461 @@ +@file:Suppress("NOTHING_TO_INLINE") +@file:OptIn(kotlin.experimental.ExperimentalTypeInference::class, kotlin.ExperimentalUnsignedTypes::class) +package kool.ubuffers +import kool.isEmpty +import kool.ubuffers.UShortBuffer +import kool.sliceAs +import kool.BYTES +import java.nio.ByteOrder +import kool.lastIndex +import kool.rem +import java.nio.ByteBuffer +import kool.free +import kool.iterator +import java.nio.ShortBuffer +import kool.cap +import kool.pos +import kool.forEachIndexed +import kool.adr +import kool.Adr + +@JvmInline +value class UShortBuffer(val buffer: ShortBuffer) { + /** + * Relative get method. Reads the ushort at this buffer's current position, and then increments the position. + * @return The ushort at the buffer's current position + * @throws `BufferUnderflowException` If the buffer's current position is not smaller than its limit + */ + fun get(): UShort = buffer.get().toUShort() + /** + * Absolute get method. Reads the ushort at the given index. + * @param index The index from which the ushort will be read + * @return The ushort at the given index + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit + */ + infix operator fun get(index: Int): UShort = buffer[index].toUShort() + /** + * Relative bulk get method. + * This method transfers ushorts from this buffer into the given destination array. An invocation of this method + * of the form `src.get(a)` behaves in exactly the same way as the invocation + * `src.get(a, 0, a.length)` + * @param dst The destination array + * @return This buffer + * @throws `BufferUnderflowException` If there are fewer than length ushorts remaining in this buffer + */ + infix operator fun get(array: UShortArray): UShortBuffer = UShortBuffer(buffer[array.asShortArray()]) + /** + * Relative bulk get method. + * This method transfers ushorts from this buffer into the given destination array. If there are fewer ushorts + * remaining in the buffer than are required to satisfy the request, that is, if `length > remaining`, then no + * ushorts are transferred and a `BufferUnderflowException` is thrown. + * Otherwise, this method copies length ushorts from this buffer into the given array, starting at the current + * position of this buffer and at the given offset in the array. + * The position of this buffer is then incremented by length. + * In other words, an invocation of this method of the form `src.get(dst, off, len)` has exactly the same + * effect as the loop + * ``` + * for (i in off until off + len) + * dst[i] = src.get() + * ``` + * except that it first checks that there are sufficient ushorts in this buffer and it is potentially much more efficient. + * @param dst The array into which ushorts are to be written + * @param offset The offset within the array of the first ushort to be written; must be non-negative and no larger than `dst.length` + * @param length The maximum number of ushorts to be written to the given array; must be non-negative and no larger than `dst.length - offset` + * @return This buffer + * @throws `BufferUnderflowException` If there are fewer than length ushorts remaining in this buffer + * @throws `IndexOutOfBoundsException` If the preconditions on the offset and length parameters do not hold + */ + operator fun get(dst: UShortArray, offset: Int, length: Int): UShortBuffer = UShortBuffer(buffer[dst.toShortArray(), offset, length]) + /** + * Compacts this buffer (optional operation). + * The ushorts between the buffer's current position and its limit, if any, are copied to the beginning of the buffer. + * That is, the ushort at index `p = position` is copied to index zero, the ushort at index `p + 1` is copied to index + * one, and so forth until the ushort at index `limit - 1` is copied to index `n = limit - 1 - p`. + * The buffer's position is then set to `n+1` and its limit is set to its capacity. The mark, if defined, is discarded. + * The buffer's position is set to the number of ubytes copied, rather than to zero, so that an invocation of this + * method can be followed immediately by an invocation of another relative put method. + * @return This buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun compact(): UShortBuffer = UShortBuffer(buffer.compact()) + /** + * Creates a new ushort buffer that shares this buffer's content. + * The content of the new buffer will be that of this buffer. Changes to this buffer's content will be visible in + * the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, + * this buffer is read-only. + * @return The new ubyte buffer + */ + fun duplicate(): UShortBuffer = UShortBuffer(buffer.duplicate()) + /** + * Retrieves this buffer's byte order. + * The byte order of an ushort buffer created by allocation or by wrapping an existing ushort array is the native order + * of the underlying hardware. The byte order of an ushort buffer created as a view of an ushort buffer is that of the + * ushort buffer at the moment that the view is created. + * @return This buffer's byte order + */ + val order: ByteOrder + get() = buffer.order() + /** + * Relative put method (optional operation). + * Writes the given ushort into this buffer at the current position, and then increments the position. + * @param uShort The ushort to be written + * @return This buffer + * @throws `BufferOverflowException` If this buffer's current position is not smaller than its limit + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(uShort: UShort): UShortBuffer = UShortBuffer(buffer.put(uShort.toShort())) + /** + * Absolute put method (optional operation). + * Writes the given ushort into this buffer at the given index. + * @param index The index at which the ushort will be written + * @param uShort The ushort value to be written + * @return This buffer + * @throws `IndexOutOfBoundsException` If index is negative or not smaller than the buffer's limit + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun put(index: Int, uShort: UShort): UShortBuffer = UShortBuffer(buffer.put(index, uShort.toShort())) + /** + * Relative bulk put method (optional operation). + * This method transfers the entire content of the given source ushort array into this buffer. An invocation of this + * method of the form `dst.put(a)` behaves in exactly the same way as the invocation + * `dst.put(a, 0, a.length)` + * @param src The source array + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(src: UShortArray): UShortBuffer = UShortBuffer(buffer.put(src.toShortArray())) + /** + * Relative bulk put method (optional operation). + * This method transfers the ushorts remaining in the given source buffer into this buffer. If there are more ushorts + * remaining in the source buffer than in this buffer, that is, if `src.remaining > remaining`, then no ushorts are + * transferred and a `BufferOverflowException` is thrown. + * Otherwise, this method copies `n = src.remaining` ushorts from the given buffer into this buffer, starting at each + * buffer's current position. The positions of both buffers are then incremented by `n`. + * In other words, an invocation of this method of the form `dst.put(src)` has exactly the same effect as the loop + * ``` + * while (src.hasRemaining) + * dst.put(src.get()); + * ``` + * except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient. + * @param src The source buffer from which ushorts are to be read; must not be this buffer + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer for the remaining ushorts in the source buffer + * @throws `IllegalArgumentException` If the source buffer is this buffer + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + infix fun put(src: UShortBuffer): UShortBuffer = UShortBuffer(buffer.put(src.buffer)) + /** + * Relative bulk put method (optional operation). + * This method transfers ushorts into this buffer from the given source array. If there are more ushorts to be copied + * from the array than remain in this buffer, that is, if `length > remaining`, then no ushorts are transferred and + * a `BufferOverflowException` is thrown. + * Otherwise, this method copies length ushorts from the given array into this buffer, starting at the given offset in + * the array and at the current position of this buffer. The position of this buffer is then incremented by length. + * In other words, an invocation of this method of the form `dst.put(src, off, len)` has exactly the same effect as + * the loop + * ``` + * for (i in off until off + len) + * dst.put(a[i]) + * `` + * except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient. + * @param src The array from which ushorts are to be read + * @param offset The offset within the array of the first ushort to be read; must be non-negative and no larger than `array.length` + * @param length The number of ushorts to be read from the given array; must be non-negative and no larger than `array.length - offset` + * @return This buffer + * @throws `BufferOverflowException` If there is insufficient space in this buffer + * @throws `IndexOutOfBoundsException` If the preconditions on the offset and length parameters do not hold + * @throws `ReadOnlyBufferException` If this buffer is read-only + */ + fun put(src: UShortArray, offset: Int, length: Int): UShortBuffer = UShortBuffer(buffer.put(src.toShortArray(), offset, length)) + /** + * Creates a new, read-only ushort buffer that shares this buffer's content. + * The content of the new buffer will be that of this buffer. Changes to this buffer's content will be visible in + * the new buffer; the new buffer itself, however, will be read-only and will not allow the shared content to be + * modified. The two buffers' position, limit, and mark values will be independent. + * The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer. + * If this buffer is itself read-only then this method behaves in exactly the same way as the duplicate method. + * @return The new, read-only ushort buffer + */ + fun asReadOnlyBuffer(): UShortBuffer = UShortBuffer(buffer.asReadOnlyBuffer()) + /** + * Creates a new ushort buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content will + * be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of ushorts remaining in this + * buffer, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer is direct, + * and it will be read-only if, and only if, this buffer is read-only. + * @return The new ushort buffer + */ + fun slice(): UShortBuffer = UShortBuffer(buffer.slice()) + /** + * Tells whether or not this buffer is read-only. + * @return `true` if, and only if, this buffer is read-only + */ + fun isReadOnly(): Boolean = buffer.isReadOnly() + /** + * Tells whether or not this buffer is backed by an accessible byte array. + * If this method returns true then the array and arrayOffset methods may safely be invoked. + * Specified by: + * `hasArray` in class `Buffer` + * @return `true` if, and only if, this buffer is backed by an array and is not read-only + */ + fun hasArray(): Boolean = buffer.hasArray() + /** + * Returns the byte array that backs this buffer (optional operation). + * Modifications to this buffer's content will cause the returned array's content to be modified, and vice versa. + * Invoke the hasArray method before invoking this method in order to ensure that this buffer has an accessible backing array. + * Specified by: + * `array` in class `Buffer` + * @return The array that backs this buffer + * @throws `ReadOnlyBufferException` If this buffer is backed by an array but is read-only + * @throws `UnsupportedOperationException` If this buffer is not backed by an accessible array + */ + fun array(): Any = buffer.array() + /** + * Returns the offset within this buffer's backing array of the first element of the buffer (optional operation). + * If this buffer is backed by an array then buffer position p corresponds to array index p + arrayOffset(). + * Invoke the hasArray method before invoking this method in order to ensure that this buffer has an accessible backing array. + * Specified by: + * `arrayOffset` in class `Buffer` + * @return The offset within this buffer's array of the first element of the buffer + * @throws `ReadOnlyBufferException` If this buffer is backed by an array but is read-only + * @throws `UnsupportedOperationException` If this buffer is not backed by an accessible array + */ + fun arrayOffset(): Int = buffer.arrayOffset() + /** + * Tells whether or not this byte buffer is direct. + * Specified by: + * `isDirect` in class `Buffer` + * @return `true` if, and only if, this buffer is direct + */ + fun isDirect(): Boolean = buffer.isDirect() + /** + * Creates a new byte buffer whose content is a shared subsequence of this buffer's content. + * The content of the new buffer will start at [offset]. Changes to this buffer's content will be visible in the + * new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. + * The new buffer's position will be zero, its capacity and its limit will be [size], and its mark will be undefined. + * The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return The new byte buffer + */ + fun sliceAs(offset: Int, size: Int = lim - offset): UShortBuffer = UShortBuffer(buffer.sliceAs(offset, size)) + /** + * The standard C free function. + * A block of memory previously allocated by a call to `memAlloc`, `memCalloc` or `memRealloc` is deallocated, making it available again for further allocations. + */ + inline fun free() = buffer.free() + /** + * Returns the memory address at the current position of the buffer. This is effectively a pointer value that can be used in native function calls. + * @return the memory address + */ + inline val adr: Adr + get() = buffer.adr + /** + * This buffer's position. + * When assigning it, if the mark is defined and larger than the new position then it is discarded. + */ + inline var pos: Int + get() = buffer.pos + set(value) { buffer.pos = value } + /** Returns this buffer's capacity. */ + inline val cap: Int + get() = buffer.cap + /** + * Returns the number of elements between the current position and the limit. + * @return The number of elements remaining in this buffer + */ + inline val rem: Int + get() = buffer.rem + /** Returns the total size in Bytes between the current position and the limit. */ + inline val remByte: Int + get() = rem * UShort.BYTES + /** + * This buffer's limit. + * When assigning it, if the position is larger than the new limit then it is set to the new limit. + * If the mark is defined and larger than the new limit then it is discarded. + */ + inline var lim: Int + get() = buffer.limit() + set(value) { buffer.limit(value) } + /** + * Absolute put method (optional operation). + * Writes the given uint into this buffer at the given index. + * @param index The index at which the uint will be written + * @param uShort The uint value to be written + * @return This buffer + * @throws IndexOutOfBoundsException If index is negative or not smaller than the buffer's limit + * @throws ReadOnlyBufferException If this buffer is read-only + */ + operator fun set(index: Int, uShort: UShort): UShortBuffer = put(index, uShort) + /** Returns a single list of all elements yielded from results of [transform] function being invoked on each element and its index in the original array. */ + inline fun flatMapIndexed(transform: (index: Int, UShort) -> Iterable): List = flatMapIndexedTo(ArrayList(), transform) + /** Appends all elements yielded from results of [transform] function being invoked on each element and its index in the original array, to the given [destination]. */ + inline fun > flatMapIndexedTo(destination: C, transform: (index: Int, UShort) -> Iterable): C { + var index = 0 + for (element in this) { + val list = transform(index++, element) + destination.addAll(list) + } + return destination + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOf(selector: (UShort) -> Double): Double { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOf(selector: (UShort) -> Float): Float { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun > maxOf(selector: (UShort) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (maxValue < v) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. + * + * If any of values produced by [selector] function is `NaN`, the returned result is `NaN`. + */ + inline fun maxOfOrNull(selector: (UShort) -> Double): Double? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + maxValue = maxOf(maxValue, v) + } + return maxValue + } + /** Returns the largest value among all values produced by [selector] function applied to each element in the array or `null` if there are no elements. */ + inline fun > maxOfOrNull(selector: (UShort) -> R): R? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (maxValue < v) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value according to the provided [comparator] among all values produced by [selector] function applied to each element in the array. + * + * @throws NoSuchElementException if the array is empty. + */ + inline fun maxOfWith(comparator: Comparator, selector: (UShort) -> R): R { + if (isEmpty()) throw NoSuchElementException() + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(maxValue, v) < 0) + maxValue = v + } + return maxValue + } + /** + * Returns the largest value according to the provided [comparator] among all values produced by [selector] + * function applied to each element in the array or `null` if there are no elements. + */ + inline fun maxOfWithOrNull(comparator: Comparator, selector: (UShort) -> R): R? { + if (isEmpty()) return null + var maxValue = selector(this[0]) + for (i in 1..lastIndex) { + val v = selector(this[i]) + if (comparator.compare(maxValue, v) < 0) + maxValue = v + } + return maxValue + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UShort) -> Double): Double { + var sum: Double = 0.toDouble() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UShort) -> Int): Int { + var sum: Int = 0.toInt() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UShort) -> Long): Long { + var sum: Long = 0.toLong() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UShort) -> UInt): UInt { + var sum: UInt = 0.toUInt() + for (element in this) + sum += selector(element) + return sum + } + /** Returns the sum of all values produced by [selector] function applied to each element in the array. */ + inline fun sumOf(selector: (UShort) -> ULong): ULong { + var sum: ULong = 0.toULong() + for (element in this) + sum += selector(element) + return sum + } +} +/** + * Creates a view of this byte buffer as a ushort buffer. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content + * will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be + * independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this + * buffer divided by eight, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer + * is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return A new ushort buffer + */ +fun ShortBuffer.asUShortBuffer(): UShortBuffer = UShortBuffer(this) +/** + * Creates a view of this byte buffer as a ushort buffer. + * The content of the new buffer will start at this buffer's current position. Changes to this buffer's content + * will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be + * independent. + * The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this + * buffer divided by eight, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer + * is direct, and it will be read-only if, and only if, this buffer is read-only. + * @return A new ushort buffer + */ +fun ByteBuffer.asUShortBuffer(): UShortBuffer = UShortBuffer(asShortBuffer()) diff --git a/src/mainGen/kotlin/kool/unsafe.kt b/src/mainGen/kotlin/kool/unsafe.kt new file mode 100644 index 0000000..2c6a373 --- /dev/null +++ b/src/mainGen/kotlin/kool/unsafe.kt @@ -0,0 +1,108 @@ +@file:Suppress("NOTHING_TO_INLINE") +package kool +import sun.misc.Unsafe + +/** + * Different runtimes use different names for the Unsafe singleton, so we cannot use `.getDeclaredField` and + * we scan instead. For example: + * Oracle: theUnsafe + * PERC : m_unsafe_instance + * Android: THE_ONE + */ +val unsafe: Unsafe by lazy { + Unsafe::class.java.declaredFields + .find { + it.type == Unsafe::class.java && + java.lang.reflect.Modifier.isStatic(it.modifiers) + && java.lang.reflect.Modifier.isFinal(it.modifiers) + }?.run { + isAccessible = true + get(null) as Unsafe + } ?: throw UnsupportedOperationException("Kool requires sun.misc.Unsafe to be available.") +} +inline operator fun Unsafe.get(offset: ULong): Byte = getByte(offset.toLong()) +inline operator fun Unsafe.get(offset: Long): Byte = getByte(offset) +inline operator fun Unsafe.get(offset: ULong): T = get(offset.toLong()) +inline operator fun Unsafe.get(offset: Long): T = when (T::class.java) { + Byte::class.java -> getByte(offset) + Short::class.java -> getShort(offset) + Int::class.java -> getInt(offset) + Long::class.java -> getLong(offset) + UByte::class.java -> getUByte(offset) + UShort::class.java -> getUShort(offset) + UInt::class.java -> getUInt(offset) + ULong::class.java -> getULong(offset) + Float::class.java -> getFloat(offset) + Double::class.java -> getDouble(offset) + else -> error("type ${T::class} unsupported") +} as T +inline fun Unsafe.getChar(offset: Int): Char = getChar(offset.toULong()) +inline fun Unsafe.getChar(offset: UInt): Char = getChar(offset.toULong()) +inline fun Unsafe.getChar(offset: ULong): Char = getChar(offset.toLong()) +inline fun Unsafe.set(offset: Int, char: Char) = set(offset.toULong(), char) +inline fun Unsafe.set(offset: UInt, char: Char) = set(offset.toULong(), char) +inline fun Unsafe.set(offset: ULong, char: Char) = putChar(null, offset.toLong(), char) +inline fun Unsafe.getByte(offset: Int): Byte = getByte(offset.toULong()) +inline fun Unsafe.getByte(offset: UInt): Byte = getByte(offset.toULong()) +inline fun Unsafe.getByte(offset: ULong): Byte = getByte(offset.toLong()) +inline fun Unsafe.set(offset: Int, byte: Byte) = set(offset.toULong(), byte) +inline fun Unsafe.set(offset: UInt, byte: Byte) = set(offset.toULong(), byte) +inline fun Unsafe.set(offset: ULong, byte: Byte) = putByte(null, offset.toLong(), byte) +inline fun Unsafe.getShort(offset: Int): Short = getShort(offset.toULong()) +inline fun Unsafe.getShort(offset: UInt): Short = getShort(offset.toULong()) +inline fun Unsafe.getShort(offset: ULong): Short = getShort(offset.toLong()) +inline fun Unsafe.set(offset: Int, short: Short) = set(offset.toULong(), short) +inline fun Unsafe.set(offset: UInt, short: Short) = set(offset.toULong(), short) +inline fun Unsafe.set(offset: ULong, short: Short) = putShort(null, offset.toLong(), short) +inline fun Unsafe.getInt(offset: Int): Int = getInt(offset.toULong()) +inline fun Unsafe.getInt(offset: UInt): Int = getInt(offset.toULong()) +inline fun Unsafe.getInt(offset: ULong): Int = getInt(offset.toLong()) +inline fun Unsafe.set(offset: Int, int: Int) = set(offset.toULong(), int) +inline fun Unsafe.set(offset: UInt, int: Int) = set(offset.toULong(), int) +inline fun Unsafe.set(offset: ULong, int: Int) = putInt(null, offset.toLong(), int) +inline fun Unsafe.getLong(offset: Int): Long = getLong(offset.toULong()) +inline fun Unsafe.getLong(offset: UInt): Long = getLong(offset.toULong()) +inline fun Unsafe.getLong(offset: ULong): Long = getLong(offset.toLong()) +inline fun Unsafe.set(offset: Int, long: Long) = set(offset.toULong(), long) +inline fun Unsafe.set(offset: UInt, long: Long) = set(offset.toULong(), long) +inline fun Unsafe.set(offset: ULong, long: Long) = putLong(null, offset.toLong(), long) +inline fun Unsafe.getUByte(offset: Int): UByte = getUByte(offset.toULong()) +inline fun Unsafe.getUByte(offset: UInt): UByte = getUByte(offset.toULong()) +inline fun Unsafe.getUByte(offset: Long): UByte = getUByte(offset.toULong()) +inline fun Unsafe.getUByte(offset: ULong): UByte = getByte(offset.toLong()).toUByte() +inline fun Unsafe.set(offset: Int, ubyte: UByte) = set(offset.toULong(), ubyte) +inline fun Unsafe.set(offset: Long, ubyte: UByte) = set(offset.toULong(), ubyte) +inline fun Unsafe.set(offset: ULong, ubyte: UByte) = putByte(null, offset.toLong(), ubyte.toByte()) +inline fun Unsafe.getUShort(offset: Int): UShort = getUShort(offset.toULong()) +inline fun Unsafe.getUShort(offset: UInt): UShort = getUShort(offset.toULong()) +inline fun Unsafe.getUShort(offset: Long): UShort = getUShort(offset.toULong()) +inline fun Unsafe.getUShort(offset: ULong): UShort = getShort(offset.toLong()).toUShort() +inline fun Unsafe.set(offset: Int, ushort: UShort) = set(offset.toULong(), ushort) +inline fun Unsafe.set(offset: Long, ushort: UShort) = set(offset.toULong(), ushort) +inline fun Unsafe.set(offset: ULong, ushort: UShort) = putShort(null, offset.toLong(), ushort.toShort()) +inline fun Unsafe.getUInt(offset: Int): UInt = getUInt(offset.toULong()) +inline fun Unsafe.getUInt(offset: UInt): UInt = getUInt(offset.toULong()) +inline fun Unsafe.getUInt(offset: Long): UInt = getUInt(offset.toULong()) +inline fun Unsafe.getUInt(offset: ULong): UInt = getInt(offset.toLong()).toUInt() +inline fun Unsafe.set(offset: Int, uint: UInt) = set(offset.toULong(), uint) +inline fun Unsafe.set(offset: Long, uint: UInt) = set(offset.toULong(), uint) +inline fun Unsafe.set(offset: ULong, uint: UInt) = putInt(null, offset.toLong(), uint.toInt()) +inline fun Unsafe.getULong(offset: Int): ULong = getULong(offset.toULong()) +inline fun Unsafe.getULong(offset: UInt): ULong = getULong(offset.toULong()) +inline fun Unsafe.getULong(offset: Long): ULong = getULong(offset.toULong()) +inline fun Unsafe.getULong(offset: ULong): ULong = getLong(offset.toLong()).toULong() +inline fun Unsafe.set(offset: Int, ulong: ULong) = set(offset.toULong(), ulong) +inline fun Unsafe.set(offset: Long, ulong: ULong) = set(offset.toULong(), ulong) +inline fun Unsafe.set(offset: ULong, ulong: ULong) = putLong(null, offset.toLong(), ulong.toLong()) +inline fun Unsafe.getFloat(offset: Int): Float = getFloat(offset.toULong()) +inline fun Unsafe.getFloat(offset: UInt): Float = getFloat(offset.toULong()) +inline fun Unsafe.getFloat(offset: ULong): Float = getFloat(offset.toLong()) +inline fun Unsafe.set(offset: Int, float: Float) = set(offset.toULong(), float) +inline fun Unsafe.set(offset: UInt, float: Float) = set(offset.toULong(), float) +inline fun Unsafe.set(offset: ULong, float: Float) = putFloat(null, offset.toLong(), float) +inline fun Unsafe.getDouble(offset: Int): Double = getDouble(offset.toULong()) +inline fun Unsafe.getDouble(offset: UInt): Double = getDouble(offset.toULong()) +inline fun Unsafe.getDouble(offset: ULong): Double = getDouble(offset.toLong()) +inline fun Unsafe.set(offset: Int, double: Double) = set(offset.toULong(), double) +inline fun Unsafe.set(offset: UInt, double: Double) = set(offset.toULong(), double) +inline fun Unsafe.set(offset: ULong, double: Double) = putDouble(null, offset.toLong(), double)