Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
4f897ce
Very rudimentary kv3 text parsing
xPaw Aug 5, 2022
5e6fb2f
Basic test for flagged value
xPaw Aug 5, 2022
1e9e2a5
kv3 does not have includes
xPaw Aug 5, 2022
844f11b
kv3 does not have conditionals
xPaw Aug 5, 2022
1e8cd55
Basic identifier read (flagged values)
xPaw Aug 5, 2022
d726423
Support multiline strings
xPaw Aug 5, 2022
9940ea5
Support multi line comments
xPaw Aug 5, 2022
93aee66
Partial support for arrays
xPaw Aug 5, 2022
5020ec6
Add kv3 guids
xPaw Aug 5, 2022
fb8f8f7
Parse kv3 header outside of the state machine
xPaw Aug 5, 2022
51aeab5
Add tests for header parsing
xPaw Aug 5, 2022
63cb12f
Add value type to debugger display
xPaw Aug 7, 2022
898bc3a
Parse basic types
xPaw Aug 7, 2022
a86f154
Add some text kv3 serialization support
xPaw Aug 7, 2022
5cb87c2
Prepare kv flag handling
xPaw Aug 8, 2022
80b0da7
Use Valve's delimeters
xPaw Aug 8, 2022
20f4943
flag 4
xPaw Aug 9, 2022
eb1d0b0
case insensitive
xPaw Aug 9, 2022
0d9d770
Read single quoted strings, read flags, correctly detect identifiers
xPaw Aug 9, 2022
bd83f7c
Support quoted keys
xPaw Aug 9, 2022
4c61cc7
still check for :
xPaw Aug 9, 2022
bc68831
Remove InObjectBeforeValue state
xPaw Aug 9, 2022
a6e5985
Write quoted keys when necessary; test objects
xPaw Aug 9, 2022
c60ecab
Support escaping """
xPaw Aug 9, 2022
1eb55e7
Parse binary blobs
xPaw Aug 9, 2022
59c05b3
Changes for array
xPaw Aug 9, 2022
b0d3889
Add OnArrayStart/OnArrayEnd
xPaw Aug 10, 2022
07698fa
Fix nested objects/arrays in arrays
xPaw Aug 10, 2022
4482558
Some preparation for kv flags
xPaw Aug 10, 2022
45d09ea
Implement flags on objects/arrays
xPaw Aug 11, 2022
c6b194e
Serialize arrays and flags
xPaw Aug 11, 2022
8fdeeba
Test that we serialize to kv1 without flags and arrays
xPaw Aug 11, 2022
540b173
Add expected array serialization
xPaw Aug 11, 2022
59c45ca
Simplify
xPaw Aug 11, 2022
925b1e7
Put common token reader methods in one class
xPaw Aug 11, 2022
0e3e72f
Put commas after objects and arrays in arrays
xPaw Dec 2, 2022
9eb46f3
Implement binary blobs
xPaw Dec 2, 2022
9526d89
Remove unused usings
xPaw Dec 3, 2022
a73b3b4
Add test for nested arrays and objects
xPaw Dec 4, 2022
cb935ba
Implement ICollection/IList on KVArrayValue
xPaw Dec 4, 2022
5ec4f3d
Return KVFile from read header
xPaw Mar 3, 2023
4bc0af1
Asset.Pass breaks analyzer
xPaw Mar 6, 2023
7b58d62
Add test cases for different types of roots
xPaw Mar 6, 2023
1eda68e
Add kv1 -> kv3 test
xPaw Apr 8, 2023
58a5dbd
Improve kv3 key escaping
xPaw Jul 4, 2023
6e4dc25
Make KVFile extend KVObject
xPaw Jul 24, 2023
2442f09
Make KVFlag singular
xPaw Jul 24, 2023
ee9c4cd
Rebase
xPaw Feb 9, 2024
07cf860
Fix
xPaw Apr 5, 2025
dd57a97
Fix require
xPaw Mar 26, 2026
cff67fe
Fix
xPaw Mar 26, 2026
3612110
Normalize line endings
xPaw Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ValveKeyValue/ValveKeyValue.Test/KVValueToStringTestCase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections;
using System.Linq;

namespace ValveKeyValue.Test
{
Expand All @@ -13,7 +14,7 @@ public static IEnumerable ToStringTestCases
{
yield return new TestCaseData(new KVObject("a", "blah").Value).Returns("blah");
yield return new TestCaseData(new KVObject("a", "yay").Value).Returns("yay");
yield return new TestCaseData(new KVObject("a", []).Value).Returns("[Collection]").SetName("{m} - Empty Collection");
yield return new TestCaseData(new KVObject("a", Enumerable.Empty<KVObject>()).Value).Returns("[Collection]").SetName("{m} - Empty Collection");
yield return new TestCaseData(new KVObject("a", [new KVObject("boo", "aah")]).Value).Returns("[Collection]").SetName("{m} - Collection With Value");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Keep intended line endings to test parser
*.kv3 eol=lf
*_crlf.kv3 eol=crlf
33 changes: 33 additions & 0 deletions ValveKeyValue/ValveKeyValue.Test/Test Data/TextKV3/array.kv3
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
arrayValue =
[
"a",
"b",
]
arrayOnSingleLine = [ 16.7551, 20.3763, 19.6448 ]
arrayNoSpace=[1.3763,19.6448]
arrayMixedTypes =
[
"a",
1,
true,
false,
null,
{
foo = "bar"
},
[
1, 3, 3, 7
],
#[
11 FF
],
resource:"hello.world",
"""
multiline
string
""",
-69.420
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
arrayValue = {
"0" = "a"
"1" = "b"
}
arrayOnSingleLine = {
"0" = 16.755100
"1" = 20.376300
"2" = 19.644800
}
arrayNoSpace = {
"0" = 1.376300
"1" = 19.644800
}
arrayMixedTypes = {
"0" = "a"
"1" = 1
"2" = "True"
"3" = "False"
"4" = ""
"5" = {
foo = "bar"
}
"6" = {
"0" = 1
"1" = 3
"2" = 3
"3" = 7
}
"7" = "11 FF"
"8" = "hello.world"
"9" = """
multiline
string
"""
"10" = -69.420000
}
test = "success"
test = "success"
}
44 changes: 44 additions & 0 deletions ValveKeyValue/ValveKeyValue.Test/Test Data/TextKV3/array_kv1.vdf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
""
{
"arrayValue"
{
"0" "a"
"1" "b"
}
"arrayOnSingleLine"
{
"0" "16.7551"
"1" "20.3763"
"2" "19.6448"
}
"arrayNoSpace"
{
"0" "1.3763"
"1" "19.6448"
}
"arrayMixedTypes"
{
"0" "a"
"1" "1"
"2" "True"
"3" "False"
"4" ""
"5"
{
"foo" "bar"
}
"6"
{
"0" "1"
"1" "3"
"2" "3"
"3" "7"
}
"7" "11 FF"
"8" "hello.world"
"9" "multiline
string"
"10" "-69.42"
}
"test" "success"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
array = [
1,
2,
3,
{
array2 = [
4,
5,
6,
{
something = "something"
array3 = [
7,
8,
9,
]
test = "abc"
},
10,
]
test2 = "def"
},
"string",
11,
12,
[
13,
14,
15,
[
16,
17,
18,
],
],
19,
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
arrayValue = [
"a",
"b",
]
arrayOnSingleLine = [
16.755100,
20.376300,
19.644800,
]
arrayNoSpace = [
1.376300,
19.644800,
]
arrayMixedTypes = [
"a",
1,
true,
false,
null,
{
foo = "bar"
},
[
1,
3,
3,
7,
],
#[
11 FF
],
resource:"hello.world",
"""
multiline
string
""",
-69.420000,
]
test = "success"
}
4 changes: 4 additions & 0 deletions ValveKeyValue/ValveKeyValue.Test/Test Data/TextKV3/basic.kv3
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
foo = "bar"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
array =
#[
00 11 22 33 44 55 66 77 88 99
AA BB CC DD FF
]
}
10 changes: 10 additions & 0 deletions ValveKeyValue/ValveKeyValue.Test/Test Data/TextKV3/comments.kv3
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
// single line comment
/* multi
line
comment */
foo = "bar" // comment after
one = /* comment in between */ /* another comment in between */ "1" /* comment after */
two /* comment in between */ = "2" /* comment after */
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
name = entity_name:"some_entity"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
newline = "hello\nworld"
tab = "hello\tworld"
backslash = "hello\\world"
quote = "hello\"world"
combined = "line1\nline2\ttab\\slash\"quote"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
foo = resource:"bar"
bar = resource|"foo"
uppercase = RESOURCE:"foo"
flaggedNumber = panorama:-1234
multipleFlags = resource:resource_name|subclass:"cool value"
soundEvent = soundEvent:"event sound"
noFlags = 5

flaggedObject = panorama:{
1 = soundEvent:"test1"
2 = "test2"
3 = subclass:[
"test3"
]
4 = resource_name:"test4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
foo = "bar"
bar = "foo"
uppercase = "foo"
flaggedNumber = -1234
multipleFlags = "cool value"
soundEvent = "event sound"
noFlags = 5
flaggedObject = {
"1" = "test1"
"2" = "test2"
"3" = {
"0" = "test3"
}
"4" = "test4"
}
test = "success"
test = "success"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
""
{
"foo" "bar"
"bar" "foo"
"uppercase" "foo"
"flaggedNumber" "-1234"
"multipleFlags" "cool value"
"soundEvent" "event sound"
"noFlags" "5"
"flaggedObject"
{
"1" "test1"
"2" "test2"
"3"
{
"0" "test3"
}
"4" "test4"
}
"test" "success"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
foo = resource:"bar"
bar = resource:"foo"
uppercase = resource:"foo"
flaggedNumber = panorama:-1234
multipleFlags = subclass:"cool value"
soundEvent = soundevent:"event sound"
noFlags = 5
flaggedObject = panorama:{
"1" = soundevent:"test1"
"2" = "test2"
"3" = subclass:[
"test3",
]
"4" = resource_name:"test4"
}
test = "success"
}
13 changes: 13 additions & 0 deletions ValveKeyValue/ValveKeyValue.Test/Test Data/TextKV3/multiline.kv3
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
multiLineStringValue = """
First line of a multi-line string literal.
Second line of a multi-line string literal.
"""
multiLineWithQuotesInside = """
hmm this \"""is awkward
\""" yes
"""
singleQuotesButWithNewLineAnyway = "hello
valve"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
multiLineStringValue = """
First line of a multi-line string literal.
Second line of a multi-line string literal.
"""
}
9 changes: 9 additions & 0 deletions ValveKeyValue/ValveKeyValue.Test/Test Data/TextKV3/object.kv3
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
a = {
foo = "bar"
b = {
c = "d"
}
}
}
Loading
Loading