diff -r 5bba9369df0f -r f07de07b90c4 core/src/commonMain/kotlin/gms/OssLicenseParser.kt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/commonMain/kotlin/gms/OssLicenseParser.kt Wed Mar 12 19:49:58 2025 -0400 @@ -0,0 +1,105 @@ +/* + * AboutOss is an utility library to retrieve and display + * opensource licenses in Android applications. + * + * Copyright (C) 2023 by Frederic-Charles Barthelery. + * + * This file is part of AboutOss. + * + * AboutOss is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AboutOss is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AboutOss. If not, see . + */ +package com.geekorum.aboutoss.core.gms + +import okio.ByteString +import okio.Source +import okio.buffer +import okio.use + +/** + * Parse licences data generated by the "com.google.android.gms.oss-licenses-plugin" gradle plugin. + */ +class OssLicenseParser { + + /** + * Parse licenses + * @param [thirdPartyLicensesInput] is usually res/raw/third_party_licenses file + * @param [thirdPartyLicensesMetadataInput] is usually res/raw/third_party_license_metadata file + */ + fun parseLicenses( + thirdPartyLicensesInput: Source, thirdPartyLicensesMetadataInput: Source + ): Map { + val licenses = readLicensesFile(thirdPartyLicensesInput) + return buildLicenseInfo(licenses, thirdPartyLicensesMetadataInput) + } + + private fun readLicensesFile(thirdPartyLicensesInput: Source): ByteString { + return thirdPartyLicensesInput.buffer().use { + it.readByteString() + } + } + + private fun buildLicenseInfo(license: ByteString, thirdPartyLicensesMetadataInput: Source): Map { + return thirdPartyLicensesMetadataInput.buffer().use { + buildMap { + while (true) { + val line = it.readUtf8Line() ?: break + if (line.isNotBlank()) { + with(line.toLineParser()) { + val start = readStartIdx() + val length = readLength() + val dependency = readName() + val licenseTxt = license.substring( + beginIndex = start, + endIndex = start + length + 1 + ).utf8() + put(dependency, licenseTxt) + } + } + } + } + } + } + + companion object +} + +private class LicenseMetadataLineParser( + private val line: String +) { + + private var idx = 0 + + fun readStartIdx(): Int { + val end = line.indexOf(':', startIndex = idx) + val result = line.substring(idx, end).toInt() + idx = end + 1 + return result + } + + fun readLength(): Int { + val end = line.indexOf(' ', startIndex = idx) + val result = line.substring(idx, end).toInt() + idx = end + 1 + return result + } + + fun readName(): String { + val result = line.substring(idx) + idx = line.length + 1 + return result + } + +} + +private fun String.toLineParser() = LicenseMetadataLineParser(this) \ No newline at end of file