diff --git a/js/src/main/scala/io/kaitai/struct/Platform.scala b/js/src/main/scala/io/kaitai/struct/Platform.scala new file mode 100644 index 000000000..a675b64a2 --- /dev/null +++ b/js/src/main/scala/io/kaitai/struct/Platform.scala @@ -0,0 +1,5 @@ +package io.kaitai.struct + +object Platform { + def toUpperLocaleInsensitive(s: String) = s.toUpperCase() +} diff --git a/jvm/src/main/scala/io/kaitai/struct/Platform.scala b/jvm/src/main/scala/io/kaitai/struct/Platform.scala new file mode 100644 index 000000000..e9ab71d4c --- /dev/null +++ b/jvm/src/main/scala/io/kaitai/struct/Platform.scala @@ -0,0 +1,7 @@ +package io.kaitai.struct + +import java.util.Locale + +object Platform { + def toUpperLocaleInsensitive(s: String) = s.toUpperCase(Locale.ROOT) +} diff --git a/jvm/src/test/scala/io/kaitai/struct/UtilsSpec.scala b/jvm/src/test/scala/io/kaitai/struct/UtilsSpec.scala new file mode 100644 index 000000000..207232d8f --- /dev/null +++ b/jvm/src/test/scala/io/kaitai/struct/UtilsSpec.scala @@ -0,0 +1,83 @@ +package io.kaitai.struct + +import java.util.Locale + +import org.scalatest.{FunSpec, Matchers} + +/** + * Checks that our string case conversion utilities perform well in all locales. + * To test with different locale than you have set up in your system, pass JVM + * options, e.g. `-Duser.language=tr -Duser.country=TR`. + */ +class UtilsSpec extends FunSpec with Matchers { + val simpleStr = "foo_bar" + val internalId = "_foo_bar" + val allLetters = "a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z" + + describe("UtilsSpec") { + it("checks default locale") { + val l = Locale.getDefault + Console.println(s"country: ${l.getCountry}") + Console.println(s"language: ${l.getLanguage}") + Console.println(s"displayScript: ${l.getDisplayScript}") + Console.println(s"displayVariant: ${l.getDisplayVariant}") + } + + describe("lowerUnderscoreCase") { + it("has Turkish locale") { + Console.println(Locale.getDefault) + Console.println(Locale.forLanguageTag("tr")) + } + + it("works with simple string") { + Utils.lowerUnderscoreCase(simpleStr) shouldEqual "foo_bar" + } + + it("is locale-independent") { + Utils.lowerUnderscoreCase(allLetters) shouldEqual + "a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z" + } + } + + describe("upperUnderscoreCase") { + it("works with simple string") { + Utils.upperUnderscoreCase(simpleStr) shouldEqual "FOO_BAR" + } + + it("is locale-independent") { + Utils.upperUnderscoreCase(allLetters) shouldEqual + "A_B_C_D_E_F_G_H_I_J_K_L_M_N_O_P_Q_R_S_T_U_V_W_X_Y_Z" + } + } + + describe("upperCamelCase") { + it("works") { + Utils.upperCamelCase(simpleStr) shouldEqual "FooBar" + } + + it("preserves initial underscore") { + Utils.upperCamelCase(internalId) shouldEqual "_FooBar" + } + + it("is locale-independent") { + Utils.upperCamelCase(allLetters) shouldEqual + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + } + + describe("lowerCamelCase") { + it("works") { + Utils.lowerCamelCase(simpleStr) shouldEqual "fooBar" + } + + it("preserves initial underscore") { + Utils.lowerCamelCase(internalId) shouldEqual "_fooBar" + } + + it("is locale-independent") { + Utils.lowerCamelCase(allLetters) shouldEqual + "aBCDEFGHIJKLMNOPQRSTUVWXYZ" + } + } + } +} diff --git a/shared/src/main/scala/io/kaitai/struct/Utils.scala b/shared/src/main/scala/io/kaitai/struct/Utils.scala index bae0c7050..0bd6f7062 100644 --- a/shared/src/main/scala/io/kaitai/struct/Utils.scala +++ b/shared/src/main/scala/io/kaitai/struct/Utils.scala @@ -44,6 +44,27 @@ object Utils { } } + /** + * Converts string to `UPPER_UNDER_SCORE` case. + * @param s original string in `lower_under_score` case. + * @return same string in `UPPER_UNDER_SCORE` case. + */ + def upperUnderscoreCase(s: String): String = + Platform.toUpperLocaleInsensitive(s) + + /** + * Converts string to `lower_under_score` case. Given that currently + * original string is using the same case, it is essentially a no-op. + * @param s original string in `lower_under_score` case. + * @return same string in `lower_under_score` case. + */ + def lowerUnderscoreCase(s: String): String = s + + /** + * Converts string to `UpperCamelCase`. + * @param s original string in `lower_under_score` case. + * @return same string in `UpperCamelCase`. + */ def upperCamelCase(s: String): String = { if (s.startsWith("_")) { "_" + upperCamelCase(s.substring(1)) @@ -52,6 +73,11 @@ object Utils { } } + /** + * Converts string to `lowerCamelCase`. + * @param s original string in `lower_under_score` case. + * @return same string in `lowerCamelCase`. + */ def lowerCamelCase(s: String): String = { if (s.startsWith("_")) { "_" + lowerCamelCase(s.substring(1)) diff --git a/shared/src/main/scala/io/kaitai/struct/datatype/NeedRaw.scala b/shared/src/main/scala/io/kaitai/struct/datatype/NeedRaw.scala new file mode 100644 index 000000000..647ee36d1 --- /dev/null +++ b/shared/src/main/scala/io/kaitai/struct/datatype/NeedRaw.scala @@ -0,0 +1,18 @@ +package io.kaitai.struct.datatype + +sealed trait NeedRaw { + val level: Int +} + +case object NotRaw extends NeedRaw { + val level = 0 +} +case object RawIo extends NeedRaw { + val level = 1 +} +case object RawProcess extends NeedRaw { + val level = 1 +} +case object RawIoProcess extends NeedRaw { + val level = 2 +} diff --git a/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala index 51c58fe29..535196d6f 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala @@ -142,7 +142,7 @@ class CSharpCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) "private" } val suffix = endian match { - case Some(e) => s"${e.toSuffix.toUpperCase}" + case Some(e) => Utils.upperUnderscoreCase(e.toSuffix) case None => "" } out.puts(s"$readAccessAndType void _read$suffix()") @@ -196,28 +196,28 @@ class CSharpCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) override def attrFixedContentsParse(attrName: Identifier, contents: String): Unit = out.puts(s"${privateMemberName(attrName)} = $normalIO.EnsureFixedContents($contents);") - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - proc match { + val expr = proc match { case ProcessXor(xorValue) => - out.puts(s"$destName = $normalIO.ProcessXor($srcName, ${expression(xorValue)});") + s"$normalIO.ProcessXor($srcExpr, ${expression(xorValue)})" case ProcessZlib => - out.puts(s"$destName = $normalIO.ProcessZlib($srcName);") + s"$normalIO.ProcessZlib($srcExpr)" case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - out.puts(s"$destName = $normalIO.ProcessRotateLeft($srcName, $expr, 1);") + s"$normalIO.ProcessRotateLeft($srcExpr, $expr, 1)" case ProcessCustom(name, args) => val procClass = types2class(name) val procName = s"_process_${idToStr(varSrc)}" out.puts(s"$procClass $procName = new $procClass(${args.map(expression).mkString(", ")});") - out.puts(s"$destName = $procName.Decode($srcName);") + s"$procName.Decode($srcExpr)" } + handleAssignment(varDest, expr, rep, false) } override def allocateIO(varName: Identifier, rep: RepeatSpec): String = { @@ -226,15 +226,22 @@ class CSharpCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) val ioName = s"io_$privateVarName" val args = rep match { - case RepeatEos | RepeatExpr(_) => s"$privateVarName[$privateVarName.Count - 1]" case RepeatUntil(_) => translator.doName(Identifier.ITERATOR2) - case NoRepeat => privateVarName + case _ => getRawIdExpr(varName, rep) } out.puts(s"var $ioName = new $kstreamName($args);") ioName } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case _ => s"$memberName[$memberName.Count - 1]" + } + } + override def useIO(ioEx: expr): String = { out.puts(s"$kstreamName io = ${expression(ioEx)};") "io" @@ -267,11 +274,14 @@ class CSharpCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) override def condIfFooter(expr: expr): Unit = fileFooter(null) - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { importList.add("System.Collections.Generic") - if (needRaw) + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = new List();") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new List();") + out.puts(s"${privateMemberName(id)} = new ${kaitaiType2NativeType(ArrayTypeInStream(dataType))}();") out.puts("{") out.inc @@ -292,11 +302,13 @@ class CSharpCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("}") } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: expr): Unit = { + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: expr): Unit = { importList.add("System.Collections.Generic") - if (needRaw) + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = new List((int) (${expression(repeatExpr)}));") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new List((int) (${expression(repeatExpr)}));") out.puts(s"${privateMemberName(id)} = new ${kaitaiType2NativeType(ArrayTypeInStream(dataType))}((int) (${expression(repeatExpr)}));") out.puts(s"for (var i = 0; i < ${expression(repeatExpr)}; i++)") out.puts("{") @@ -309,11 +321,13 @@ class CSharpCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) override def condRepeatExprFooter: Unit = fileFooter(null) - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { importList.add("System.Collections.Generic") - if (needRaw) + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = new List();") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new List();") out.puts(s"${privateMemberName(id)} = new ${kaitaiType2NativeType(ArrayTypeInStream(dataType))}();") out.puts("{") out.inc @@ -333,7 +347,7 @@ class CSharpCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)}.Add($tempVar);") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.puts("i++;") out.dec @@ -664,6 +678,4 @@ object CSharpCompiler extends LanguageCompilerStatic case EndOfStreamError => "EndOfStreamException" case _ => err.name } - - override def type2class(name: String): String = Utils.upperCamelCase(name) } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/CppCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/CppCompiler.scala index dd2311feb..7beb39747 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/CppCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/CppCompiler.scala @@ -462,26 +462,25 @@ class CppCompiler( override def attrFixedContentsParse(attrName: Identifier, contents: String): Unit = outSrc.puts(s"${privateMemberName(attrName)} = $normalIO->ensure_fixed_contents($contents);") - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - proc match { + val expr = proc match { case ProcessXor(xorValue) => val procName = translator.detectType(xorValue) match { case _: IntType => "process_xor_one" case _: BytesType => "process_xor_many" } - outSrc.puts(s"$destName = $kstreamName::$procName($srcName, ${expression(xorValue)});") + s"$kstreamName::$procName($srcExpr, ${expression(xorValue)})" case ProcessZlib => - outSrc.puts(s"$destName = $kstreamName::process_zlib($srcName);") + s"$kstreamName::process_zlib($srcExpr)" case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - outSrc.puts(s"$destName = $kstreamName::process_rotate_left($srcName, $expr);") + s"$kstreamName::process_rotate_left($srcExpr, $expr)" case ProcessCustom(name, args) => val procClass = name.map((x) => type2class(x)).mkString("::") val procName = s"_process_${idToStr(varSrc)}" @@ -491,8 +490,9 @@ class CppCompiler( val argList = args.map(expression).mkString(", ") var argListInParens = if (argList.nonEmpty) s"($argList)" else "" outSrc.puts(s"$procClass $procName$argListInParens;") - outSrc.puts(s"$destName = $procName.decode($srcName);") + s"$procName.decode($srcExpr)" } + handleAssignment(varDest, expr, rep, false) } override def allocateIO(id: Identifier, rep: RepeatSpec): String = { @@ -500,9 +500,8 @@ class CppCompiler( val ioId = IoStorageIdentifier(id) val args = rep match { - case RepeatEos | RepeatExpr(_) => s"$memberName->at($memberName->size() - 1)" case RepeatUntil(_) => translator.doName(Identifier.ITERATOR2) - case NoRepeat => memberName + case _ => getRawIdExpr(id, rep) } val newStream = s"new $kstreamName($args)" @@ -521,6 +520,14 @@ class CppCompiler( ioName } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case _ => s"$memberName->at($memberName->size() - 1)" + } + } + override def useIO(ioEx: Ast.expr): String = { outSrc.puts(s"$kstreamName *io = ${expression(ioEx)};") "io" @@ -560,13 +567,16 @@ class CppCompiler( outSrc.puts("}") } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { importListHdr.addSystem("vector") - if (needRaw) { + if (needRaw.level >= 1) { outSrc.puts(s"${privateMemberName(RawIdentifier(id))} = ${newVector(CalcBytesType)};") outSrc.puts(s"${privateMemberName(IoStorageIdentifier(RawIdentifier(id)))} = ${newVector(KaitaiStreamType)};") } + if (needRaw.level >= 2) { + outSrc.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = ${newVector(CalcBytesType)};") + } outSrc.puts(s"${privateMemberName(id)} = ${newVector(dataType)};") outSrc.puts("{") outSrc.inc @@ -587,12 +597,12 @@ class CppCompiler( outSrc.puts("}") } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: Ast.expr): Unit = { + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: Ast.expr): Unit = { importListHdr.addSystem("vector") val lenVar = s"l_${idToStr(id)}" outSrc.puts(s"int $lenVar = ${expression(repeatExpr)};") - if (needRaw) { + if (needRaw.level >= 1) { val rawId = privateMemberName(RawIdentifier(id)) outSrc.puts(s"$rawId = ${newVector(CalcBytesType)};") outSrc.puts(s"$rawId->reserve($lenVar);") @@ -600,6 +610,11 @@ class CppCompiler( outSrc.puts(s"$ioId = ${newVector(KaitaiStreamType)};") outSrc.puts(s"$ioId->reserve($lenVar);") } + if (needRaw.level >= 2) { + val rawId = privateMemberName(RawIdentifier(RawIdentifier(id))) + outSrc.puts(s"$rawId = ${newVector(CalcBytesType)};") + outSrc.puts(s"$rawId->reserve($lenVar);") + } outSrc.puts(s"${privateMemberName(id)} = ${newVector(dataType)};") outSrc.puts(s"${privateMemberName(id)}->reserve($lenVar);") outSrc.puts(s"for (int i = 0; i < $lenVar; i++) {") @@ -615,13 +630,16 @@ class CppCompiler( outSrc.puts("}") } - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { importListHdr.addSystem("vector") - if (needRaw) { + if (needRaw.level >= 1) { outSrc.puts(s"${privateMemberName(RawIdentifier(id))} = ${newVector(CalcBytesType)};") outSrc.puts(s"${privateMemberName(IoStorageIdentifier(RawIdentifier(id)))} = ${newVector(KaitaiStreamType)};") } + if (needRaw.level >= 2) { + outSrc.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = ${newVector(CalcBytesType)};") + } outSrc.puts(s"${privateMemberName(id)} = ${newVector(dataType)};") outSrc.puts("{") outSrc.inc @@ -656,7 +674,7 @@ class CppCompiler( outSrc.puts(s"${privateMemberName(id)}->push_back($wrappedTempVar);") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { typeProvider._currentIteratorType = Some(dataType) outSrc.puts("i++;") outSrc.dec @@ -877,9 +895,9 @@ class CppCompiler( outHdr.puts("};") } - def value2Const(enumName: String, label: String) = (enumName + "_" + label).toUpperCase + def value2Const(enumName: String, label: String) = Utils.upperUnderscoreCase(enumName + "_" + label) - def defineName(className: String) = className.toUpperCase + "_H_" + def defineName(className: String) = Utils.upperUnderscoreCase(className) + "_H_" /** * Returns name of a member that stores "calculated flag" for a given lazy @@ -905,10 +923,10 @@ class CppCompiler( id match { case RawIdentifier(inner) => s"_raw_${idToStr(inner)}" case IoStorageIdentifier(inner) => s"_io_${idToStr(inner)}" - case si: SpecialIdentifier => si.name - case ni: NamedIdentifier => ni.name + case si: SpecialIdentifier => Utils.lowerUnderscoreCase(si.name) + case ni: NamedIdentifier => Utils.lowerUnderscoreCase(ni.name) case NumberedIdentifier(idx) => s"_${NumberedIdentifier.TEMPLATE}$idx" - case ni: InstanceIdentifier => ni.name + case ni: InstanceIdentifier => Utils.lowerUnderscoreCase(ni.name) } } @@ -1053,7 +1071,10 @@ object CppCompiler extends LanguageCompilerStatic case RawPointers => s"std::vector<${kaitaiType2NativeType(config, inType, absolute)}>*" case UniqueAndRawPointers => s"std::unique_ptr>" } - case CalcArrayType(inType) => s"std::vector<${kaitaiType2NativeType(config, inType, absolute)}>*" + case CalcArrayType(inType) => config.pointers match { + case RawPointers => s"std::vector<${kaitaiType2NativeType(config, inType, absolute)}>*" + case UniqueAndRawPointers => s"std::unique_ptr>" + } case KaitaiStreamType => s"$kstreamName*" case KaitaiStructType => config.pointers match { case RawPointers => s"$kstructName*" @@ -1106,5 +1127,5 @@ object CppCompiler extends LanguageCompilerStatic def types2class(components: List[String]) = components.map(type2class).mkString("::") - def type2class(name: String) = name + "_t" + def type2class(name: String) = Utils.lowerUnderscoreCase(name) + "_t" } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala index f884ef4a0..b34825561 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala @@ -195,32 +195,31 @@ class GoCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("}") } - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - proc match { + val expr = proc match { case ProcessXor(xorValue) => translator.detectType(xorValue) match { case _: IntType => - out.puts(s"$destName = kaitai.ProcessXOR($srcName, []byte{${expression(xorValue)}})") + s"kaitai.ProcessXOR($srcExpr, []byte{${expression(xorValue)}})" case _: BytesType => - out.puts(s"$destName = kaitai.ProcessXOR($srcName, ${expression(xorValue)})") + s"kaitai.ProcessXOR($srcExpr, ${expression(xorValue)})" } case ProcessZlib => - out.puts(s"$destName, err = kaitai.ProcessZlib($srcName)") - translator.outAddErrCheck() + translator.resToStr(translator.outVarCheckRes(s"kaitai.ProcessZlib($srcExpr)")) case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - out.puts(s"$destName = kaitai.ProcessRotateLeft($srcName, int($expr))") + s"kaitai.ProcessRotateLeft($srcExpr, int($expr))" case ProcessCustom(name, args) => // TODO(jchw): This hack is necessary because Go tests fail catastrophically otherwise... - out.puts(s"$destName = $srcName") + s"$srcExpr" } + handleAssignment(varDest, ResultString(expr), rep, false) } override def allocateIO(varName: Identifier, rep: RepeatSpec): String = { @@ -229,9 +228,8 @@ class GoCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) val ioName = idToStr(IoStorageIdentifier(varName)) val args = rep match { - case RepeatEos | RepeatExpr(_) => s"$javaName[len($javaName) - 1]" case RepeatUntil(_) => translator.specialName(Identifier.ITERATOR2) - case NoRepeat => javaName + case _ => getRawIdExpr(varName, rep) } importList.add("bytes") @@ -240,6 +238,15 @@ class GoCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) ioName } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case RepeatExpr(_) => s"$memberName[i]" + case _ => s"$memberName[len($memberName) - 1]" + } + } + override def useIO(ioEx: Ast.expr): String = { out.puts(s"thisIo := ${expression(ioEx)}") "thisIo" @@ -272,9 +279,11 @@ class GoCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { - if (needRaw) + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = make([][]byte, 0);") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = make([][]byte, 0);") //out.puts(s"${privateMemberName(id)} = make(${kaitaiType2NativeType(ArrayType(dataType))})") out.puts(s"for {") out.inc @@ -295,9 +304,11 @@ class GoCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"$name = append($name, $expr)") } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: Ast.expr): Unit = { - if (needRaw) + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: Ast.expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = make([][]byte, ${expression(repeatExpr)})") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = make([][]byte, ${expression(repeatExpr)})") out.puts(s"${privateMemberName(id)} = make(${kaitaiType2NativeType(ArrayTypeInStream(dataType))}, ${expression(repeatExpr)})") out.puts(s"for i := range ${privateMemberName(id)} {") out.inc @@ -309,9 +320,11 @@ class GoCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"$name[i] = $expr") } - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: Ast.expr): Unit = { - if (needRaw) + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: Ast.expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = make([][]byte, 0);") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = make([][]byte, 0);") out.puts("for {") out.inc } @@ -323,7 +336,7 @@ class GoCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)} = append(${privateMemberName(id)}, $tempVar)") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: Ast.expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: Ast.expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.puts(s"if ${expression(untilExpr)} {") out.inc diff --git a/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala index bdfb5020f..a4a012390 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala @@ -2,7 +2,7 @@ package io.kaitai.struct.languages import io.kaitai.struct._ import io.kaitai.struct.datatype.DataType._ -import io.kaitai.struct.datatype.{CalcEndian, DataType, EndOfStreamError, FixedEndian, InheritedEndian, KSError} +import io.kaitai.struct.datatype.{CalcEndian, DataType, EndOfStreamError, FixedEndian, InheritedEndian, KSError, NeedRaw} import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.exprlang.Ast.expr import io.kaitai.struct.format._ @@ -201,7 +201,7 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) "private" } val suffix = endian match { - case Some(e) => s"${e.toSuffix.toUpperCase}" + case Some(e) => Utils.upperUnderscoreCase(e.toSuffix) case None => "" } out.puts(s"$readAccessAndType void _read$suffix() {") @@ -293,22 +293,21 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(attrName)} = $normalIO.ensureFixedContents($contents);") } - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - proc match { + val expr = proc match { case ProcessXor(xorValue) => - out.puts(s"$destName = $kstreamName.processXor($srcName, ${expression(xorValue)});") + s"$kstreamName.processXor($srcExpr, ${expression(xorValue)})" case ProcessZlib => - out.puts(s"$destName = $kstreamName.processZlib($srcName);") + s"$kstreamName.processZlib($srcExpr)" case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - out.puts(s"$destName = $kstreamName.processRotateLeft($srcName, $expr, 1);") + s"$kstreamName.processRotateLeft($srcExpr, $expr, 1)" case ProcessCustom(name, args) => val namespace = name.init.mkString(".") val procClass = namespace + @@ -316,8 +315,9 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) type2class(name.last) val procName = s"_process_${idToStr(varSrc)}" out.puts(s"$procClass $procName = new $procClass(${args.map(expression).mkString(", ")});") - out.puts(s"$destName = $procName.decode($srcName);") + s"$procName.decode($srcExpr)" } + handleAssignment(varDest, expr, rep, false) } override def allocateIO(varName: Identifier, rep: RepeatSpec): String = { @@ -326,9 +326,8 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) val ioName = s"_io_$javaName" val args = rep match { - case RepeatEos | RepeatExpr(_) => s"$javaName.get($javaName.size() - 1)" case RepeatUntil(_) => translator.doName(Identifier.ITERATOR2) - case NoRepeat => javaName + case _ => getRawIdExpr(varName, rep) } importList.add("io.kaitai.struct.ByteBufferKaitaiStream") @@ -336,6 +335,14 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) ioName } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = idToStr(varName) + rep match { + case NoRepeat => memberName + case _ => s"$memberName.get($memberName.size() - 1)" + } + } + override def useIO(ioEx: expr): String = { out.puts(s"$kstreamName io = ${expression(ioEx)};") "io" @@ -401,9 +408,11 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { - if (needRaw) + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = new ArrayList();") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new ArrayList();") out.puts(s"${privateMemberName(id)} = new ${kaitaiType2JavaType(ArrayTypeInStream(dataType))}();") out.puts("{") out.inc @@ -426,9 +435,11 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("}") } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: expr): Unit = { - if (needRaw) + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = new ArrayList(((Number) (${expression(repeatExpr)})).intValue());") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new ArrayList(((Number) (${expression(repeatExpr)})).intValue());") out.puts(s"${idToStr(id)} = new ${kaitaiType2JavaType(ArrayTypeInStream(dataType))}(((Number) (${expression(repeatExpr)})).intValue());") out.puts(s"for (int i = 0; i < ${expression(repeatExpr)}; i++) {") out.inc @@ -440,9 +451,11 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)}.add($expr);") } - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { - if (needRaw) + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = new ArrayList();") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new ArrayList();") out.puts(s"${privateMemberName(id)} = new ${kaitaiType2JavaType(ArrayTypeInStream(dataType))}();") out.puts("{") out.inc @@ -464,7 +477,7 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)}.add($tempVar);") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.puts("i++;") out.dec @@ -759,7 +772,7 @@ class JavaCompiler(val typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"public static String[] _seqFields = new String[] { $seqStr };") } - def value2Const(s: String) = s.toUpperCase + def value2Const(s: String) = Utils.upperUnderscoreCase(s) def long2str(l: Long): String = { if (l.isValidInt) { diff --git a/shared/src/main/scala/io/kaitai/struct/languages/JavaScriptCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/JavaScriptCompiler.scala index bd4355957..241368ca0 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/JavaScriptCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/JavaScriptCompiler.scala @@ -138,7 +138,7 @@ class JavaScriptCompiler(val typeProvider: ClassTypeProvider, config: RuntimeCon override def readHeader(endian: Option[FixedEndian], isEmpty: Boolean) = { val suffix = endian match { - case Some(e) => e.toSuffix.toUpperCase + case Some(e) => Utils.upperUnderscoreCase(e.toSuffix) case None => "" } out.puts(s"${type2class(typeProvider.nowClass.name.last)}.prototype._read$suffix = function() {") @@ -189,26 +189,25 @@ class JavaScriptCompiler(val typeProvider: ClassTypeProvider, config: RuntimeCon s"$normalIO.ensureFixedContents($contents);") } - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - proc match { + val expr = proc match { case ProcessXor(xorValue) => val procName = translator.detectType(xorValue) match { case _: IntType => "processXorOne" case _: BytesType => "processXorMany" } - out.puts(s"$destName = $kstreamName.$procName($srcName, ${expression(xorValue)});") + s"$kstreamName.$procName($srcExpr, ${expression(xorValue)})" case ProcessZlib => - out.puts(s"$destName = $kstreamName.processZlib($srcName);") + s"$kstreamName.processZlib($srcExpr)" case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - out.puts(s"$destName = $kstreamName.processRotateLeft($srcName, $expr, 1);") + s"$kstreamName.processRotateLeft($srcExpr, $expr, 1)" case ProcessCustom(name, args) => val nameInit = name.init val pkgName = if (nameInit.isEmpty) "" else nameInit.mkString("-") + "/" @@ -217,8 +216,9 @@ class JavaScriptCompiler(val typeProvider: ClassTypeProvider, config: RuntimeCon importList.add(s"$pkgName$procClass") out.puts(s"var _process = new $procClass(${args.map(expression).mkString(", ")});") - out.puts(s"$destName = _process.decode($srcName);") + s"_process.decode($srcExpr)" } + handleAssignment(varDest, expr, rep, false) } override def allocateIO(varName: Identifier, rep: RepeatSpec): String = { @@ -227,16 +227,21 @@ class JavaScriptCompiler(val typeProvider: ClassTypeProvider, config: RuntimeCon val ioName = s"_io_$langName" - val args = rep match { - case RepeatEos | RepeatUntil(_) => s"$memberCall[$memberCall.length - 1]" - case RepeatExpr(_) => s"$memberCall[i]" - case NoRepeat => memberCall - } + val args = getRawIdExpr(varName, rep) out.puts(s"var $ioName = new $kstreamName($args);") ioName } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case RepeatExpr(_) => s"$memberName[i]" + case _ => s"$memberName[$memberName.length - 1]" + } + } + override def useIO(ioEx: expr): String = { out.puts(s"var io = ${expression(ioEx)};") "io" @@ -291,9 +296,11 @@ class JavaScriptCompiler(val typeProvider: ClassTypeProvider, config: RuntimeCon out.puts("}") } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { - if (needRaw) + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = [];") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [];") out.puts(s"${privateMemberName(id)} = [];") if (config.readStoresPos) out.puts(s"this._debug.${idToStr(id)}.arr = [];") @@ -312,9 +319,11 @@ class JavaScriptCompiler(val typeProvider: ClassTypeProvider, config: RuntimeCon out.puts("}") } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: expr): Unit = { - if (needRaw) + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = new Array(${expression(repeatExpr)});") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new Array(${expression(repeatExpr)});") out.puts(s"${privateMemberName(id)} = new Array(${expression(repeatExpr)});") if (config.readStoresPos) out.puts(s"this._debug.${idToStr(id)}.arr = new Array(${expression(repeatExpr)});") @@ -331,9 +340,11 @@ class JavaScriptCompiler(val typeProvider: ClassTypeProvider, config: RuntimeCon out.puts("}") } - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { - if (needRaw) + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = []") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [];") out.puts(s"${privateMemberName(id)} = []") if (config.readStoresPos) out.puts(s"this._debug.${idToStr(id)}.arr = [];") @@ -348,7 +359,7 @@ class JavaScriptCompiler(val typeProvider: ClassTypeProvider, config: RuntimeCon out.puts(s"${privateMemberName(id)}.push($tmpName);") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.puts("i++;") out.dec @@ -538,7 +549,7 @@ class JavaScriptCompiler(val typeProvider: ClassTypeProvider, config: RuntimeCon out.puts } - def enumValue(enumName: String, label: String) = label.toUpperCase + def enumValue(enumName: String, label: String) = Utils.upperUnderscoreCase(label) override def debugClassSequence(seq: List[AttrSpec]) = { //val seqStr = seq.map((attr) => "\"" + idToStr(attr.id) + "\"").mkString(", ") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/LuaCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/LuaCompiler.scala index d7c4179ab..2d08a9d25 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/LuaCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/LuaCompiler.scala @@ -1,7 +1,7 @@ package io.kaitai.struct.languages import io.kaitai.struct.{ClassTypeProvider, RuntimeConfig, Utils} -import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError} +import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError, NeedRaw} import io.kaitai.struct.datatype.DataType._ import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format._ @@ -161,9 +161,11 @@ class LuaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("end") } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { - if (needRaw) + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = {}") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = {}") out.puts(s"${privateMemberName(id)} = {}") out.puts("local i = 1") out.puts(s"while not $io:is_eof() do") @@ -175,9 +177,11 @@ class LuaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("end") } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: Ast.expr): Unit = { - if (needRaw) + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: Ast.expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = {}") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = {}") out.puts(s"${privateMemberName(id)} = {}") out.puts(s"for i = 1, ${expression(repeatExpr)} do") out.inc @@ -187,15 +191,17 @@ class LuaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("end") } - override def condRepeatUntilHeader(id: Identifier, io: String, datatype: DataType, needRaw: Boolean, repeatExpr: Ast.expr): Unit = { - if (needRaw) + override def condRepeatUntilHeader(id: Identifier, io: String, datatype: DataType, needRaw: NeedRaw, repeatExpr: Ast.expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = {}") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = {}") out.puts(s"${privateMemberName(id)} = {}") out.puts("local i = 1") out.puts("while true do") out.inc } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: Ast.expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: Ast.expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.puts(s"if ${expression(untilExpr)} then") out.inc @@ -208,17 +214,16 @@ class LuaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.dec } - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - proc match { + val expr = proc match { case ProcessXor(xorValue) => val procName = translator.detectType(xorValue) match { case _: IntType => "process_xor_one" case _: BytesType => "process_xor_many" } - out.puts(s"$destName = $kstreamName.$procName($srcName, ${expression(xorValue)})") + s"$kstreamName.$procName($srcExpr, ${expression(xorValue)})" case ProcessZlib => throw new RuntimeException("Lua zlib not supported") case ProcessRotate(isLeft, rotValue) => @@ -227,14 +232,24 @@ class LuaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) } else { s"8 - (${expression(rotValue)})" } - out.puts(s"$destName = $kstreamName.process_rotate_left($srcName, $expr, 1)") + s"$kstreamName.process_rotate_left($srcExpr, $expr, 1)" case ProcessCustom(name, args) => val procName = s"_process_${idToStr(varSrc)}" importList.add("require(\"" + s"${name.last}" + "\")") out.puts(s"local $procName = ${types2class(name)}(${args.map(expression).mkString(", ")})") - out.puts(s"$destName = $procName:decode($srcName)") + s"$procName:decode($srcExpr)" + } + handleAssignment(varDest, expr, rep, false) + } + + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case RepeatExpr(_) => s"$memberName[i]" + case _ => s"$memberName[#$memberName]" } } @@ -381,11 +396,7 @@ class LuaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def allocateIO(varName: Identifier, rep: RepeatSpec): String = { val varStr = privateMemberName(varName) - val args = rep match { - case RepeatEos | RepeatUntil(_) => s"$varStr[#$varStr]" - case RepeatExpr(_) => s"$varStr[i]" - case NoRepeat => varStr - } + val args = getRawIdExpr(varName, rep) importList.add("local stringstream = require(\"string_stream\")") out.puts(s"local _io = $kstreamName(stringstream($args))") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala index 0882cf448..0f9327046 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala @@ -1,7 +1,7 @@ package io.kaitai.struct.languages import io.kaitai.struct.datatype.DataType._ -import io.kaitai.struct.datatype.{CalcEndian, DataType, FixedEndian, InheritedEndian, KSError} +import io.kaitai.struct.datatype.{CalcEndian, DataType, FixedEndian, InheritedEndian, KSError, NeedRaw} import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format.{NoRepeat, RepeatEos, RepeatExpr, RepeatSpec, _} import io.kaitai.struct.languages.components._ @@ -140,7 +140,7 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def readHeader(endian: Option[FixedEndian], isEmpty: Boolean) = { val suffix = endian match { - case Some(e) => s"${e.toSuffix.toUpperCase}" + case Some(e) => Utils.upperUnderscoreCase(e.toSuffix) case None => "" } val access = if (config.autoRead) "private" else "public" @@ -188,34 +188,34 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def attrFixedContentsParse(attrName: Identifier, contents: String): Unit = out.puts(s"${privateMemberName(attrName)} = $normalIO->ensureFixedContents($contents);") - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - proc match { + val expr = proc match { case ProcessXor(xorValue) => val procName = translator.detectType(xorValue) match { case _: IntType => "processXorOne" case _: BytesType => "processXorMany" } - out.puts(s"$destName = $kstreamName::$procName($srcName, ${expression(xorValue)});") + s"$kstreamName::$procName($srcExpr, ${expression(xorValue)})" case ProcessZlib => - out.puts(s"$destName = $kstreamName::processZlib($srcName);") + s"$kstreamName::processZlib($srcExpr)" case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - out.puts(s"$destName = $kstreamName::processRotateLeft($srcName, $expr, 1);") + s"$kstreamName::processRotateLeft($srcExpr, $expr, 1)" case ProcessCustom(name, args) => val isAbsolute = name.length > 1 val procClass = name.map((x) => type2class(x)).mkString( if (isAbsolute) "\\" else "", "\\", "" ) out.puts(s"$$_process = new $procClass(${args.map(expression).mkString(", ")});") - out.puts(s"$destName = $$_process->decode($srcName);") + s"$$_process->decode($srcExpr)" } + handleAssignment(varDest, expr, rep, false) } override def allocateIO(id: Identifier, rep: RepeatSpec): String = { @@ -223,15 +223,22 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) val ioName = s"$$_io_${idToStr(id)}" val args = rep match { - case RepeatEos | RepeatExpr(_) => s"end($memberName)" case RepeatUntil(_) => translator.doLocalName(Identifier.ITERATOR2) - case NoRepeat => memberName + case _ => getRawIdExpr(id, rep) } out.puts(s"$ioName = new $kstreamName($args);") ioName } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case _ => s"end($memberName)" + } + } + override def useIO(ioEx: Ast.expr): String = { out.puts(s"$$io = ${expression(ioEx)};") "$io" @@ -254,9 +261,11 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { - if (needRaw) + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = [];") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [];") out.puts(s"${privateMemberName(id)} = [];") out.puts("$i = 0;") out.puts(s"while (!$io->isEof()) {") @@ -272,9 +281,11 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) super.condRepeatEosFooter } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: Ast.expr): Unit = { - if (needRaw) + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: Ast.expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = [];") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [];") out.puts(s"${privateMemberName(id)} = [];") out.puts(s"$$n = ${expression(repeatExpr)};") out.puts("for ($i = 0; $i < $n; $i++) {") @@ -285,9 +296,11 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)}[] = $expr;") } - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: Ast.expr): Unit = { - if (needRaw) + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: Ast.expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = [];") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [];") out.puts(s"${privateMemberName(id)} = [];") out.puts("$i = 0;") out.puts("do {") @@ -300,7 +313,7 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)}[] = $tmpName;") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: Ast.expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: Ast.expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.puts("$i++;") out.dec @@ -416,7 +429,7 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) classFooter(name) } - def value2Const(label: String) = label.toUpperCase + def value2Const(label: String) = Utils.upperUnderscoreCase(label) def idToStr(id: Identifier): String = { id match { diff --git a/shared/src/main/scala/io/kaitai/struct/languages/PerlCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/PerlCompiler.scala index ff908f74e..f8e2a389f 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/PerlCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/PerlCompiler.scala @@ -1,6 +1,6 @@ package io.kaitai.struct.languages -import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError} +import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError, NeedRaw} import io.kaitai.struct.datatype.DataType._ import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.exprlang.Ast.expr @@ -166,38 +166,36 @@ class PerlCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(attrName)} = $normalIO->ensure_fixed_contents($contents);") } - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - out.puts(proc match { + val expr = proc match { case ProcessXor(xorValue) => val procName = translator.detectType(xorValue) match { case _: IntType => "process_xor_one" case _: BytesType => "process_xor_many" } - s"$destName = $kstreamName::$procName($srcName, ${expression(xorValue)});" + s"$kstreamName::$procName($srcExpr, ${expression(xorValue)})" case ProcessZlib => importList.add("Compress::Zlib") - s"$destName = Compress::Zlib::uncompress($srcName);" + s"Compress::Zlib::uncompress($srcExpr)" case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - s"$destName = $kstreamName::process_rotate_left($srcName, $expr, 1);" - }) + s"$kstreamName::process_rotate_left($srcExpr, $expr, 1)" + } + handleAssignment(varDest, expr, rep, false) } override def allocateIO(id: Identifier, rep: RepeatSpec): String = { val memberName = privateMemberName(id) val args = rep match { - case RepeatEos => s"$memberName[-1]" - case RepeatExpr(_) => s"$memberName[$$i]" case RepeatUntil(_) => translator.doName(Identifier.ITERATOR2) - case NoRepeat => s"$memberName" + case _ => getRawIdExpr(id, rep) } val ioName = s"$$io_${idToStr(id)}" @@ -206,6 +204,15 @@ class PerlCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) ioName } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case RepeatExpr(_) => s"$memberName[$$i]" + case _ => s"$memberName[-1]" + } + } + override def useIO(ioEx: expr): String = { out.puts(s"my $$io = ${expression(ioEx)};") "$io" @@ -228,9 +235,11 @@ class PerlCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { - if (needRaw) + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = ();") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = ();") out.puts(s"${privateMemberName(id)} = ();") out.puts(s"while (!$io->is_eof()) {") out.inc @@ -239,9 +248,11 @@ class PerlCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def handleAssignmentRepeatEos(id: Identifier, expr: String): Unit = out.puts(s"push @{${privateMemberName(id)}}, $expr;") - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: expr): Unit = { - if (needRaw) + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = ();") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = ();") out.puts(s"${privateMemberName(id)} = ();") val nVar = s"$$n_${idToStr(id)}" out.puts(s"my $nVar = ${expression(repeatExpr)};") @@ -252,9 +263,11 @@ class PerlCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def handleAssignmentRepeatExpr(id: Identifier, expr: String): Unit = out.puts(s"${privateMemberName(id)}[$$i] = $expr;") - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { - if (needRaw) + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = ();") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = ();") out.puts(s"${privateMemberName(id)} = ();") out.puts("do {") out.inc @@ -270,7 +283,7 @@ class PerlCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"push @{${privateMemberName(id)}}, $tmpName;") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.dec out.puts(s"} until (${expression(untilExpr)});") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/PythonCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/PythonCompiler.scala index 6a8706ac0..cd09385d7 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/PythonCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/PythonCompiler.scala @@ -1,7 +1,7 @@ package io.kaitai.struct.languages import io.kaitai.struct.datatype.DataType._ -import io.kaitai.struct.datatype.{DataType, EndOfStreamError, FixedEndian, InheritedEndian, KSError, UndecidedEndiannessError} +import io.kaitai.struct.datatype.{DataType, EndOfStreamError, FixedEndian, InheritedEndian, KSError, UndecidedEndiannessError, NeedRaw} import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.exprlang.Ast.expr import io.kaitai.struct.format._ @@ -181,27 +181,26 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.dec } - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - proc match { + val expr = proc match { case ProcessXor(xorValue) => val procName = translator.detectType(xorValue) match { case _: IntType => "process_xor_one" case _: BytesType => "process_xor_many" } - out.puts(s"$destName = $kstreamName.$procName($srcName, ${expression(xorValue)})") + s"$kstreamName.$procName($srcExpr, ${expression(xorValue)})" case ProcessZlib => importList.add("import zlib") - out.puts(s"$destName = zlib.decompress($srcName)") + s"zlib.decompress($srcExpr)" case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - out.puts(s"$destName = $kstreamName.process_rotate_left($srcName, $expr, 1)") + s"$kstreamName.process_rotate_left($srcExpr, $expr, 1)" case ProcessCustom(name, args) => val procClass = if (name.length == 1) { val onlyName = name.head @@ -215,8 +214,9 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) } out.puts(s"_process = $procClass(${args.map(expression).mkString(", ")})") - out.puts(s"$destName = _process.decode($srcName)") + s"_process.decode($srcExpr)" } + handleAssignment(varDest, expr, rep, false) } override def normalIO: String = "self._io" @@ -225,16 +225,21 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) val varStr = privateMemberName(varName) val ioName = s"_io_${idToStr(varName)}" - val args = rep match { - case RepeatEos | RepeatUntil(_) => s"$varStr[-1]" - case RepeatExpr(_) => s"$varStr[i]" - case NoRepeat => varStr - } + val args = getRawIdExpr(varName, rep) out.puts(s"$ioName = $kstreamName(BytesIO($args))") ioName } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case RepeatExpr(_) => s"$memberName[i]" + case _ => s"$memberName[-1]" + } + } + override def useIO(ioEx: expr): String = { out.puts(s"io = ${expression(ioEx)}") "io" @@ -291,9 +296,11 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { - if (needRaw) + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = []") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = []") out.puts(s"${privateMemberName(id)} = []") out.puts("i = 0") out.puts(s"while not $io.is_eof():") @@ -306,9 +313,11 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) universalFooter } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: expr): Unit = { - if (needRaw) + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = [None] * (${expression(repeatExpr)})") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [None] * (${expression(repeatExpr)})") out.puts(s"${privateMemberName(id)} = [None] * (${expression(repeatExpr)})") out.puts(s"for i in range(${expression(repeatExpr)}):") out.inc @@ -316,9 +325,11 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def handleAssignmentRepeatExpr(id: Identifier, expr: String): Unit = out.puts(s"${privateMemberName(id)}[i] = $expr") - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { - if (needRaw) + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = []") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = []") out.puts(s"${privateMemberName(id)} = []") out.puts("i = 0") out.puts("while True:") @@ -331,7 +342,7 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)}.append($tmpName)") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.puts(s"if ${expression(untilExpr)}:") out.inc diff --git a/shared/src/main/scala/io/kaitai/struct/languages/RubyCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/RubyCompiler.scala index 15072a311..bfce51217 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/RubyCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/RubyCompiler.scala @@ -177,48 +177,53 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def attrFixedContentsParse(attrName: Identifier, contents: String): Unit = out.puts(s"${privateMemberName(attrName)} = $normalIO.ensure_fixed_contents($contents)") - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - out.puts(proc match { + val expr = proc match { case ProcessXor(xorValue) => val procName = translator.detectType(xorValue) match { case _: IntType => "process_xor_one" case _: BytesType => "process_xor_many" } - s"$destName = $kstreamName::$procName($srcName, ${expression(xorValue)})" + s"$kstreamName::$procName($srcExpr, ${expression(xorValue)})" case ProcessZlib => importList.add("zlib") - s"$destName = Zlib::Inflate.inflate($srcName)" + s"Zlib::Inflate.inflate($srcExpr)" case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - s"$destName = $kstreamName::process_rotate_left($srcName, $expr, 1)" + s"$kstreamName::process_rotate_left($srcExpr, $expr, 1)" case ProcessCustom(name, args) => val procClass = name.map((x) => type2class(x)).mkString("::") out.puts(s"_process = $procClass.new(${args.map(expression).mkString(", ")})") - s"$destName = _process.decode($srcName)" - }) + s"_process.decode($srcExpr)" + } + handleAssignment(varDest, expr, rep, false) } override def allocateIO(id: Identifier, rep: RepeatSpec): String = { val memberName = privateMemberName(id) val ioName = s"_io_${idToStr(id)}" - val args = rep match { - case RepeatEos | RepeatUntil(_) => s"$memberName.last" - case RepeatExpr(_) => s"$memberName[i]" - case NoRepeat => s"$memberName" - } + val args = getRawIdExpr(id, rep) out.puts(s"$ioName = $kstreamName.new($args)") ioName } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case RepeatExpr(_) => s"$memberName[i]" + case _ => s"$memberName.last" + } + } + override def useIO(ioEx: expr): String = { out.puts(s"io = ${expression(ioEx)}") "io" @@ -273,9 +278,11 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { - if (needRaw) + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = []") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = []") out.puts(s"${privateMemberName(id)} = []") out.puts("i = 0") @@ -289,9 +296,11 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) super.condRepeatEosFooter } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: expr): Unit = { - if (needRaw) + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = Array.new(${expression(repeatExpr)})") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = Array.new(${expression(repeatExpr)})") out.puts(s"${privateMemberName(id)} = Array.new(${expression(repeatExpr)})") out.puts(s"(${expression(repeatExpr)}).times { |i|") out.inc @@ -303,9 +312,11 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("}") } - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { - if (needRaw) + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = []") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = []") out.puts(s"${privateMemberName(id)} = []") out.puts("i = 0") out.puts("begin") @@ -318,7 +329,7 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)} << $tmpName") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.puts("i += 1") out.dec @@ -430,7 +441,7 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) def enumValue(enumName: String, enumLabel: String) = translator.doEnumByLabel(List(enumName), enumLabel) - def value2Const(s: String) = s.toUpperCase + def value2Const(s: String) = Utils.upperUnderscoreCase(s) override def debugClassSequence(seq: List[AttrSpec]) = { val seqStr = seq.map((attr) => "\"" + idToStr(attr.id) + "\"").mkString(", ") @@ -439,11 +450,11 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def idToStr(id: Identifier): String = { id match { - case NamedIdentifier(name) => name + case NamedIdentifier(name) => Utils.lowerUnderscoreCase(name) case NumberedIdentifier(idx) => s"_${NumberedIdentifier.TEMPLATE}$idx" case si: SpecialIdentifier => si.name case RawIdentifier(inner) => s"_raw_${idToStr(inner)}" - case InstanceIdentifier(name) => name + case InstanceIdentifier(name) => Utils.lowerUnderscoreCase(name) } } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/RustCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/RustCompiler.scala index 37f670aae..18fef1c1c 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/RustCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/RustCompiler.scala @@ -1,7 +1,7 @@ package io.kaitai.struct.languages import io.kaitai.struct.datatype.DataType._ -import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError} +import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError, NeedRaw} import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format.{NoRepeat, RepeatEos, RepeatExpr, RepeatSpec, _} import io.kaitai.struct.languages.components._ @@ -146,7 +146,6 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) } override def attributeReader(attr: MemberSpec, index: Int, isNullable: Boolean): Unit = { - } override def universalDoc(doc: DocSpec): Unit = { @@ -173,26 +172,25 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def attrFixedContentsParse(attrName: Identifier, contents: String): Unit = out.puts(s"${privateMemberName(attrName)} = $normalIO.ensureFixedContents($contents);") - override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit = { - val srcName = privateMemberName(varSrc) - val destName = privateMemberName(varDest) + override def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit = { + val srcExpr = getRawIdExpr(varSrc, rep) - proc match { + val expr = proc match { case ProcessXor(xorValue) => val procName = translator.detectType(xorValue) match { case _: IntType => "processXorOne" case _: BytesType => "processXorMany" } - out.puts(s"$destName = $kstreamName::$procName($srcName, ${expression(xorValue)});") + s"$kstreamName::$procName($srcExpr, ${expression(xorValue)})" case ProcessZlib => - out.puts(s"$destName = $kstreamName::processZlib($srcName);") + s"$kstreamName::processZlib($srcExpr);" case ProcessRotate(isLeft, rotValue) => val expr = if (isLeft) { expression(rotValue) } else { s"8 - (${expression(rotValue)})" } - out.puts(s"$destName = $kstreamName::processRotateLeft($srcName, $expr, 1);") + s"$kstreamName::processRotateLeft($srcExpr, $expr, 1)" case ProcessCustom(name, args) => val procClass = if (name.length == 1) { val onlyName = name.head @@ -207,23 +205,31 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) } out.puts(s"let _process = $procClass::new(${args.map(expression).mkString(", ")});") - out.puts(s"$destName = _process.decode($srcName);") + s"_process.decode($srcExpr)" } + handleAssignment(varDest, expr, rep, false) } override def allocateIO(id: Identifier, rep: RepeatSpec): String = { val memberName = privateMemberName(id) val args = rep match { - case RepeatEos | RepeatExpr(_) => s"$memberName.last()" case RepeatUntil(_) => translator.doLocalName(Identifier.ITERATOR2) - case NoRepeat => memberName + case _ => getRawIdExpr(id, rep) } out.puts(s"let mut io = Cursor::new($args);") "io" } + def getRawIdExpr(varName: Identifier, rep: RepeatSpec): String = { + val memberName = privateMemberName(varName) + rep match { + case NoRepeat => memberName + case _ => s"$memberName.last()" + } + } + override def useIO(ioEx: Ast.expr): String = { out.puts(s"let mut io = ${expression(ioEx)};") "io" @@ -246,9 +252,11 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit = { - if (needRaw) + override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = [];") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [];") out.puts(s"${privateMemberName(id)} = [];") out.puts(s"while !$io.isEof() {") out.inc @@ -262,9 +270,11 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) super.condRepeatEosFooter } - override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: Ast.expr): Unit = { - if (needRaw) + override def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: Ast.expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = vec!();") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = vec!();") out.puts(s"${privateMemberName(id)} = vec!();") out.puts(s"for i in 0..${expression(repeatExpr)} {") out.inc @@ -274,9 +284,11 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)}.push($expr);") } - override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: Ast.expr): Unit = { - if (needRaw) + override def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: Ast.expr): Unit = { + if (needRaw.level >= 1) out.puts(s"${privateMemberName(RawIdentifier(id))} = vec!();") + if (needRaw.level >= 2) + out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = vec!();") out.puts(s"${privateMemberName(id)} = vec!();") out.puts("while {") out.inc @@ -292,7 +304,7 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts(s"${privateMemberName(id)}.append($expr);") } - override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, untilExpr: Ast.expr): Unit = { + override def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, untilExpr: Ast.expr): Unit = { typeProvider._currentIteratorType = Some(dataType) out.puts(s"!(${expression(untilExpr)})") out.dec @@ -468,7 +480,7 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("}") } - def value2Const(label: String) = label.toUpperCase + def value2Const(label: String) = Utils.upperUnderscoreCase(label) def idToStr(id: Identifier): String = { id match { diff --git a/shared/src/main/scala/io/kaitai/struct/languages/components/CommonReads.scala b/shared/src/main/scala/io/kaitai/struct/languages/components/CommonReads.scala index 8a35f33e1..ed36b47d7 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/components/CommonReads.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/components/CommonReads.scala @@ -1,7 +1,7 @@ package io.kaitai.struct.languages.components import io.kaitai.struct.datatype._ -import io.kaitai.struct.datatype.DataType.{SwitchType, UserTypeFromBytes} +import io.kaitai.struct.datatype.DataType.{SwitchType, UserTypeFromBytes, BytesType} import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format._ @@ -83,12 +83,23 @@ 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 needRaw(dataType: DataType): Boolean = { - dataType match { + def needRaw(dataType: DataType): NeedRaw = { + val rawIo = dataType match { case _: UserTypeFromBytes => true case st: SwitchType => st.hasSize case _ => false } + val rawProcess = dataType match { + case bt: BytesType => bt.process.nonEmpty + case utfb: UserTypeFromBytes => utfb.bytes.process.nonEmpty + case _ => false + } + (rawIo, rawProcess) match { + case (true, false) => RawIo + case (false, true) => RawProcess + case (true, true) => RawIoProcess + case _ => NotRaw + } } def attrDebugStart(attrName: Identifier, attrType: DataType, io: Option[String], repeat: RepeatSpec): Unit = {} diff --git a/shared/src/main/scala/io/kaitai/struct/languages/components/EveryReadIsExpression.scala b/shared/src/main/scala/io/kaitai/struct/languages/components/EveryReadIsExpression.scala index af5217d74..a28493e59 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/components/EveryReadIsExpression.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/components/EveryReadIsExpression.scala @@ -80,7 +80,7 @@ trait EveryReadIsExpression handleAssignment(rawId, expr, rep, isRaw) // apply post-processing - dataType.process.foreach((proc) => attrProcess(proc, rawId, id)) + dataType.process.foreach((proc) => attrProcess(proc, rawId, id, rep)) } def parseExprBytes(dataType: BytesType, io: String): String = { diff --git a/shared/src/main/scala/io/kaitai/struct/languages/components/GoReads.scala b/shared/src/main/scala/io/kaitai/struct/languages/components/GoReads.scala index 35c03aabf..c4e1bf90d 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/components/GoReads.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/components/GoReads.scala @@ -22,7 +22,7 @@ trait GoReads extends CommonReads with ObjectOrientedLanguage with GoSwitchOps { } val expr = parseExprBytes(translator.outVarCheckRes(parseExpr(dataType, io, None)), dataType) handleAssignment(rawId, expr, rep, isRaw) - dataType.process.foreach((proc) => attrProcess(proc, rawId, id)) + dataType.process.foreach((proc) => attrProcess(proc, rawId, id, rep)) } def attrSwitchTypeParse( diff --git a/shared/src/main/scala/io/kaitai/struct/languages/components/LanguageCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/components/LanguageCompiler.scala index 4769fe04b..61a614bf3 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/components/LanguageCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/components/LanguageCompiler.scala @@ -1,6 +1,6 @@ package io.kaitai.struct.languages.components -import io.kaitai.struct.datatype.{DataType, Endianness, FixedEndian, InheritedEndian} +import io.kaitai.struct.datatype.{DataType, Endianness, FixedEndian, InheritedEndian, NeedRaw} import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format._ import io.kaitai.struct.translators.AbstractTranslator @@ -103,16 +103,16 @@ abstract class LanguageCompiler( def condIfHeader(expr: Ast.expr): Unit def condIfFooter(expr: Ast.expr): Unit - def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean): Unit + def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw): Unit def condRepeatEosFooter: Unit - def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: Ast.expr): Unit + def condRepeatExprHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: Ast.expr): Unit def condRepeatExprFooter: Unit - def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: Ast.expr): Unit - def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: Boolean, repeatExpr: Ast.expr): Unit + def condRepeatUntilHeader(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: Ast.expr): Unit + def condRepeatUntilFooter(id: Identifier, io: String, dataType: DataType, needRaw: NeedRaw, repeatExpr: Ast.expr): Unit - def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier): Unit + def attrProcess(proc: ProcessExpr, varSrc: Identifier, varDest: Identifier, rep: RepeatSpec): Unit def normalIO: String def useIO(ioEx: Ast.expr): String diff --git a/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala index c01338bdb..43534c8c3 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala @@ -106,8 +106,15 @@ class CppTranslator(provider: TypeProvider, importListSrc: CppImportList, import override def doArrayLiteral(t: DataType, values: Seq[expr]): String = { if (config.cppConfig.useListInitializers) { importListHdr.addSystem("vector") - s"std::vector<${CppCompiler.kaitaiType2NativeType(config.cppConfig, t)}>" + - "{" + values.map((value) => translate(value)).mkString(", ") + "}" + val cppElType = CppCompiler.kaitaiType2NativeType(config.cppConfig, t) + val rawInit = s"new std::vector<$cppElType>{" + values.map((value) => translate(value)).mkString(", ") + "}" + config.cppConfig.pointers match { + case RawPointers => + rawInit + case UniqueAndRawPointers => + s"std::unique_ptr>($rawInit)" + // TODO: C++14 + } } else { throw new RuntimeException("C++ literal arrays are not implemented yet") } @@ -137,7 +144,7 @@ class CppTranslator(provider: TypeProvider, importListSrc: CppImportList, import override def doEnumByLabel(enumType: List[String], label: String): String = CppCompiler.types2class(enumType.dropRight(1)) + "::" + - (enumType.last + "_" + label).toUpperCase + Utils.upperUnderscoreCase(enumType.last + "_" + label) override def doEnumById(enumType: List[String], id: String): String = s"static_cast<${CppCompiler.types2class(enumType)}>($id)" diff --git a/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala index 2edc6b646..d6ffd9289 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala @@ -54,7 +54,7 @@ class JavaScriptTranslator(provider: TypeProvider) extends BaseTranslator(provid } override def doEnumByLabel(enumType: List[String], label: String): String = - s"${JavaScriptCompiler.types2class(enumType)}.${label.toUpperCase}" + s"${JavaScriptCompiler.types2class(enumType)}.${Utils.upperUnderscoreCase(label)}" override def doEnumById(enumTypeAbs: List[String], label: String): String = // Just an integer, without any casts / resolutions - one would have to look up constants manually label diff --git a/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala index d75c7274e..07c880692 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala @@ -56,7 +56,7 @@ class JavaTranslator(provider: TypeProvider, importList: ImportList) extends Bas } override def doEnumByLabel(enumTypeAbs: List[String], label: String): String = - s"${enumClass(enumTypeAbs)}.${label.toUpperCase}" + s"${enumClass(enumTypeAbs)}.${Utils.upperUnderscoreCase(label)}" override def doEnumById(enumTypeAbs: List[String], id: String): String = s"${enumClass(enumTypeAbs)}.byId($id)" diff --git a/shared/src/main/scala/io/kaitai/struct/translators/PHPTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/PHPTranslator.scala index b92397979..01094aa5a 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/PHPTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/PHPTranslator.scala @@ -59,7 +59,7 @@ class PHPTranslator(provider: TypeProvider, config: RuntimeConfig) extends BaseT override def doEnumByLabel(enumTypeAbs: List[String], label: String): String = { val enumClass = types2classAbs(enumTypeAbs) - s"$enumClass::${label.toUpperCase}" + s"$enumClass::${Utils.upperUnderscoreCase(label)}" } override def doEnumById(enumTypeAbs: List[String], id: String) = // Just an integer, without any casts / resolutions - one would have to look up constants manually diff --git a/shared/src/main/scala/io/kaitai/struct/translators/PerlTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/PerlTranslator.scala index cf705dc5a..3a20a5310 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/PerlTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/PerlTranslator.scala @@ -76,8 +76,8 @@ class PerlTranslator(provider: TypeProvider, importList: ImportList) extends Bas override def doEnumByLabel(enumType: List[String], label: String): String = { val enumClass = PerlCompiler.types2class(enumType.init) val enumClassWithScope = if (enumClass.isEmpty) "" else s"$enumClass::" - val enumName = enumType.last.toUpperCase - s"$$$enumClassWithScope${enumName}_${label.toUpperCase}" + val enumName = Utils.upperUnderscoreCase(enumType.last) + s"$$$enumClassWithScope${enumName}_${Utils.upperUnderscoreCase(label)}" } override def doEnumById(enumTypeAbs: List[String], id: String): String = // Just an integer, without any casts / resolutions - one would have to look up constants manually diff --git a/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala index 7f320d90a..e1d8fb7b5 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala @@ -44,7 +44,7 @@ class RubyTranslator(provider: TypeProvider) extends BaseTranslator(provider) def enumDirectMap(enumTypeAndName: List[String]): String = { val enumTypeAbs = enumTypeAndName.dropRight(1) - val enumTypeName = enumTypeAndName.last.toUpperCase + val enumTypeName = Utils.upperUnderscoreCase(enumTypeAndName.last) val enumTypeRel = Utils.relClass(enumTypeAbs, provider.nowClass.name) @@ -58,7 +58,7 @@ class RubyTranslator(provider: TypeProvider) extends BaseTranslator(provider) def enumInverseMap(et: EnumType): String = { val enumTypeAndName = et.enumSpec.get.name val enumDirectMap = this.enumDirectMap(enumTypeAndName) - val enumNameDirect = enumTypeAndName.last.toUpperCase + val enumNameDirect = Utils.upperUnderscoreCase(enumTypeAndName.last) val enumNameInverse = RubyCompiler.inverseEnumName(enumNameDirect) enumDirectMap.replace(enumNameDirect, enumNameInverse) diff --git a/shared/src/main/scala/io/kaitai/struct/translators/RustTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/RustTranslator.scala index 7e824a76c..252f7cf08 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/RustTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/RustTranslator.scala @@ -50,7 +50,7 @@ class RustTranslator(provider: TypeProvider, config: RuntimeConfig) extends Base override def doEnumByLabel(enumTypeAbs: List[String], label: String): String = { val enumClass = types2classAbs(enumTypeAbs) - s"$enumClass::${label.toUpperCase}" + s"$enumClass::${Utils.upperUnderscoreCase(label)}" } override def doEnumById(enumTypeAbs: List[String], id: String) = // Just an integer, without any casts / resolutions - one would have to look up constants manually @@ -72,7 +72,7 @@ class RustTranslator(provider: TypeProvider, config: RuntimeConfig) extends Base case "10" => s"${translate(s)}.parse().unwrap()" case _ => - "panic!(\"Converting from string to int in base {} is unimplemented\"" + translate(base) + ")" + "panic!(\"Converting from string to int in base {} is unimplemented\", " + translate(base) + ")" } override def enumToInt(v: expr, et: EnumType): String =