Last active
December 12, 2022 19:08
-
-
Save wafna/627c359b70036727294ed014d821e7af to your computer and use it in GitHub Desktop.
Unit Formatter Generator
This file contains hidden or 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
/** | |
* This generates formatting functions for applying aggregating units (e.g. Kilo, Mega) | |
* to values. If you run out of units it gives up and shows the unit value. | |
* | |
* @param base The unit base, e.g. 1024 for bytes, 1000 for metric units of measure. | |
* @param units the names of the units starting with the base unit (e.g. byte, meter). | |
*/ | |
fun generateUnitFormatter(base: Int, units: List<String>): (Double, Int) -> String { | |
check(1 < base) | |
check(units.isNotEmpty()) | |
return { value, precision -> | |
check(0 <= precision) | |
tailrec fun haveAtIt(unitsTail: List<String>, adj: Double): String { | |
if (unitsTail.isEmpty()) { | |
return "$value${units.first()}" | |
} | |
if (adj < base) { | |
val formatter: Double = precision.let { | |
var i = 1.0 | |
for (q in 0 until precision) | |
i *= 10.0 | |
i | |
} | |
val mag = ((adj * formatter).roundToInt() / formatter).toString().let { | |
if (it.endsWith(".0")) it.substring(0 .. it.length - 3) | |
else it | |
} | |
return "$mag${unitsTail.first()}" | |
} | |
return haveAtIt(unitsTail.drop(1), adj / base) | |
} | |
haveAtIt(units, value) | |
} | |
} | |
private val formatBytesImpl = | |
generateUnitFormatter(1024, listOf("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")) | |
fun formatBytes(bytes: Long, precision: Int = 2): String = | |
formatBytesImpl(bytes.toDouble(), precision) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment