Skip to content

Instantly share code, notes, and snippets.

@cypherdare
Created February 1, 2020 16:10
Show Gist options
  • Save cypherdare/4ef04c4e292fbe1e610a4ad5e1108164 to your computer and use it in GitHub Desktop.
Save cypherdare/4ef04c4e292fbe1e610a4ad5e1108164 to your computer and use it in GitHub Desktop.
Unpacks the flags of an Int by name
package com.cyphercove.flagunwrapper
import java.lang.reflect.Modifier
import kotlin.reflect.KClass
/** Return a set of String field names for flags used in the input value.
*
* Usage:
* ```
* Log.d("Flags", unwrapFlags(WindowManager.LayoutParams::class, 2097152).joinToString())
* ```
*
* @param cls The class containing the constant flag values.
* @param flags The Int containing the flag values
* @param fieldNamePrefix The start of every field name that is a flag value.
*/
fun unwrapFlags(cls: KClass<*>, flags: Int, fieldNamePrefix: String = "FLAG_"): Set<String> {
val flagValues = cls.java.declaredFields
.filter {
Modifier.isStatic(it.modifiers) &&
Modifier.isPublic(it.modifiers) &&
Modifier.isFinal(it.modifiers) &&
it.type == Int::class.javaPrimitiveType &&
it.getInt(null).toBits().count { bit -> bit } == 1 &&
it.name.startsWith(fieldNamePrefix)
}.map {
val bits = it.getInt(null).toBits()
val bitIndex = (0..31).first { i -> bits[i] }
it.name to bitIndex
}
val bits = flags.toBits()
val usedFlags = mutableSetOf<String>()
for (i in 0..31) {
if (bits[i]) {
flagValues.firstOrNull { it.second == i }?.first?.run {
usedFlags += this
}
}
}
return usedFlags
}
fun Int.toBits(): BooleanArray {
val bits = BooleanArray(32)
for (i in 31 downTo 0) {
bits[i] = this and (1 shl i) != 0
}
return bits
}
fun BooleanArray.toBitString() = joinToString("") { if (it) "1" else "0" }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment