Skip to content

Commit 38b61d0

Browse files
committed
release 1.4.3
1 parent 719b33c commit 38b61d0

26 files changed

Lines changed: 1423 additions & 34 deletions

File tree

DataConfig/Source/DataConfigCore/Private/DataConfig/Deserialize/DcDeserializeUtils.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ FDcResult RecursiveDeserialize(FDcDeserializeContext& Ctx)
2222
return DcOk();
2323
}
2424

25+
EDcDeserializePredicateResult PredicateIsRootProperty(FDcDeserializeContext& Ctx)
26+
{
27+
check(Ctx.Properties.Num() > 0);
28+
return Ctx.TopProperty() == Ctx.Properties[0]
29+
? EDcDeserializePredicateResult::Process
30+
: EDcDeserializePredicateResult::Pass;
31+
}
32+
2533
} // namespace DcDeserializeUtils
2634

2735

DataConfig/Source/DataConfigCore/Private/DataConfig/Diagnostic/DcDiagnosticSerDe.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ namespace DcDSerDe
77
struct FDcDiagnosticDetail _DeserializeDetails[] = {
88
{ NoMatchingHandler, TEXT("No matching handler, Property: '{0}' '{1}'"), },
99
{ MismatchHandler, TEXT("Mismatched handler, Property: '{0}' '{1}'"), },
10-
{ NotPrepared, TEXT("Deserialize isn't prepared, need to call 'Ctx.Prepare'"), },
11-
{ DataEntryMismatch, TEXT("Deserialize type mismatch, Expect: '{0}', Actual: '{1}'"), },
12-
{ DataEntryMismatch2, TEXT("Deserialize type mismatch, Expect: '{0}'/'{1}', Actual: '{2}'"), },
13-
{ DataEntryMismatch3, TEXT("Deserialize type mismatch, Expect: '{0}'/'{1}'/'{2}', Actual: {3}"), },
10+
{ NotPrepared, TEXT("Context isn't prepared, need to call 'Ctx.Prepare'"), },
11+
{ DataEntryMismatch, TEXT("Type mismatch, Expect: '{0}', Actual: '{1}'"), },
12+
{ DataEntryMismatch2, TEXT("Type mismatch, Expect: '{0}'/'{1}', Actual: '{2}'"), },
13+
{ DataEntryMismatch3, TEXT("Type mismatch, Expect: '{0}'/'{1}'/'{2}', Actual: {3}"), },
1414
{ ExpectMetaType, TEXT("Expect '$type' but not found")},
1515
{ ExpectNumericEntry, TEXT("Expect numeric data but not found, Actual: '{0}'")},
1616
{ CoercionFail, TEXT("Reader coercion failed, Actual: '{0}'")},

DataConfig/Source/DataConfigCore/Private/DataConfig/Json/DcJsonReader.cpp

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ FDcResult TDcJsonReader<CharType>::FinishRead()
308308

309309
EDcDataEntry Next;
310310
DC_TRY(PeekRead(&Next));
311+
311312
if (Next != EDcDataEntry::Ended)
312313
{
313314
return DC_FAIL(DcDJSON, UnexpectedTrailingToken)
@@ -316,8 +317,19 @@ FDcResult TDcJsonReader<CharType>::FinishRead()
316317
}
317318
else
318319
{
319-
check(State == EState::FinishedStr);
320-
return DcOk();
320+
if (GetTopState() == EParseState::Object)
321+
{
322+
return DC_FAIL(DcDJSON, EndUnclosedObject) << FormatHighlight(Cur, 0);
323+
}
324+
else if (GetTopState() == EParseState::Array)
325+
{
326+
return DC_FAIL(DcDJSON, EndUnclosedArray) << FormatHighlight(Cur, 0);
327+
}
328+
else
329+
{
330+
check(State == EState::FinishedStr);
331+
return DcOk();
332+
}
321333
}
322334
}
323335

@@ -917,7 +929,7 @@ FDcResult TDcJsonReader<CharType>::CheckConsumeToken(EDcDataEntry Expect)
917929
<< FormatHighlight(Token.Ref);
918930
}
919931

920-
// setting need consume token for the next one
932+
// setting need consume token for the next one when not at end
921933
bNeedConsumeToken = true;
922934
return DcOk();
923935
}
@@ -948,8 +960,9 @@ FDcResult TDcJsonReader<CharType>::EndTopRead()
948960
DC_TRY(ConsumeEffectiveToken());
949961
bTopObjectAtValue = false;
950962

