Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java: add ability to report positions relative to root stream and add PositionInfo interface #197

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ class CSharpCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
handleAssignment(varDest, expr, rep, false)
}

override def allocateIO(varName: Identifier, rep: RepeatSpec): String = {
override def allocateIO(varName: Identifier, rep: RepeatSpec, currentIo: String): String = {
val privateVarName = privateMemberName(varName)

val ioName = s"io_$privateVarName"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ class CppCompiler(
handleAssignment(varDest, expr, rep, false)
}

override def allocateIO(id: Identifier, rep: RepeatSpec): String = {
override def allocateIO(id: Identifier, rep: RepeatSpec, currentIo: String): String = {
val memberName = privateMemberName(id)
val ioId = IoStorageIdentifier(id)

Expand Down Expand Up @@ -855,7 +855,7 @@ class CppCompiler(

override def instanceCalculate(instName: Identifier, dataType: DataType, value: Ast.expr): Unit = {
if (attrDebugNeeded(instName))
attrDebugStart(instName, dataType, None, NoRepeat)
attrDebugStart(instName, dataType, NoRepeat, None, NoRepeat)
val valExpr = expression(value)
val isOwningInExpr = dataType match {
case ct: ComplexDataType => ct.isOwningInExpr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ class GoCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
handleAssignment(varDest, ResultString(expr), rep, false)
}

override def allocateIO(varName: Identifier, rep: RepeatSpec): String = {
override def allocateIO(varName: Identifier, rep: RepeatSpec, currentIo: String): String = {
val javaName = privateMemberName(varName)

val ioName = idToStr(IoStorageIdentifier(varName))
Expand Down
70 changes: 42 additions & 28 deletions shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,23 @@ class JavaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
""
}

out.puts(s"public ${staticStr}class ${type2class(name)} extends $kstructName {")
val iface = if (config.readStoresPos) {
"implements PositionInfo "
} else {
""
}

out.puts(s"public ${staticStr}class ${type2class(name)} extends $kstructName $iface{")
out.inc

if (config.readStoresPos) {
out.puts("public Map<String, Integer> _attrStart = new HashMap<String, Integer>();")
out.puts("public Map<String, Integer> _attrEnd = new HashMap<String, Integer>();")
out.puts("public Map<String, ArrayList<Integer>> _arrStart = new HashMap<String, ArrayList<Integer>>();")
out.puts("public Map<String, ArrayList<Integer>> _arrEnd = new HashMap<String, ArrayList<Integer>>();")
out.puts("public final Map<String, Span> _spans = new HashMap<String, Span>();")
out.puts("@Override")
out.puts("public final Map<String, Span> _spans() { return this._spans; }")
out.puts

importList.add("io.kaitai.struct.PositionInfo")
importList.add("io.kaitai.struct.Span")
importList.add("java.util.ArrayList")
importList.add("java.util.HashMap")
importList.add("java.util.Map")
Expand Down Expand Up @@ -221,6 +228,14 @@ class JavaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
out.puts( " */")
}

override def attrParse(attr: AttrLikeSpec, id: Identifier, defEndian: Option[Endianness]): Unit = {
out.puts(s"{// ${idToStr(id)}")
out.inc
super.attrParse(attr, id, defEndian)
out.dec
out.puts("}")
}

override def attrParseHybrid(leProc: () => Unit, beProc: () => Unit): Unit = {
out.puts("if (_is_le) {")
out.inc
Expand Down Expand Up @@ -268,7 +283,7 @@ class JavaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
handleAssignment(varDest, expr, rep, false)
}

override def allocateIO(varName: Identifier, rep: RepeatSpec): String = {
override def allocateIO(varName: Identifier, rep: RepeatSpec, currentIo: String): String = {
val ioName = idToStr(IoStorageIdentifier(varName))

val args = rep match {
Expand All @@ -277,7 +292,7 @@ class JavaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
}

importList.add("io.kaitai.struct.ByteBufferKaitaiStream")
out.puts(s"$kstreamName $ioName = new ByteBufferKaitaiStream($args);")
out.puts(s"$kstreamName $ioName = new ByteBufferKaitaiStream($args, $currentIo.offset());")
ioName
}

Expand Down Expand Up @@ -306,14 +321,23 @@ class JavaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
override def alignToByte(io: String): Unit =
out.puts(s"$io.alignToByte();")

override def attrDebugStart(attrId: Identifier, attrType: DataType, ios: Option[String], rep: RepeatSpec): Unit = {
override def attrDebugStart(attrId: Identifier, attrType: DataType, attrRep: RepeatSpec, ios: Option[String], rep: RepeatSpec): Unit = {
ios.foreach { (io) =>
val name = idToStr(attrId)
rep match {
case NoRepeat =>
out.puts("_attrStart.put(\"" + name + "\", " + io + ".pos());")
attrRep match {
case NoRepeat =>
out.puts(s"final Span _s = new Span(${io});")
out.puts(s"""this._spans.put("${name}", _s);""")
importList.add("io.kaitai.struct.Span")
case _: RepeatExpr | RepeatEos | _: RepeatUntil =>
out.puts(s"final ArraySpan _as = new ArraySpan(${io});")
out.puts(s"""this._spans.put("${name}", _as);""")
importList.add("io.kaitai.struct.ArraySpan")
}
case _: RepeatExpr | RepeatEos | _: RepeatUntil =>
getOrCreatePosList("_arrStart", name, io)
out.puts(s"final Span _is = _as.addItem(${io});")
}
}
}
Expand All @@ -322,31 +346,21 @@ class JavaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
// no _debug[$name]['arr'] initialization needed in Java
}

override def attrDebugEnd(attrId: Identifier, attrType: DataType, io: String, rep: RepeatSpec): Unit = {
override def attrDebugEnd(attrId: Identifier, attrType: DataType, attrRep: RepeatSpec, io: String, rep: RepeatSpec): Unit = {
val name = idToStr(attrId)
rep match {
case NoRepeat =>
out.puts("_attrEnd.put(\"" + name + "\", " + io + ".pos());")
attrRep match {
case NoRepeat =>
out.puts(s"_s.end = ${io}.pos();")
case _: RepeatExpr | RepeatEos | _: RepeatUntil =>
out.puts(s"_as.end = ${io}.pos();")
}
case _: RepeatExpr | RepeatEos | _: RepeatUntil =>
getOrCreatePosList("_arrEnd", name, io)
out.puts(s"_is.end = ${io}.pos();")
}
}

def getOrCreatePosList(listName: String, varName: String, io: String): Unit = {
out.puts("{")
out.inc
out.puts("ArrayList<Integer> _posList = " + listName + ".get(\"" + varName + "\");")
out.puts("if (_posList == null) {")
out.inc
out.puts("_posList = new ArrayList<Integer>();")
out.puts(listName + ".put(\"" + varName + "\", _posList);")
out.dec
out.puts("}")
out.puts(s"_posList.add($io.pos());")
out.dec
out.puts("}")
}

override def condIfHeader(expr: expr): Unit = {
out.puts(s"if (${expression(expr)}) {")
out.inc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ class JavaScriptCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
handleAssignment(varDest, expr, rep, false)
}

override def allocateIO(varName: Identifier, rep: RepeatSpec): String = {
override def allocateIO(varName: Identifier, rep: RepeatSpec, currentIo: String): String = {
val langName = idToStr(varName)
val memberCall = privateMemberName(varName)

Expand Down Expand Up @@ -264,7 +264,7 @@ class JavaScriptCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
override def alignToByte(io: String): Unit =
out.puts(s"$io.alignToByte();")

override def attrDebugStart(attrId: Identifier, attrType: DataType, io: Option[String], rep: RepeatSpec): Unit = {
override def attrDebugStart(attrId: Identifier, attrType: DataType, attrRep: RepeatSpec, io: Option[String], rep: RepeatSpec): Unit = {
val debugName = attrDebugName(attrId, rep, false)

val ioProps = io match {
Expand All @@ -283,7 +283,7 @@ class JavaScriptCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
override def attrDebugArrInit(id: Identifier, attrType: DataType): Unit =
out.puts(s"this._debug.${idToStr(id)}.arr = [];")

override def attrDebugEnd(attrId: Identifier, attrType: DataType, io: String, rep: RepeatSpec): Unit = {
override def attrDebugEnd(attrId: Identifier, attrType: DataType, attrRep: RepeatSpec, io: String, rep: RepeatSpec): Unit = {
val debugName = attrDebugName(attrId, rep, true)

out.puts(s"$debugName.end = $io.pos;")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ class LuaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
override def switchIfEnd(): Unit =
out.puts("end")

override def allocateIO(varName: Identifier, rep: RepeatSpec): String = {
override def allocateIO(varName: Identifier, rep: RepeatSpec, currentIo: String): String = {
val varStr = privateMemberName(varName)

val args = getRawIdExpr(varName, rep)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class NimCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
override def universalFooter: Unit = {
out.dec
}
override def allocateIO(id: Identifier, rep: RepeatSpec): String = {
override def allocateIO(id: Identifier, rep: RepeatSpec, currentIo: String): String = {
val ioName = s"${idToStr(id)}Io"
val arg = rep match {
case NoRepeat => idToStr(id) + "Expr"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
handleAssignment(varDest, expr, rep, false)
}

override def allocateIO(id: Identifier, rep: RepeatSpec): String = {
override def allocateIO(id: Identifier, rep: RepeatSpec, currentIo: String): String = {
val memberName = privateMemberName(id)
val ioName = s"$$_io_${idToStr(id)}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class PerlCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
handleAssignment(varDest, expr, rep, false)
}

override def allocateIO(id: Identifier, rep: RepeatSpec): String = {
override def allocateIO(id: Identifier, rep: RepeatSpec, currentIo: String): String = {
val memberName = privateMemberName(id)

val args = rep match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)

override def normalIO: String = "self._io"

override def allocateIO(varName: Identifier, rep: RepeatSpec): String = {
override def allocateIO(varName: Identifier, rep: RepeatSpec, currentIo: String): String = {
val varStr = privateMemberName(varName)
val ioName = s"_io_${idToStr(varName)}"

Expand Down Expand Up @@ -265,7 +265,7 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
override def alignToByte(io: String): Unit =
out.puts(s"$io.align_to_byte()")

override def attrDebugStart(attrId: Identifier, attrType: DataType, ios: Option[String], rep: RepeatSpec): Unit = {
override def attrDebugStart(attrId: Identifier, attrType: DataType, attrRep: RepeatSpec, ios: Option[String], rep: RepeatSpec): Unit = {
ios.foreach { (io) =>
val name = idToStr(attrId)
rep match {
Expand All @@ -280,7 +280,7 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
override def attrDebugArrInit(attrId: Identifier, attrType: DataType): Unit =
out.puts(s"self._debug['${idToStr(attrId)}']['arr'] = []")

override def attrDebugEnd(attrId: Identifier, attrType: DataType, io: String, rep: RepeatSpec): Unit = {
override def attrDebugEnd(attrId: Identifier, attrType: DataType, attrRep: RepeatSpec, io: String, rep: RepeatSpec): Unit = {
val name = idToStr(attrId)
rep match {
case NoRepeat =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
handleAssignment(varDest, expr, rep, false)
}

override def allocateIO(id: Identifier, rep: RepeatSpec): String = {
override def allocateIO(id: Identifier, rep: RepeatSpec, currentIo: String): String = {
val memberName = privateMemberName(id)
val ioName = s"_io_${idToStr(id)}"

Expand Down Expand Up @@ -269,7 +269,7 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
override def alignToByte(io: String): Unit =
out.puts(s"$io.align_to_byte")

override def attrDebugStart(attrId: Identifier, attrType: DataType, ios: Option[String], rep: RepeatSpec): Unit = {
override def attrDebugStart(attrId: Identifier, attrType: DataType, attrRep: RepeatSpec, ios: Option[String], rep: RepeatSpec): Unit = {
ios.foreach { (io) =>
val name = idToStr(attrId)
rep match {
Expand All @@ -286,7 +286,7 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
override def attrDebugArrInit(attrId: Identifier, attrType: DataType): Unit =
out.puts(s"@_debug['${idToStr(attrId)}'][:arr] = []")

override def attrDebugEnd(attrId: Identifier, attrType: DataType, io: String, rep: RepeatSpec): Unit = {
override def attrDebugEnd(attrId: Identifier, attrType: DataType, attrRep: RepeatSpec, io: String, rep: RepeatSpec): Unit = {
val name = idToStr(attrId)
rep match {
case NoRepeat =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
out.puts("}")
}

override def allocateIO(id: Identifier, rep: RepeatSpec): String = {//= privateMemberName(IoIdentifier)
override def allocateIO(id: Identifier, rep: RepeatSpec, currentIo: String): String = {//= privateMemberName(IoIdentifier)
val memberName = privateMemberName(id)
val ioId = IoStorageIdentifier(id)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ import io.kaitai.struct.format._
* keep track of allocated IOs.
*/
trait AllocateAndStoreIO extends ExtraAttrs {
def allocateIO(id: Identifier, rep: RepeatSpec): String
/**
* Generates code that create new input stream for read specified field content
*
* @param id Name of variable that used to store field for which stream is created
* @param rep Repeat specification for the [[id]] field
* @param currentIo Name of current stream variable, that used to read data currently
*/
def allocateIO(id: Identifier, rep: RepeatSpec, currentIo: String): String

override def extraAttrForIO(id: Identifier, rep: RepeatSpec): List[AttrSpec] =
List(AttrSpec(List(), IoStorageIdentifier(id), OwnedKaitaiStreamType, ConditionalSpec(None, rep)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ import io.kaitai.struct.format.{AttrSpec, Identifier, RepeatSpec}
* probably garbage collector will deal with them.
*/
trait AllocateIOLocalVar extends ExtraAttrs {
def allocateIO(varName: Identifier, rep: RepeatSpec): String
/**
* Generates code that create new input stream for read specified field content
*
* @param id Name of variable that used to store field for which stream is created
* @param rep Repeat specification for the [[id]] field
* @param currentIo Name of current stream variable, that used to read data currently
*/
def allocateIO(varName: Identifier, rep: RepeatSpec, currentIo: String): String

override def extraAttrForIO(id: Identifier, rep: RepeatSpec): List[AttrSpec] = List()
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ trait CommonReads extends LanguageCompiler {
val needsArrayDebug = attrDebugNeeded(id) && attr.cond.repeat != NoRepeat

if (needsArrayDebug) {
attrDebugStart(id, attr.dataType, Some(io), NoRepeat)
attrDebugStart(id, attr.dataType, attr.cond.repeat, Some(io), NoRepeat)
attrDebugArrInit(id, attr.dataType)
}

Expand All @@ -45,7 +45,7 @@ trait CommonReads extends LanguageCompiler {
}

if (needsArrayDebug)
attrDebugEnd(id, attr.dataType, io, NoRepeat)
attrDebugEnd(id, attr.dataType, attr.cond.repeat, io, NoRepeat)

// More position management + set calculated flag after parsing for ParseInstanceSpecs
attr match {
Expand Down Expand Up @@ -74,12 +74,12 @@ trait CommonReads extends LanguageCompiler {

val needsDebug = attrDebugNeeded(id)
if (needsDebug)
attrDebugStart(id, attr.dataType, Some(io), attr.cond.repeat)
attrDebugStart(id, attr.dataType, attr.cond.repeat, Some(io), attr.cond.repeat)

attrParse2(id, attr.dataType, io, attr.cond.repeat, false, defEndian)

if (needsDebug)
attrDebugEnd(id, attr.dataType, io, attr.cond.repeat)
attrDebugEnd(id, attr.dataType, attr.cond.repeat, io, attr.cond.repeat)

attrValidateAll(attr)
attr.cond.repeat match {
Expand All @@ -95,9 +95,9 @@ trait CommonReads extends LanguageCompiler {

def attrParse2(id: Identifier, dataType: DataType, io: String, rep: RepeatSpec, isRaw: Boolean, defEndian: Option[FixedEndian], assignType: Option[DataType] = None): Unit

def attrDebugStart(attrId: Identifier, attrType: DataType, io: Option[String], repeat: RepeatSpec): Unit = {}
def attrDebugStart(attrName: Identifier, attrType: DataType, attrRep: RepeatSpec, io: Option[String], repeat: RepeatSpec): Unit = {}
def attrDebugArrInit(attrId: Identifier, attrType: DataType): Unit = {}
def attrDebugEnd(attrName: Identifier, attrType: DataType, io: String, repeat: RepeatSpec): Unit = {}
def attrDebugEnd(attrName: Identifier, attrType: DataType, attrRep: RepeatSpec, io: String, repeat: RepeatSpec): Unit = {}

def attrDebugNeeded(attrId: Identifier): Boolean = {
if (!config.readStoresPos)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ trait EveryReadIsExpression

this match {
case thisStore: AllocateAndStoreIO =>
thisStore.allocateIO(rawId, rep)
thisStore.allocateIO(rawId, rep, io)
case thisLocal: AllocateIOLocalVar =>
thisLocal.allocateIO(rawId, rep)
thisLocal.allocateIO(rawId, rep, io)
}
}

Expand Down Expand Up @@ -245,7 +245,7 @@ trait EveryReadIsExpression

def instanceCalculate(instName: Identifier, dataType: DataType, value: Ast.expr): Unit = {
if (attrDebugNeeded(instName))
attrDebugStart(instName, dataType, None, NoRepeat)
attrDebugStart(instName, dataType, NoRepeat, None, NoRepeat)
handleAssignmentSimple(instName, expression(value))
}
}
Loading
Loading