Open-source multiplayer game server compatible with the RuneScape client https://www.openrs2.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
openrs2/deob-ast/src/main/kotlin/org/openrs2/deob/ast/transform/CharLiteralTransformer.kt

95 lines
3.3 KiB

package org.openrs2.deob.ast.transform
import com.github.javaparser.ast.CompilationUnit
import com.github.javaparser.ast.expr.AssignExpr
import com.github.javaparser.ast.expr.BinaryExpr
import com.github.javaparser.ast.expr.BinaryExpr.Operator.EQUALS
import com.github.javaparser.ast.expr.BinaryExpr.Operator.GREATER
import com.github.javaparser.ast.expr.BinaryExpr.Operator.GREATER_EQUALS
import com.github.javaparser.ast.expr.BinaryExpr.Operator.LESS
import com.github.javaparser.ast.expr.BinaryExpr.Operator.LESS_EQUALS
import com.github.javaparser.ast.expr.BinaryExpr.Operator.NOT_EQUALS
import com.github.javaparser.ast.expr.CharLiteralExpr
import com.github.javaparser.ast.expr.Expression
import com.github.javaparser.ast.expr.IntegerLiteralExpr
import com.github.javaparser.ast.expr.UnaryExpr
import com.github.javaparser.resolution.types.ResolvedPrimitiveType
import org.openrs2.deob.ast.Library
import org.openrs2.deob.ast.LibraryGroup
import org.openrs2.deob.ast.util.checkedAsInt
import org.openrs2.deob.ast.util.walk
import java.lang.Character.CONTROL
import java.lang.Character.FORMAT
import java.lang.Character.LINE_SEPARATOR
import java.lang.Character.PARAGRAPH_SEPARATOR
import java.lang.Character.PRIVATE_USE
import java.lang.Character.SURROGATE
import java.lang.Character.UNASSIGNED
import javax.inject.Singleton
@Singleton
public class CharLiteralTransformer : Transformer() {
override fun transformUnit(group: LibraryGroup, library: Library, unit: CompilationUnit) {
unit.walk { expr: BinaryExpr ->
if (expr.operator in COMPARISON_OPERATORS) {
convertToCharLiteral(expr.left, expr.right)
convertToCharLiteral(expr.right, expr.left)
}
}
unit.walk { expr: AssignExpr ->
convertToCharLiteral(expr.target, expr.value)
}
}
private fun convertToCharLiteral(a: Expression, b: Expression) {
if (b !is IntegerLiteralExpr) {
return
} else if (a.calculateResolvedType() != ResolvedPrimitiveType.CHAR) {
return
}
val n = b.checkedAsInt()
if (n < 0) {
val char = (-n).toChar()
b.replace(UnaryExpr(CharLiteralExpr(escape(char)), UnaryExpr.Operator.MINUS))
} else {
val char = n.toChar()
b.replace(CharLiteralExpr(escape(char)))
}
}
private fun escape(c: Char): String {
// compatible with Fernflower's character escape code
return when (c) {
'\b' -> "\\b"
'\t' -> "\\t"
'\n' -> "\\n"
'\u000c' -> "\\f"
'r' -> "\\r"
'\'' -> "'"
'\\' -> "\\"
else -> {
val type = Character.getType(c).toByte()
if (type in UNPRINTABLE_TYPES) {
"\\u" + Integer.toHexString(c.code).padStart(4, '0')
} else {
c.toString()
}
}
}
}
private companion object {
private val COMPARISON_OPERATORS = setOf(EQUALS, NOT_EQUALS, LESS, GREATER, LESS_EQUALS, GREATER_EQUALS)
private val UNPRINTABLE_TYPES = setOf(
UNASSIGNED,
LINE_SEPARATOR,
PARAGRAPH_SEPARATOR,
CONTROL,
FORMAT,
PRIVATE_USE,
SURROGATE
)
}
}