951-
// allowing optional trailing comma
952-
if (Token.Type == ETokenType::Comma)
963+
if (Token.Type == ETokenType::Comma // allowing optional trailing comma
964+
|| Token.Type == ETokenType::EOF_) // allowing root level object
965+
953966
{
954967
return DcOk();
955968
}
@@ -969,7 +982,8 @@ FDcResult TDcJsonReader<CharType>::EndTopRead()
969982
FToken Prev = Token;
970983
DC_TRY(ConsumeEffectiveToken());
971984

972-
if (Token.Type == ETokenType::Comma)
985+
if (Token.Type == ETokenType::Comma // allowing optional trailing comma
986+
|| Token.Type == ETokenType::EOF_) // allowing root level array
973987
{
974988
return DcOk();
975989
}
@@ -1101,21 +1115,11 @@ FDcResult TDcJsonReader<CharType>::ConsumeRawToken()
11011115

11021116
if (IsAtEnd())
11031117
{
1104-
if (GetTopState() == EParseState::Object)
1105-
{
1106-
return DC_FAIL(DcDJSON, EndUnclosedObject) << FormatHighlight(Cur, 1);
1107-
}
1108-
else if (GetTopState() == EParseState::Array)
1109-
{
1110-
return DC_FAIL(DcDJSON, EndUnclosedArray) << FormatHighlight(Cur, 1);
1111-
}
1112-
else
1113-
{
1114-
Token.Type = ETokenType::EOF_;
1115-
// keep the token for diagnostic highlight
1116-
State = EState::FinishedStr;
1117-
return DcOk();
1118-
}
1118+
Token.Type = ETokenType::EOF_;
1119+
// keep the token for diagnostic highlight
1120+
State = EState::FinishedStr;
1121+
bNeedConsumeToken = false;
1122+
return DcOk();
11191123
}
11201124

11211125
auto _ConsumeSingleCharToken = [this](ETokenType TokenType) {

DataConfig/Source/DataConfigCore/Private/DataConfig/Serialize/DcSerializeUtils.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,13 @@ FDcResult RecursiveSerialize(FDcSerializeContext& Ctx)
2222
return DcOk();
2323
}
2424

25+
EDcSerializePredicateResult PredicateIsRootProperty(FDcSerializeContext& Ctx)
26+
{
27+
check(Ctx.Properties.Num() > 0);
28+
return Ctx.TopProperty() == Ctx.Properties[0]
29+
? EDcSerializePredicateResult::Process
30+
: EDcSerializePredicateResult::Pass;
31+
}
32+
2533
} // namespace DcSerializeUtils
2634

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#pragma once
22

3-
#define DATA_CONFIG_CORE_VERSION "1.4.2"
4-
#define DATA_CONFIG_CORE_VERSION_NUMBER 10402
3+
#define DATA_CONFIG_CORE_VERSION "1.4.3"
4+
#define DATA_CONFIG_CORE_VERSION_NUMBER 10403

DataConfig/Source/DataConfigCore/Public/DataConfig/Deserialize/DcDeserializeUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ EDcDeserializePredicateResult PredicateIsUStruct(FDcDeserializeContext& Ctx)
1717
? EDcDeserializePredicateResult::Process
1818
: EDcDeserializePredicateResult::Pass;
1919
}
20+
21+
DATACONFIGCORE_API EDcDeserializePredicateResult PredicateIsRootProperty(FDcDeserializeContext& Ctx);
2022

2123
} // namespace DcDeserializeUtils
2224

DataConfig/Source/DataConfigCore/Public/DataConfig/Diagnostic/DcDiagnostic.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ struct DATACONFIGCORE_API FDcDiagnostic
4242
};
4343

4444
template<typename T>
45-
FORCEINLINE typename TEnableIf<!TIsEnumClass<T>::Value, FDcDiagnostic&>::Type
45+
typename TEnableIf<!TIsEnumClass< typename TRemoveReference<T>::Type >::Value, FDcDiagnostic&>::Type
4646
operator<<(FDcDiagnostic& Diag, T&& InValue)
4747
{
4848
Diag.Args.Emplace(Forward<T>(InValue));
4949
return Diag;
5050
}
5151

