Skip to content

Commit

Permalink
Merge branch 'master' into annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
GreyCat authored Mar 8, 2020
2 parents 834a4ad + 185fac8 commit 329e242
Show file tree
Hide file tree
Showing 27 changed files with 550 additions and 252 deletions.
5 changes: 5 additions & 0 deletions js/src/main/scala/io/kaitai/struct/Platform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.kaitai.struct

object Platform {
def toUpperLocaleInsensitive(s: String) = s.toUpperCase()
}
7 changes: 7 additions & 0 deletions jvm/src/main/scala/io/kaitai/struct/Platform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.kaitai.struct

import java.util.Locale

object Platform {
def toUpperLocaleInsensitive(s: String) = s.toUpperCase(Locale.ROOT)
}
83 changes: 83 additions & 0 deletions jvm/src/test/scala/io/kaitai/struct/UtilsSpec.scala
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
}
26 changes: 26 additions & 0 deletions shared/src/main/scala/io/kaitai/struct/Utils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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))
Expand Down
18 changes: 18 additions & 0 deletions shared/src/main/scala/io/kaitai/struct/datatype/NeedRaw.scala
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()")
Expand Down Expand Up @@ -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 = {
Expand All @@ -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"
Expand Down Expand Up @@ -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<byte[]>();")
if (needRaw.level >= 2)
out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new List<byte[]>();")

out.puts(s"${privateMemberName(id)} = new ${kaitaiType2NativeType(ArrayTypeInStream(dataType))}();")
out.puts("{")
out.inc
Expand All @@ -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<byte[]>((int) (${expression(repeatExpr)}));")
if (needRaw.level >= 2)
out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new List<byte[]>((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("{")
Expand All @@ -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<byte[]>();")
if (needRaw.level >= 2)
out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new List<byte[]>();")
out.puts(s"${privateMemberName(id)} = new ${kaitaiType2NativeType(ArrayTypeInStream(dataType))}();")
out.puts("{")
out.inc
Expand All @@ -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
Expand Down Expand Up @@ -664,6 +678,4 @@ object CSharpCompiler extends LanguageCompilerStatic
case EndOfStreamError => "EndOfStreamException"
case _ => err.name
}

override def type2class(name: String): String = Utils.upperCamelCase(name)
}
Loading

0 comments on commit 329e242

Please sign in to comment.