Skip to content

Commit

Permalink
Merge pull request #5 from XYOracleNetwork/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
carterharrison authored Nov 30, 2018
2 parents 64e4490 + 46e99f9 commit 71e9f9b
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 90 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package network.xyo.sdkobjectmodelkotlin.objects

import network.xyo.sdkobjectmodelkotlin.objects.sets.XyoObjectIterator
import network.xyo.sdkobjectmodelkotlin.objects.sets.XyoIterableObject
import network.xyo.sdkobjectmodelkotlin.schema.XyoObjectSchema
import org.json.JSONArray
import org.json.JSONObject
Expand Down Expand Up @@ -54,7 +54,7 @@ object XyoObjectCreator {
val rootJsonObject = JSONArray()

if (itemHeader.isIterable) {
for (subItem in XyoObjectIterator(item)) {
for (subItem in XyoIterableObject(item).iterator) {
rootJsonObject.put(itemToJSON(subItem))
}
} else {
Expand All @@ -64,6 +64,47 @@ object XyoObjectCreator {
return rootJsonObject
}

fun itemToByteString(item : ByteArray) : String {
return itemToByteString(item, 0, true)
}

fun itemToByteString (item : ByteArray, depth: Int, hasHeader: Boolean) : String {
val itemHeader = XyoObjectSchema.createFromHeader(item.copyOfRange(0, 2))
val itemSize = item.copyOfRange(2, 2 + itemHeader.sizeIdentifier)
val itemValue = XyoObjectCreator.getObjectValue(item)

val rootString = StringBuilder()

if (hasHeader) {
rootString.append(appendDepthToStringBuilder(depth, itemHeader.header.toHexString()))
}

rootString.append(appendDepthToStringBuilder(depth, itemSize.toHexString()))


if (itemHeader.isIterable) {
for (subItem in XyoIterableObject(item).iterator) {
rootString.append(itemToByteString(subItem, depth+1, !itemHeader.isTyped))
}
} else {
rootString.append(appendDepthToStringBuilder(depth, itemValue.toHexString()))
}

return rootString.toString()
}

private fun appendDepthToStringBuilder (depth : Int, value : String) : String {
val builder = StringBuffer()

for (i in 1..depth) {
builder.append("| ")
}

builder.append(value + "\n")

return builder.toString()
}

private fun ByteArray.toHexString(): String {
val builder = StringBuilder()
val it = this.iterator()
Expand Down
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
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ object XyoObjectSetCreator {
return XyoObjectCreator.createObject(schema, buffer.array())
}

fun convertObjectsToType (array : Array<ByteArray>, type: XyoObjectSchema) : Array<ByteArray> {
val newValues = ArrayList<ByteArray>()

for (value in array) {
if (value[1] != type.id) {
throw XyoObjectExceotion("Can not convert types! ${value[1]}, ${type.id}")
}

newValues.add(XyoObjectCreator.createObject(type, XyoObjectCreator.getObjectValue(value)))
}

return newValues.toTypedArray()
}

/**
* Creates an typed array. (An array that can only contain a single type of object).
*/
Expand All @@ -43,6 +57,10 @@ object XyoObjectSetCreator {

var totalSize = 2

if (values.isEmpty()) {
totalSize = 0
}

for (item in values) {
totalSize += item.size - 2
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ import network.xyo.sdkobjectmodelkotlin.objects.XyoObjectCreator
import network.xyo.sdkobjectmodelkotlin.schema.XyoObjectSchema
import org.junit.Assert
import org.junit.Test
import java.math.BigInteger

class XyoObjectCreatorTest {

// @Test
// fun test () {
// val bytes = BigInteger("A0020000004AA00100000011A0010000000B800E0000000500B0CC0000001EB00700000018A0010000000E8003000000080000000000000004A00100000011A0010000000B800B0000000500", 16).toByteArray()
// val correctBytes = bytes.copyOfRange(1, bytes.size)
// println(XyoObjectCreator.itemToByteString(correctBytes,0, true))
// }

@Test
fun testSmartSizeForByte () {
val sizeOfImageryObject = 254
Expand Down
Loading

0 comments on commit 71e9f9b

Please sign in to comment.