generated from korlibs/korlibs-library-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
2,497 additions
and
6 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 |
---|---|---|
@@ -1 +1 @@ | ||
# korlibs-library-template | ||
# korlibs-serialization |
File renamed without changes.
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
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,44 @@ | ||
package korlibs.io.lang | ||
|
||
import kotlin.collections.component1 | ||
import kotlin.collections.component2 | ||
import kotlin.collections.set | ||
|
||
open class Properties(map: Map<String, String>? = null) { | ||
//private val map = FastStringMap<String>() | ||
// This is required to work with K/N memory model | ||
private val map = LinkedHashMap<String, String>().also { | ||
if (map != null) it.putAll(map) | ||
} | ||
|
||
open operator fun contains(key: String): Boolean = get(key) != null | ||
open operator fun get(key: String): String? = map[key] | ||
open operator fun set(key: String, value: String) { map[key] = value } | ||
open fun setAll(values: Map<String, String>) { | ||
for ((key, value) in values) set(key, value) | ||
} | ||
open fun remove(key: String) { map.remove(key) } | ||
open fun getAll(): Map<String, String> = map.toMap() | ||
|
||
override fun toString(): String = buildString { | ||
for ((key, value) in map) { | ||
appendLine("$key=${value.replace("\n", "\\n")}") | ||
} | ||
} | ||
|
||
companion object { | ||
fun parseString(data: String): Properties { | ||
val props = LinkedHashMap<String, String>() | ||
for (line in data.lines()) { | ||
val (rline) = line.trim().split('#') | ||
if (rline.isEmpty()) continue | ||
val key = rline.substringBefore('=', "").trim() | ||
val value = rline.substringAfter('=', "").trim() | ||
if (key.isNotEmpty() && value.isNotEmpty()) { | ||
props[key] = value | ||
} | ||
} | ||
return Properties(props) | ||
} | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
korlibs-serialization/src/korlibs/io/lang/SystemProperties.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,3 @@ | ||
package korlibs.io.lang | ||
|
||
expect object SystemProperties : Properties |
105 changes: 105 additions & 0 deletions
105
korlibs-serialization/src/korlibs/io/serialization/csv/CSV.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,105 @@ | ||
@file:Suppress("PackageDirectoryMismatch") | ||
|
||
package korlibs.io.serialization.csv | ||
|
||
import korlibs.util.* | ||
|
||
class CSV(val lines: List<List<String>>, val names: List<String>? = null) : Collection<CSV.Record> { | ||
val namesToIndex: Map<String, Int> = names?.withIndex()?.associate { it.value to it.index } ?: emptyMap() | ||
val linesWithNames = if (names != null) listOf(names, *lines.toTypedArray()) else lines | ||
val records: List<Record> = lines.map { Record(it) } | ||
|
||
override val size: Int get() = records.size | ||
operator fun get(index: Int) = records[index] | ||
|
||
override fun iterator(): Iterator<Record> = records.iterator() | ||
override fun contains(element: Record): Boolean = records.contains(element) | ||
override fun containsAll(elements: Collection<Record>): Boolean = records.containsAll(elements) | ||
override fun isEmpty(): Boolean = records.isEmpty() | ||
|
||
inner class Record(val cells: List<String>) { | ||
operator fun get(index: Int): String = getOrNull(index) ?: error("Can't find element at $index") | ||
operator fun get(name: String): String = getOrNull(name) ?: error("Can't find element '$name'") | ||
|
||
fun getOrNull(index: Int): String? = cells.getOrNull(index) | ||
fun getOrNull(name: String): String? = namesToIndex[name]?.let { cells[it] } | ||
|
||
fun toMap(): Map<String, String> = if (names != null) cells.zip(names).associate { it.first to it.second } else cells.mapIndexed { index, s -> index to s }.associate { "${it.first}" to it.second } | ||
override fun toString(): String = if (names != null) "${toMap()}" else "$cells" | ||
} | ||
|
||
fun toString(separator: Char): String = linesWithNames.joinToString("\n") { serializeLine(it, separator) } | ||
override fun toString(): String = toString(DEFAULT_SEPARATOR) | ||
|
||
companion object { | ||
const val DEFAULT_SEPARATOR = ',' | ||
|
||
internal fun serializeElement(value: String, separator: Char): String { | ||
if (!value.contains('"') && !value.contains('\n') && !value.contains(separator)) return value | ||
val out = StringBuilder(value.length) | ||
for (n in 0 until value.length) { | ||
out.append(value[n]) | ||
} | ||
return out.toString() | ||
} | ||
|
||
fun serializeLine(values: List<String>, separator: Char = DEFAULT_SEPARATOR): String { | ||
return values.joinToString("$separator") { serializeElement(it, separator) } | ||
} | ||
|
||
fun parseLine(line: String, separator: Char = DEFAULT_SEPARATOR): List<String> = parseLine(SimpleStrReader(line), separator) | ||
|
||
fun parseLine(line: SimpleStrReader, separator: Char = DEFAULT_SEPARATOR): List<String> { | ||
val out = arrayListOf<String>() | ||
val str = StringBuilder() | ||
while (line.hasMore) { | ||
val c = line.readChar() | ||
when (c) { | ||
// Quoted string | ||
'"' -> { | ||
loop@while (line.hasMore) { | ||
val c2 = line.readChar() | ||
when (c2) { | ||
'"' -> { | ||
if (line.peekChar() == '"') { | ||
line.readChar() | ||
str.append('"') | ||
} else { | ||
break@loop | ||
} | ||
} | ||
else -> str.append(c2) | ||
} | ||
} | ||
} | ||
// Line break | ||
'\n' -> { | ||
break | ||
} | ||
// Empty string | ||
separator -> { | ||
out.add(str.toString()) | ||
str.clear() | ||
} | ||
// Normal string | ||
else -> { | ||
str.append(c) | ||
} | ||
} | ||
} | ||
out.add(str.toString()) | ||
str.clear() | ||
return out | ||
} | ||
|
||
fun parse(s: SimpleStrReader, separator: Char = DEFAULT_SEPARATOR, headerNames: Boolean = true): CSV { | ||
val lines = arrayListOf<List<String>>() | ||
while (s.hasMore) { | ||
lines.add(parseLine(s, separator)) | ||
} | ||
return if (headerNames) CSV(lines.drop(1), lines[0]) else CSV(lines, null) | ||
} | ||
|
||
fun parse(str: String, separator: Char = DEFAULT_SEPARATOR, headerNames: Boolean = true): CSV = parse(SimpleStrReader(str), separator, headerNames) | ||
} | ||
} |
Oops, something went wrong.