5252
template<typename T>
53-
FORCEINLINE typename TEnableIf<TIsEnumClass<T>::Value, FDcDiagnostic&>::Type
53+
typename TEnableIf<TIsEnumClass< typename TRemoveReference<T>::Type >::Value, FDcDiagnostic&>::Type
5454
operator<<(FDcDiagnostic& Diag, T&& InValue)
5555
{
5656
Diag.Args.Emplace((int)(InValue));

DataConfig/Source/DataConfigCore/Public/DataConfig/Serialize/DcSerializeUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ EDcSerializePredicateResult PredicateIsUStruct(FDcSerializeContext& Ctx)
1818
? EDcSerializePredicateResult::Process
1919
: EDcSerializePredicateResult::Pass;
2020
}
21+
22+
DATACONFIGCORE_API EDcSerializePredicateResult PredicateIsRootProperty(FDcSerializeContext& Ctx);
2123

2224
} // namespace DcSerializeUtils
2325

DataConfig/Source/DataConfigExtra/Private/DataConfig/Extra/Diagnostic/DcDiagnosticExtra.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ static FDcDiagnosticDetail _ExtraDetails[] = {
1515
// InlineStruct
1616
{ InlineStructTooBig, TEXT("Inline struct too big: BufSize '{0}', Struct '{1}' Size '{2}'"), },
1717
{ InlineStructNotSet, TEXT("Inline struct not set"), },
18+
19+
// Nested
20+
{ NestedMissingMetaData, TEXT("Nested missing metadata: '{0}'"), },
21+
{ NestedGrid2DHeightMismatch, TEXT("Nested Grid2D height mismatch, Expect '{0}'"), },
22+
{ NestedGrid2DWidthMismatch, TEXT("Nested Grid2D width mismatch, Expect '{0}'"), },
23+
{ NestedGrid2DLenMismatch, TEXT("Nested Grid2D total length mismatch, Expect '{0}', Actual: '{1}'"), },
1824
};
1925

