-
Notifications
You must be signed in to change notification settings - Fork 584
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix issue #5: retains referenced symbols
- Loading branch information
1 parent
e04cc6a
commit da9aec8
Showing
16 changed files
with
1,453 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
apply from: '../gradle/booster.gradle' |
196 changes: 196 additions & 0 deletions
196
booster-aapt/src/main/kotlin/com/didiglobal/booster/aapt/parser/BinaryParser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
package com.didiglobal.booster.aapt.parser | ||
|
||
import java.io.Closeable | ||
import java.io.File | ||
import java.io.InputStream | ||
import java.nio.ByteBuffer | ||
import java.nio.ByteOrder | ||
import java.nio.channels.FileChannel | ||
import java.nio.file.StandardOpenOption | ||
|
||
/** | ||
* Represents a binary data parser | ||
* | ||
* @author johnsonlee | ||
*/ | ||
class BinaryParser : Closeable { | ||
|
||
private val _buffer: ByteBuffer | ||
|
||
private val _channel: FileChannel? | ||
|
||
/** | ||
* Initialize with the specified buffer | ||
* | ||
* @param buffer the buffer to parse | ||
*/ | ||
constructor(buffer: ByteBuffer) { | ||
_buffer = buffer | ||
_channel = null | ||
} | ||
|
||
/** | ||
* Initialize with the specified file and byte order | ||
* | ||
* @param file the file to parse | ||
* @param order the byte order, default is *little endian* | ||
*/ | ||
constructor(file: File, order: ByteOrder = ByteOrder.LITTLE_ENDIAN) { | ||
_channel = FileChannel.open(file.toPath(), StandardOpenOption.READ) | ||
_buffer = _channel.map(FileChannel.MapMode.READ_ONLY, 0, file.length()).order(order) | ||
} | ||
|
||
/** | ||
* Initialize with the specified input stream and byte order | ||
* | ||
* @param input the input stream to parse | ||
* @param order the byte order, default is *little endian* | ||
*/ | ||
constructor(input: InputStream, order: ByteOrder = ByteOrder.LITTLE_ENDIAN) : this(ByteBuffer.wrap(input.readBytes()).order(order)) | ||
|
||
/** | ||
* The internal buffer | ||
*/ | ||
internal val buffer: ByteBuffer | ||
get() = _buffer | ||
|
||
/** | ||
* The capacity of buffer | ||
*/ | ||
val capacity: Int | ||
get() = _buffer.capacity() | ||
|
||
/** | ||
* The remaining size of buffer | ||
*/ | ||
val remaining: Int | ||
get() = _buffer.remaining() | ||
|
||
/** | ||
* Tells whether there are any elements between the current position and the limit. | ||
*/ | ||
val hasRemaining: Boolean | ||
get() = _buffer.hasRemaining() | ||
|
||
/** | ||
* Parses the remaining data in buffer as the specified type | ||
* | ||
* @param handler the handler for remaining data parsing | ||
*/ | ||
fun <T> parse(handler: (ByteBuffer) -> T): T { | ||
return handler(_buffer) | ||
} | ||
|
||
/** | ||
* Returns the next byte | ||
*/ | ||
fun readByte() = _buffer.get() | ||
|
||
/** | ||
* Returns a byte value at the specified index | ||
*/ | ||
fun getByte(index: Int) = _buffer.get(index) | ||
|
||
/** | ||
* Returns the next short | ||
*/ | ||
fun readShort() = _buffer.short | ||
|
||
/** | ||
* Returns a short value at the specified index | ||
*/ | ||
fun getShort(index: Int) = _buffer.getShort(index) | ||
|
||
fun readChar() = _buffer.char | ||
|
||
fun getChar(index: Int) = _buffer.getChar(index) | ||
|
||
fun readInt() = _buffer.int | ||
|
||
fun getInt(index: Int) = _buffer.getInt(index) | ||
|
||
fun readLong() = _buffer.long | ||
|
||
fun getLong(index: Int) = _buffer.getLong(index) | ||
|
||
fun readBytes(size: Int) = ByteArray(size).also { | ||
_buffer.get(it) | ||
} | ||
|
||
fun getBytes(size: Int, index: Int): ByteArray { | ||
val p = tell() | ||
|
||
try { | ||
seek(index) | ||
return readBytes(size) | ||
} finally { | ||
seek(p) | ||
} | ||
} | ||
|
||
fun readUByte() = _buffer.get().toInt() and 0xff | ||
|
||
fun readUShort() = _buffer.short.toInt() and 0xffff | ||
|
||
fun readUInt() = _buffer.int | ||
|
||
fun getUByte(index: Int) = _buffer.get(index).toInt() and 0xff | ||
|
||
fun getUShort(index: Int) = _buffer.getShort(index).toInt() and 0xffff | ||
|
||
fun getUInt(index: Int) = _buffer.getInt(index) | ||
|
||
fun readUleb128(): Int { | ||
var result = 0 | ||
var count = 0 | ||
var cur: Int | ||
|
||
do { | ||
cur = _buffer.get().toInt() and 0xff | ||
result = result or (cur and 0x7f shl count * 7) | ||
count++ | ||
} while (cur and 0x80 == 0x80 && count < 5) | ||
|
||
if (cur and 0x80 == 0x80) { | ||
throw RuntimeException("Invalid LEB128 sequence") | ||
} | ||
|
||
return result | ||
} | ||
|
||
fun readSleb128(): Int { | ||
var result = 0 | ||
var cur: Int | ||
var count = 0 | ||
var signBits = -1 | ||
|
||
do { | ||
cur = readByte().toInt() and 0xff | ||
result = result or (cur and 0x7f shl count * 7) | ||
signBits = signBits shl 7 | ||
count++ | ||
} while (cur and 0x80 == 0x80 && count < 5) | ||
|
||
if (cur and 0x80 == 0x80) { | ||
throw RuntimeException("Invalid LEB128 sequence") | ||
} | ||
|
||
// Sign extend if appropriate | ||
if (signBits shr 1 and result != 0) { | ||
result = result or signBits | ||
} | ||
|
||
return result | ||
} | ||
|
||
fun skip(n: Int) = _buffer.position(_buffer.position() + n) | ||
|
||
fun seek(pos: Int) = _buffer.position(pos) | ||
|
||
fun tell() = _buffer.position() | ||
|
||
override fun close() { | ||
_channel?.close() | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
buildscript { | ||
repositories { | ||
google() | ||
mavenCentral() | ||
jcenter() | ||
} | ||
dependencies { | ||
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8' | ||
} | ||
} | ||
|
||
apply from: '../gradle/booster.gradle' | ||
apply plugin: 'com.google.protobuf' | ||
|
||
sourceSets { | ||
main { | ||
proto { | ||
srcDirs += ['src/main/proto'] | ||
} | ||
} | ||
test { | ||
proto { | ||
srcDirs += ['src/main/proto'] | ||
} | ||
} | ||
} | ||
|
||
dependencies { | ||
compile 'com.google.protobuf:protobuf-java:3.7.0-rc1' | ||
compile project(':booster-aapt') | ||
} |
39 changes: 39 additions & 0 deletions
39
booster-aapt2/src/main/kotlin/com/didiglobal/booster/aapt2/Aapt2Container.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.didiglobal.booster.aapt2 | ||
|
||
import android.aapt.pb.internal.ResourcesInternal | ||
import com.android.aapt.Resources | ||
import java.lang.RuntimeException | ||
|
||
import java.nio.ByteBuffer | ||
|
||
/** | ||
* Represents the AAPT2 container | ||
*/ | ||
class Aapt2Container(magic: Int = MAGIC, val version: Int, private vararg val _entries: Entry<Any>) { | ||
|
||
abstract class Entry<T>(val type: Int, val data: T) | ||
|
||
open class ResTableEntry(data: Resources.ResourceTable) : Entry<Resources.ResourceTable>(RES_TABLE, data) | ||
|
||
open class ResFileEntry(data: ResourcesInternal.CompiledFile) : Entry<ResourcesInternal.CompiledFile>(RES_FILE, data) | ||
|
||
open class PngEntry(header: ResourcesInternal.CompiledFile, val image: ByteBuffer) : ResFileEntry(header) | ||
|
||
open class XmlEntry(file: ResourcesInternal.CompiledFile, val xml: Resources.XmlNode): ResFileEntry(file) | ||
|
||
init { | ||
if (magic != MAGIC) { | ||
throw RuntimeException("Invalid aapt2 container") | ||
} | ||
} | ||
|
||
val entries: List<Entry<Any>> | ||
get() = listOf(*_entries) | ||
|
||
} | ||
|
||
const val MAGIC = 0x54504141 | ||
|
||
const val RES_TABLE = 0 | ||
|
||
const val RES_FILE = 1 |
Oops, something went wrong.