-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from XYOracleNetwork/develop
Develop
- Loading branch information
Showing
6 changed files
with
216 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
217 changes: 138 additions & 79 deletions
217
src/main/java/network/xyo/sdkobjectmodelkotlin/objects/sets/XyoObjectIterator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,145 +1,204 @@ | ||
package network.xyo.sdkobjectmodelkotlin.objects.sets | ||
|
||
import network.xyo.sdkobjectmodelkotlin.exceptions.XyoObjectExceotion | ||
import network.xyo.sdkobjectmodelkotlin.exceptions.XyoObjectIteratorException | ||
import network.xyo.sdkobjectmodelkotlin.schema.XyoObjectSchema | ||
import java.lang.StringBuilder | ||
import java.nio.ByteBuffer | ||
import kotlin.experimental.and | ||
|
||
/** | ||
* An Iterator for iterating over sets created with XyoObjectSetCreator. | ||
*/ | ||
open class XyoObjectIterator (private val item : ByteArray) : Iterator<ByteArray> { | ||
|
||
class XyoIterableObject (private val item : ByteArray) { | ||
private val startingOffset = readOwnHeader() | ||
private var globalSchema : XyoObjectSchema? = null | ||
private var currentOffset = 0 | ||
private var biggestOffset = startingOffset | ||
private val offsets = ArrayList<Int>() | ||
|
||
/** | ||
* Checks if there is another item in the set. | ||
*/ | ||
override fun hasNext(): Boolean { | ||
return item.size > currentOffset | ||
} | ||
val iterator : XyoObjectIterator | ||
get() = XyoObjectIterator(startingOffset) | ||
|
||
/** | ||
* Gets the next item in the set. | ||
*/ | ||
override fun next(): ByteArray { | ||
val size : Int | ||
get() { | ||
if (biggestOffset == item.size) { | ||
return offsets.size | ||
} | ||
|
||
val startingIndex = currentOffset | ||
val schemaOfItem = globalSchema ?: getNextHeader() | ||
val sizeOfObject = readSizeOfObject(schemaOfItem.sizeIdentifier) | ||
checkBounds(sizeOfObject - schemaOfItem.sizeIdentifier) | ||
val sizeIt = XyoObjectIterator(biggestOffset) | ||
while (sizeIt.hasNext()) {sizeIt.next()} | ||
return offsets.size | ||
} | ||
|
||
private fun readItemAtOffset (startingOffset : Int) : ByteArray { | ||
if (globalSchema == null) { | ||
currentOffset = startingIndex + sizeOfObject + 2 | ||
return item.copyOfRange(startingIndex, startingIndex + sizeOfObject + 2) | ||
return readItemUntyped(startingOffset) | ||
} | ||
return readItemTyped(startingOffset) | ||
} | ||
|
||
private fun readItemUntyped (startingOffset: Int) : ByteArray { | ||
val schemaOfItem = getNextHeader(startingOffset) | ||
val sizeOfObject = readSizeOfObject(schemaOfItem.sizeIdentifier, startingOffset + 2) | ||
|
||
if (sizeOfObject == 0) { | ||
throw XyoObjectIteratorException("Size can not be 0. Value: ${item.toHexString()}") | ||
} | ||
|
||
if (biggestOffset <= startingOffset) { | ||
offsets.add(startingOffset) | ||
} | ||
|
||
biggestOffset = startingOffset + sizeOfObject + 2 | ||
checkIndex(startingOffset + sizeOfObject + 2) | ||
return item.copyOfRange(startingOffset, startingOffset + sizeOfObject + 2) | ||
} | ||
|
||
private fun readItemTyped (startingOffset: Int) : ByteArray { | ||
val schemaOfItem = globalSchema ?: throw XyoObjectIteratorException("Global schema is null!") | ||
val sizeOfObject = readSizeOfObject(schemaOfItem.sizeIdentifier, startingOffset) | ||
|
||
if (sizeOfObject == 0) { | ||
throw XyoObjectIteratorException("Size can not be 0. Value: ${item.toHexString()}") | ||
} | ||
|
||
if (biggestOffset <= startingOffset) { | ||
offsets.add(startingOffset) | ||
} | ||
|
||
val buffer = ByteBuffer.allocate(sizeOfObject + 2) | ||
checkIndex(startingOffset + sizeOfObject) | ||
buffer.put(schemaOfItem.header) | ||
buffer.put(item.copyOfRange(startingIndex, startingIndex + sizeOfObject)) | ||
currentOffset = startingIndex + sizeOfObject | ||
buffer.put(item.copyOfRange(startingOffset, startingOffset + sizeOfObject)) | ||
|
||
biggestOffset = startingOffset + sizeOfObject | ||
return buffer.array() | ||
} | ||
|
||
private fun checkBounds (size : Int) { | ||
if (size + currentOffset > item.size) { | ||
throw XyoObjectIteratorException("Out of size. Length: ${item.size}, To Read: ${size + currentOffset}") | ||
operator fun get(index: Int): ByteArray { | ||
if (index < offsets.size) { | ||
return readItemAtOffset(offsets[index]) | ||
} | ||
|
||
val it = XyoObjectIterator(biggestOffset) | ||
var i = offsets.size | ||
|
||
while (it.hasNext()) { | ||
val item = it.next() | ||
|
||
if (i == index) { | ||
return item | ||
} | ||
|
||
i++ | ||
} | ||
|
||
throw XyoObjectIteratorException("Index out of range! Size $i, Index: $index. Value: ${item.toHexString()}") | ||
} | ||
|
||
private fun ByteArray.toHexString(): String { | ||
val builder = StringBuilder() | ||
val it = this.iterator() | ||
builder.append("0x") | ||
while (it.hasNext()) { | ||
builder.append(String.format("%02X", it.next())) | ||
} | ||
|
||
return builder.toString() | ||
} | ||
|
||
operator fun get(type: Byte): Array<ByteArray> { | ||
val it = XyoObjectIterator(startingOffset) | ||
val itemsThatFollowTheType = ArrayList<ByteArray>() | ||
|
||
while (it.hasNext()) { | ||
val next = it.next() | ||
val nextHeader = XyoObjectSchema.createFromHeader(next.copyOfRange(0, 2)) | ||
|
||
if (nextHeader.id == type) { | ||
itemsThatFollowTheType.add(next) | ||
} | ||
} | ||
|
||
return itemsThatFollowTheType.toTypedArray() | ||
} | ||
|
||
/** | ||
* Reads the size of the object at the current offset. | ||
*/ | ||
private fun readSizeOfObject (sizeToReadForSize : Int) : Int { | ||
private fun readSizeOfObject (sizeToReadForSize : Int, offset: Int) : Int { | ||
val buffer = ByteBuffer.allocate(sizeToReadForSize) | ||
checkBounds(sizeToReadForSize) | ||
currentOffset += sizeToReadForSize | ||
buffer.put(item.copyOfRange(currentOffset - sizeToReadForSize, currentOffset)) | ||
checkIndex(offset + sizeToReadForSize) | ||
buffer.put(item.copyOfRange(offset, offset + sizeToReadForSize)) | ||
|
||
when (sizeToReadForSize) { | ||
1 -> return (buffer[0] and 0xFF.toByte()).toInt() | ||
1 -> return (buffer[0].toInt() and 0xFF) | ||
2 -> return (buffer.getShort(0).toInt() and 0xFFFF) | ||
4 -> return buffer.getInt(0) | ||
} | ||
|
||
throw Exception("Stub for long size") | ||
throw Exception("Stub for long size. Value: ${item.toHexString()}") | ||
} | ||
|
||
/** | ||
* Gets the next object schema at the current offset. | ||
*/ | ||
private fun getNextHeader () : XyoObjectSchema { | ||
checkBounds(2) | ||
currentOffset += 2 | ||
return XyoObjectSchema.createFromHeader(item.copyOfRange(currentOffset - 2, currentOffset)) | ||
private fun getNextHeader (offset : Int) : XyoObjectSchema { | ||
return XyoObjectSchema.createFromHeader(item.copyOfRange(offset, offset + 2)) | ||
} | ||
|
||
operator fun get(index: Int): ByteArray { | ||
var i = 0 | ||
|
||
while (index != i) { | ||
next() | ||
i++ | ||
private fun checkIndex (index: Int) { | ||
if (index > item.size) { | ||
throw XyoObjectIteratorException("Out of size. Value: ${item.toHexString()}") | ||
} | ||
|
||
val next = next() | ||
currentOffset = 0 | ||
readOwnHeader() | ||
return next | ||
} | ||
|
||
operator fun get(type: Byte): Array<ByteArray> { | ||
val itemsThatFollowTheType = ArrayList<ByteArray>() | ||
inner class XyoObjectIterator (private var currentOffset: Int) : Iterator<ByteArray> { | ||
|
||
while (hasNext()) { | ||
val next = next() | ||
val nextHeader = XyoObjectSchema.createFromHeader(next.copyOfRange(0, 2)) | ||
|
||
if (nextHeader.id == type) { | ||
itemsThatFollowTheType.add(next) | ||
} | ||
/** | ||
* Checks if there is another item in the set. | ||
*/ | ||
override fun hasNext(): Boolean { | ||
return item.size > currentOffset | ||
} | ||
|
||
reset() | ||
return itemsThatFollowTheType.toTypedArray() | ||
} | ||
|
||
val size : Int | ||
get() { | ||
var i = 0 | ||
/** | ||
* Gets the next item in the set. | ||
*/ | ||
override fun next(): ByteArray { | ||
val nextItem = readItemAtOffset(currentOffset) | ||
|
||
while (hasNext()) { | ||
next() | ||
i++ | ||
if (globalSchema == null) { | ||
currentOffset += nextItem.size | ||
} else { | ||
currentOffset += nextItem.size - 2 | ||
} | ||
|
||
reset() | ||
return i | ||
return nextItem | ||
} | ||
|
||
private fun reset() { | ||
currentOffset = 0 | ||
readOwnHeader() | ||
} | ||
|
||
private fun readOwnHeader () { | ||
val setHeader = getNextHeader() | ||
val totalSize = readSizeOfObject(setHeader.sizeIdentifier) | ||
private fun readOwnHeader () : Int { | ||
val setHeader = getNextHeader(0) | ||
val totalSize = readSizeOfObject(setHeader.sizeIdentifier, 2) | ||
|
||
if ((totalSize + 2) != item.size) { | ||
throw XyoObjectIteratorException("Array size does not equal header size.") | ||
throw XyoObjectIteratorException("Array size does not equal header size. Header size: " + | ||
"$totalSize, Expected: ${item.size - 2}. Value: ${item.toHexString()}") | ||
} | ||
|
||
if (!setHeader.isIterable) { | ||
throw XyoObjectIteratorException("Can not iterate on object that is not iterable.") | ||
throw XyoObjectIteratorException("Can not iterate on object that is not iterable. Header " + | ||
"${setHeader.header[0]}, ${setHeader.header[1]}. Value: ${item.toHexString()}") | ||
} | ||
|
||
if (setHeader.isTyped) { | ||
globalSchema = getNextHeader() | ||
if (setHeader.isTyped && totalSize != setHeader.sizeIdentifier) { | ||
globalSchema = getNextHeader(setHeader.sizeIdentifier + 2) | ||
return 4 + setHeader.sizeIdentifier | ||
} | ||
} | ||
|
||
init { | ||
readOwnHeader() | ||
return 2 + setHeader.sizeIdentifier | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.