2026
FDcDiagnosticGroup Details = {
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#include "DataConfig/Extra/Misc/DcNDJSON.h"
2+
#include "DataConfig/Deserialize/DcDeserializeTypes.h"
3+
#include "DataConfig/Deserialize/DcDeserializeUtils.h"
4+
#include "DataConfig/Deserialize/DcDeserializerSetup.h"
5+
#include "DataConfig/Serialize/DcSerializer.h"
6+
#include "DataConfig/Serialize/DcSerializerSetup.h"
7+
#include "DataConfig/Serialize/DcSerializeUtils.h"
8+
#include "DataConfig/Diagnostic/DcDiagnosticReadWrite.h"
9+
10+
#include "DataConfig/Automation/DcAutomation.h"
11+
#include "DataConfig/Automation/DcAutomationUtils.h"
12+
#include "DataConfig/Extra/Misc/DcTestCommon.h"
13+
#include "DataConfig/Json/DcJsonReader.h"
14+
#include "DataConfig/Json/DcJsonWriter.h"
15+
#include "DataConfig/Serialize/DcSerializeUtils.h"
16+
#include "DataConfig/Deserialize/DcDeserializeUtils.h"
17+
#include "DataConfig/Extra/Types/DcExtraTestFixtures.h"
18+
19+
namespace DcExtra
20+
{
21+
22+
namespace NDJSONDetails
23+
{
24+
25+
static TOptional<FDcDeserializer> Deserializer;
26+
static void LazyInitializeDeserializer()
27+
{
28+
if (Deserializer.IsSet())
29+
return;
30+
31+
Deserializer.Emplace();
32+
DcSetupJsonDeserializeHandlers(Deserializer.GetValue());
33+
34+
Deserializer->AddPredicatedHandler(
35+
FDcDeserializePredicate::CreateStatic(DcDeserializeUtils::PredicateIsRootProperty),
36+
FDcDeserializeDelegate::CreateLambda([](FDcDeserializeContext& Ctx) -> FDcResult
37+
{
38+
if (!Ctx.TopProperty().IsA<FArrayProperty>())
39+
return DC_FAIL(DcDReadWrite, PropertyMismatch)
40+
<< TEXT("Array") << Ctx.TopProperty().GetFName() << Ctx.TopProperty().GetClassName();
41+
42+
DC_TRY(Ctx.Writer->WriteArrayRoot());
43+
EDcDataEntry CurPeek;
44+
while (true)
45+
{
46+
DC_TRY(Ctx.Reader->PeekRead(&CurPeek));
47+
// read until EOF as we're processing ndjson
48+
if (CurPeek == EDcDataEntry::Ended)
49+
break;
50+
51+
DC_TRY(DcDeserializeUtils::RecursiveDeserialize(Ctx));
52+
}
53+
54+
DC_TRY(Ctx.Writer->WriteArrayEnd());
55+
return DcOk();
56+
})
57+
);
58+
}
59+
60+
61+
static TOptional<FDcSerializer> Serializer;
62+
static void LazyInitializeSerializer()
63+
{
64+
if (Serializer.IsSet())
65+
return;
66+
67+
Serializer.Emplace();
68+
DcSetupJsonSerializeHandlers(Serializer.GetValue());
69+
70+
Serializer->AddPredicatedHandler(
71+
FDcSerializePredicate::CreateStatic(DcSerializeUtils::PredicateIsRootProperty),
72+
FDcSerializeDelegate::CreateLambda([](FDcSerializeContext& Ctx) -> FDcResult{
73+
if (!Ctx.TopProperty().IsA<FArrayProperty>())
74+
return DC_FAIL(DcDReadWrite, PropertyMismatch)
75+
<< TEXT("Array") << Ctx.TopProperty().GetFName() << Ctx.TopProperty().GetClassName();
76+
77+
FDcJsonWriter* JsonWriter = Ctx.Writer->CastByIdChecked<FDcJsonWriter>();
78+
79+
DC_TRY(Ctx.Reader->ReadArrayRoot());
80+
81+
EDcDataEntry CurPeek;
82+
while (true)
83+
{
84+
DC_TRY(Ctx.Reader->PeekRead(&CurPeek));
85+
if (CurPeek == EDcDataEntry::ArrayEnd)
86+
break;
87+
88+
DC_TRY(DcSerializeUtils::RecursiveSerialize(Ctx));
89+
90+
JsonWriter->CancelWriteComma();
91+
JsonWriter->Sb << TCHAR('\n');
92+
}
93+
94+
DC_TRY(Ctx.Reader->ReadArrayEnd());
95+
96+
return DcOk();
97+
})
98+
);
99+
}
100+
101+
} // namespace NDJSONDetails
102+
103+
FDcResult LoadNDJSON(const TCHAR* Str, FDcPropertyDatum Datum)
104+
{
105+
using namespace NDJSONDetails;
106+
107+
FDcJsonReader Reader(Str);
108+
FDcPropertyWriter Writer(Datum);
109+
110+
LazyInitializeDeserializer();
111+
112+
FDcDeserializeContext Ctx;
113+
Ctx.Reader = &Reader;
114+
Ctx.Writer = &Writer;
115+
Ctx.Deserializer = &Deserializer.GetValue();
116+
Ctx.Properties.Add(Datum.Property);
117+
DC_TRY(Ctx.Prepare());
118+
DC_TRY(Deserializer->Deserialize(Ctx));
119+
120+
return DcOk();
121+
}
122+
123+
124+
FDcResult SaveNDJSON(FDcPropertyDatum Datum, FString& OutStr)
125+
{
126+
using namespace NDJSONDetails;
127+
128+
FDcJsonWriter::ConfigType Config = {
129+
TEXT(" "),
130+
TEXT(" "),
131+
TEXT(""),
132+
TEXT(" "),
133+
false,
134+
false
135+
};
136+
137+
FDcJsonWriter Writer(Config);
138+
FDcPropertyReader Reader(Datum);
139+
140+
LazyInitializeSerializer();
141+
142+
FDcSerializeContext Ctx;
143+
Ctx.Reader = &Reader;
144+
Ctx.Writer = &Writer;
145+
Ctx.Serializer = &Serializer.GetValue();
146+
DC_TRY(Ctx.Prepare());
147+
DC_TRY(Serializer->Serialize(Ctx));
148+
149+
OutStr = Writer.Sb.ToString();
150+
return DcOk();
151+
}
152+
153+
} // namespace DcExtra
154+
155+
DC_TEST("DataConfig.Extra.SerDe.NDJSON")
156+
{
157+
using namespace DcExtra;
158+
159+
TArray<FDcExtraSimpleStruct> Dest;
160+
161+
FString Str = TEXT(R"(
162+
163+
{ "Name" : "Foo", "Id" : 1, "Type" : "Alpha" }
164+
{ "Name" : "Bar", "Id" : 2, "Type" : "Beta" }
165+
{ "Name" : "Baz", "Id" : 3, "Type" : "Gamma" }
166+
167+
)");
168+
169+
170+
UTEST_OK("Extra NDJSON", LoadNDJSON(*Str, Dest));
171+
172+
FString SavedStr;
173+
UTEST_OK("Extra NDJSON", SaveNDJSON(Dest, SavedStr));
174+
175+
UTEST_EQUAL("Extra NDJSON", SavedStr, DcAutomationUtils::DcReindentStringLiteral(Str));
176+
return true;
177+
};

0 commit comments

Comments
 (0)