Skip to content

Commit ca715b0

Browse files
committed
Parse configuration added. Map object factory added to parse configuration. Default is HashMap
1 parent aa8fb2b commit ca715b0

File tree

12 files changed

+167
-101
lines changed

12 files changed

+167
-101
lines changed

src/iris/json/Configuration.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package iris.json
2+
3+
/**
4+
* @created 30.12.2020
5+
* @author [Ivan Ivanov](https://vk.com/irisism)
6+
*/
7+
class Configuration {
8+
9+
companion object {
10+
val globalConfiguration = Configuration()
11+
}
12+
13+
interface MapObjectFactory {
14+
fun getMap(elementsAmount: Int): MutableMap<String, Any?>
15+
}
16+
17+
var mapObjectFactory: MapObjectFactory = object : MapObjectFactory {
18+
override fun getMap(elementsAmount: Int): MutableMap<String, Any?> {
19+
return HashMap(elementsAmount)
20+
}
21+
}
22+
}

src/iris/json/flow/FlowArray.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import iris.json.JsonItem
77
* @created 20.09.2020
88
* @author [Ivan Ivanov](https://vk.com/irisism)
99
*/
10-
class FlowArray(tokener: Tokener) : FlowItem(tokener), JsonArray {
10+
class FlowArray(private val parser: JsonFlowParser) : FlowItem(parser.tokener), JsonArray {
1111

1212
private val items = mutableListOf<JsonItem>()
1313

@@ -60,7 +60,7 @@ class FlowArray(tokener: Tokener) : FlowItem(tokener), JsonArray {
6060
if (char != ',')
6161
tokener.back()
6262

63-
return JsonFlowParser.readItem(tokener)
63+
return parser.readItem()
6464
}
6565

6666
private fun parseNextAndAdd(): FlowItem? {

src/iris/json/flow/FlowObject.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import java.util.*
1010
* @created 20.09.2020
1111
* @author [Ivan Ivanov](https://vk.com/irisism)
1212
*/
13-
class FlowObject(tokener: Tokener) : FlowItem(tokener), JsonObject {
13+
class FlowObject(private val parser: JsonFlowParser) : FlowItem(parser.tokener), JsonObject {
1414

1515
override fun get(ind: Int): JsonItem {
1616
return get(ind.toString())
@@ -44,6 +44,7 @@ class FlowObject(tokener: Tokener) : FlowItem(tokener), JsonObject {
4444
}
4545

4646
private fun parseNext(): JsonEntry? {
47+
val tokener = this.tokener
4748
var char: Char? = tokener.nextChar()
4849
if (char == '}') {
4950
isDone = true
@@ -65,7 +66,7 @@ class FlowObject(tokener: Tokener) : FlowItem(tokener), JsonObject {
6566
char = tokener.nextChar()
6667
if (char != ':')
6768
throw tokener.exception("\":\" was expected")
68-
val value = JsonFlowParser.readItem(tokener)
69+
val value = parser.readItem()
6970
return JsonEntry(key, value)
7071
}
7172

@@ -75,7 +76,8 @@ class FlowObject(tokener: Tokener) : FlowItem(tokener), JsonObject {
7576
if (obj != null)
7677
return obj
7778
parse()
78-
val res = HashMap<String, Any?>(entries.size)
79+
val res = parser.configuration.mapObjectFactory.getMap(entries.size)
80+
7981
for (it in entries)
8082
res[it.first.toString()] = it.second.obj()
8183
obj = res

src/iris/json/flow/JsonFlowParser.kt

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package iris.json.flow
22

3+
import iris.json.Configuration
34
import iris.json.IrisJson
45
import java.io.*
56
import java.net.URL
@@ -8,23 +9,31 @@ import java.net.URL
89
* @created 20.09.2020
910
* @author [Ivan Ivanov](https://vk.com/irisism)
1011
*/
11-
object JsonFlowParser {
12+
class JsonFlowParser(val tokener: Tokener, val configuration: Configuration) {
1213

13-
fun start(url: URL) = start(url.openStream())
14+
companion object {
1415

15-
fun start(ins: InputStream) = readItem(reader(InputStreamReader(ins)))
16+
fun start(url: URL, configuration: Configuration = Configuration.globalConfiguration) = start(url.openStream(), configuration)
1617

17-
fun start(reader: Reader) = readItem(reader(reader))
18+
fun start(ins: InputStream, configuration: Configuration = Configuration.globalConfiguration) = readItem(reader(InputStreamReader(ins)), configuration)
1819

19-
fun start(file: File) = readItem(reader(FileReader(file)))
20+
fun start(reader: Reader, configuration: Configuration = Configuration.globalConfiguration) = readItem(reader(reader), configuration)
2021

21-
fun start(text: String) = readItem(TokenerString(text))
22+
fun start(file: File, configuration: Configuration = Configuration.globalConfiguration) = readItem(reader(FileReader(file)), configuration)
2223

23-
private fun reader(reader: Reader) = TokenerContentBuildReader(reader)
24+
fun start(text: String, configuration: Configuration = Configuration.globalConfiguration) = readItem(TokenerString(text), configuration)
2425

25-
fun start(source: Tokener) = readItem(source)
26+
private fun reader(reader: Reader) = TokenerContentBuildReader(reader)
2627

27-
fun readItem(source: Tokener): FlowItem {
28+
fun start(source: Tokener, configuration: Configuration = Configuration.globalConfiguration) = readItem(source, configuration)
29+
30+
fun readItem(source: Tokener, configuration: Configuration = Configuration.globalConfiguration): FlowItem {
31+
return JsonFlowParser(source, configuration).readItem()
32+
}
33+
}
34+
35+
fun readItem(): FlowItem {
36+
val source = this.tokener
2837
val char = source.nextChar()
2938
val type = when {
3039
char.isDigit() || char.isLetter() || char == '-' -> IrisJson.Type.Value
@@ -35,10 +44,12 @@ object JsonFlowParser {
3544
}
3645

3746
return when (type) {
38-
IrisJson.Type.Value -> { source.back(); FlowValue(source) }
39-
IrisJson.Type.Object -> FlowObject(source)
47+
IrisJson.Type.Value -> {
48+
source.back(); FlowValue(source)
49+
}
50+
IrisJson.Type.Object -> FlowObject(this)
4051
IrisJson.Type.String -> FlowString(source, char)
41-
IrisJson.Type.Array -> FlowArray(source)
52+
IrisJson.Type.Array -> FlowArray(this)
4253
else -> throw source.exception("$type not realised yet")
4354
}
4455
}

src/iris/json/plain/IrisJsonObject.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package iris.json.plain
22

3+
import iris.json.Configuration
34
import iris.json.JsonEntry
45
import iris.json.JsonItem
56
import iris.json.JsonObject
@@ -8,9 +9,9 @@ import iris.json.JsonObject
89
* @created 14.04.2020
910
* @author [Ivan Ivanov](https://vk.com/irisism)
1011
*/
11-
open class IrisJsonObject(private val entries: List<JsonEntry>) : IrisJsonItem(), JsonObject {
12+
open class IrisJsonObject(private val entries: List<JsonEntry>, private val configuration: Configuration) : IrisJsonItem(), JsonObject {
1213

13-
constructor(vararg items: Pair<String, JsonItem>) : this(items.asList())
14+
constructor(vararg items: Pair<String, JsonItem>, configuration: Configuration) : this(items.asList(), configuration)
1415

1516
override fun get(key: String): JsonItem {
1617
return (entries.find {it.first == key }?.second) ?: IrisJsonNull.Null
@@ -43,7 +44,7 @@ open class IrisJsonObject(private val entries: List<JsonEntry>) : IrisJsonItem()
4344
override fun obj(): Any? {
4445
if (obj != null)
4546
return obj
46-
val res = HashMap<String, Any?>(entries.size)
47+
val res = configuration.mapObjectFactory.getMap(entries.size)
4748
for (it in entries)
4849
res[it.first.toString()] = it.second.obj()
4950
obj = res
Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package iris.json.plain
22

3+
import iris.json.Configuration
34
import iris.json.IrisJson
45
import iris.json.JsonEntry
56
import iris.json.flow.TokenerString
67
import iris.sequence.IrisSequenceCharArray
8+
import java.io.*
9+
import java.net.URL
710
import java.util.*
811
import kotlin.collections.ArrayList
912
import kotlin.math.max
@@ -13,12 +16,32 @@ import kotlin.math.min
1316
* @created 14.04.2020
1417
* @author [Ivan Ivanov](https://vk.com/irisism)
1518
*/
16-
class IrisJsonParser(source: String) {
19+
class JsonPlainParser(source: String, private val configuration: Configuration = Configuration.globalConfiguration) {
20+
21+
companion object {
22+
23+
fun parse(url: URL, configuration: Configuration = Configuration.globalConfiguration) =
24+
parse(url.openStream(), configuration)
25+
26+
fun parse(ins: InputStream, configuration: Configuration = Configuration.globalConfiguration) =
27+
parse(reader(InputStreamReader(ins)), configuration)
28+
29+
fun parse(reader: Reader, configuration: Configuration = Configuration.globalConfiguration) =
30+
parse(reader(reader), configuration)
31+
32+
fun parse(file: File, configuration: Configuration = Configuration.globalConfiguration) =
33+
parse(reader(FileReader(file)), configuration)
34+
35+
private fun reader(reader: Reader) = reader.use { it.readText() }
36+
37+
fun parse(source: String, configuration: Configuration = Configuration.globalConfiguration): IrisJsonItem {
38+
return JsonPlainParser(source, configuration).readItem()
39+
}
40+
}
1741

1842
private var pointer = 0
1943
private val source: CharArray = source.toCharArray()
2044

21-
2245
fun parse(): IrisJsonItem {
2346
return readItem()
2447
}
@@ -34,23 +57,28 @@ class IrisJsonParser(source: String) {
3457
else -> throw IllegalArgumentException("Character: \"$char\" at $pointer\n" + getPlace())
3558
}
3659

37-
if (type == IrisJson.Type.Value) { // примитивы
38-
pointer--
39-
val start = pointer
40-
val value = readPrimitive()
41-
val end = pointer
42-
return IrisJsonValue(IrisSequenceCharArray(source, start, end), value)
43-
} else if (type == IrisJson.Type.Object) {
44-
return readObject()
45-
} else if (type == IrisJson.Type.String) {
46-
val start = pointer
47-
readString(char)
48-
val end = pointer - 1
49-
return IrisJsonString(IrisSequenceCharArray(source, start, end))
50-
} else if (type == IrisJson.Type.Array) {
51-
return readArray()
52-
} else
53-
TODO("$type not realised yet $pointer\n" + getPlace())
60+
when (type) {
61+
IrisJson.Type.Value -> { // примитивы
62+
pointer--
63+
val start = pointer
64+
val value = readPrimitive()
65+
val end = pointer
66+
return IrisJsonValue(IrisSequenceCharArray(source, start, end), value)
67+
}
68+
IrisJson.Type.Object -> {
69+
return readObject()
70+
}
71+
IrisJson.Type.String -> {
72+
val start = pointer
73+
readString(char)
74+
val end = pointer - 1
75+
return IrisJsonString(IrisSequenceCharArray(source, start, end))
76+
}
77+
IrisJson.Type.Array -> {
78+
return readArray()
79+
}
80+
else -> TODO("$type not realised yet $pointer\n" + getPlace())
81+
}
5482
}
5583

5684
private fun getPlace(): String {
@@ -59,14 +87,13 @@ class IrisJsonParser(source: String) {
5987

6088
private fun readObject(): IrisJsonObject {
6189

62-
//val key = readKey() ?: return IrisJsonObject(ArrayList(0))
63-
val key = readKey() ?: return IrisJsonObject(ArrayList(0))
90+
val key = readKey() ?: return IrisJsonObject(ArrayList(0), configuration)
6491
val value = readValue()
6592

66-
val key2 = readKey() ?: return IrisJsonObject(ArrayList<JsonEntry>(1).also { it += key to value })
93+
val key2 = readKey() ?: return IrisJsonObject(ArrayList<JsonEntry>(1).also { it += key to value }, configuration)
6794
val value2 = readValue()
6895

69-
val key3 = readKey() ?: return IrisJsonObject(ArrayList<JsonEntry>(2).also { it += key to value; it += key2 to value2 })
96+
val key3 = readKey() ?: return IrisJsonObject(ArrayList<JsonEntry>(2).also { it += key to value; it += key2 to value2 }, configuration)
7097
val value3 = readValue()
7198

7299
val entries = LinkedList<JsonEntry>()
@@ -103,7 +130,7 @@ class IrisJsonParser(source: String) {
103130
entries += key to value
104131
//counter--
105132
} while (pointer < len)
106-
return IrisJsonObject(entries)
133+
return IrisJsonObject(entries, configuration)
107134
}
108135

109136
private fun readValue(): IrisJsonItem {
@@ -200,13 +227,13 @@ class IrisJsonParser(source: String) {
200227
var curType = IrisJson.ValueType.Integer
201228
val first = pointer
202229
val len = source.size
203-
loop@ do {
230+
do {
204231
when (source[pointer]) {
205232
in '0'..'9' -> {}
206233
'-' -> if (first != pointer) curType = IrisJson.ValueType.Constant
207234
'.' -> if (curType == IrisJson.ValueType.Integer) curType = IrisJson.ValueType.Float
208235
in 'a'..'z', in 'A'..'Z' -> curType = IrisJson.ValueType.Constant
209-
else -> break@loop
236+
else -> break
210237
}
211238
pointer++
212239
} while (pointer < len)

src/iris/json/serialization/DeserializerFactory.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ package iris.json.serialization
33
import iris.json.JsonItem
44
import kotlin.reflect.KClass
55
import kotlin.reflect.KType
6-
import kotlin.reflect.full.isSubclassOf
7-
import kotlin.reflect.full.isSubtypeOf
8-
import kotlin.reflect.full.starProjectedType
9-
import kotlin.reflect.full.superclasses
6+
import kotlin.reflect.full.*
107
import kotlin.reflect.jvm.jvmErasure
118

129
/**
@@ -36,6 +33,7 @@ object DeserializerFactory {
3633

3734
fun registerDeserializer(d: KClass<*>, deserializer: Deserializer) {
3835
cache[d] = deserializer
36+
registerDeserializer(d.starProjectedType, deserializer)
3937
}
4038

4139
fun registerDeserializer(type: KType, deserializer: Deserializer) {
@@ -72,6 +70,9 @@ object DeserializerFactory {
7270
}
7371

7472
private fun getMapType(type: KType): KType {
73+
val type = type.jvmErasure.allSupertypes.find {
74+
it.jvmErasure == Map::class
75+
} ?: throw IllegalArgumentException("$type is not subclass of Map")
7576
val (key, value) = type.arguments
7677
if (!key.type!!.isSubtypeOf(CharSequence::class.starProjectedType))
7778
throw IllegalStateException("Map key cannot be non CharSequence inherited")

src/iris/json/serialization/DeserializerMapImpl.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ class DeserializerMapImpl : DeserializerMap {
1414
lateinit var valueDeserializer: Deserializer
1515

1616
override fun <T> getMap(entries: Collection<JsonEntry>): Map<String, T> {
17-
return entries.associate {(key, value) ->
18-
key.toString() to (valueDeserializer.deserialize(value) as T)
19-
}
17+
val res = HashMap<String, T>(entries.size)
18+
val valueDeserializer = this.valueDeserializer
19+
for ((key, value) in entries)
20+
res[key.toString()] = (valueDeserializer.deserialize(value) as T)
21+
return res
2022
}
2123

2224
override fun <T> deserialize(item: JsonItem): T {

0 commit comments

Comments
 (0)