A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
DlgConfigParser.cpp
Go to the documentation of this file.
1// Copyright Csaba Molnar, Daniel Butum. All Rights Reserved.
3
4#include "Logging/LogMacros.h"
5#include "Misc/FileHelper.h"
6#include "Misc/Paths.h"
7#include "UObject/UnrealType.h"
8#include "UObject/EnumProperty.h"
9#include "UObject/UObjectIterator.h"
10#include "UObject/TextProperty.h"
11
12#include "NYReflectionHelper.h"
13
14DEFINE_LOG_CATEGORY(LogDlgConfigParser);
15
17FDlgConfigParser::FDlgConfigParser(const FString InPreTag) :
18 PreTag(InPreTag)
19{
20}
21
23FDlgConfigParser::FDlgConfigParser(const FString& FilePath, const FString& InPreTag) :
24 PreTag(InPreTag)
25{
26 InitializeParser(FilePath);
27}
28
30void FDlgConfigParser::InitializeParser(const FString& FilePath)
31{
32 FileName = "";
33 String = "";
34 From = 0;
35 Len = 0;
36 bHasValidWord = false;
37
38 if (!FFileHelper::LoadFileToString(String, *FilePath))
39 {
40 UE_LOG(LogDlgConfigParser, Error, TEXT("Failed to load config file %s"), *FilePath)
41 }
42 else
43 {
44 // find first word
46 }
47
48 FileName = FPaths::GetBaseFilename(FilePath, true);
49}
50
53{
54 FileName = "";
55 String = Text;
56 From = 0;
57 Len = 0;
58 bHasValidWord = false;
60}
61
63void FDlgConfigParser::ReadAllProperty(const UStruct* ReferenceClass, void* TargetObject, UObject* DefaultObjectOuter)
64{
65 while (ReadProperty(ReferenceClass, TargetObject, DefaultObjectOuter));
66}
67
70{
71 From = 0;
72 Len = 0;
73 bHasValidWord = false;
75}
76
78bool FDlgConfigParser::ReadProperty(const UStruct* ReferenceClass, void* TargetObject, UObject* DefaultObjectOuter)
79{
80 if (!bHasValidWord)
81 {
82 return false;
83 }
84 check(From < String.Len());
85
86 const FString PropertyName = GetActiveWord();
87 auto* PropertyBase = ReferenceClass->FindPropertyByName(*PropertyName);
88 if (PropertyBase != nullptr)
89 {
90 // check primitive types and enums
91 if (TryToReadPrimitiveProperty(TargetObject, PropertyBase) || TryToReadEnum(TargetObject, PropertyBase))
92 {
93 return true;
94 }
95
96 // check <MAP>
97 auto* MapProperty = FNYReflectionHelper::CastProperty<FNYMapProperty>(PropertyBase);
98 if (MapProperty != nullptr)
99 {
100 return ReadMap(TargetObject, *MapProperty, DefaultObjectOuter);
101 }
102
103 // check <SET>
104 auto* SetProperty = FNYReflectionHelper::CastProperty<FNYSetProperty>(PropertyBase);
105 if (SetProperty != nullptr)
106 {
107 return ReadSet(TargetObject, *SetProperty, DefaultObjectOuter);
108 }
109 }
110
111 auto* ComplexPropBase = ReferenceClass->FindPropertyByName(*PropertyName);
112
113 // struct
114 if (auto* StructProperty = FNYReflectionHelper::SmartCastProperty<FNYStructProperty>(ComplexPropBase))
115 {
116 return ReadComplexProperty<FNYStructProperty>(TargetObject,
117 ComplexPropBase,
118 StructProperty->Struct,
119 [](void* Ptr, const UClass*, UObject*) { return Ptr; },
120 DefaultObjectOuter);
121 }
122
123 // check complex object - type name has to be here as well (dynamic array)
124 const FString TypeName = PreTag + PropertyName;
125 if (!FindNextWord("block name"))
126 {
127 return false;
128 }
129
130 const bool bLoadByRef = IsNextWordString();
131 const FString VariableName = GetActiveWord();
132
133 // check if it is stored as reference
134 if (bLoadByRef)
135 {
136 // sanity check: if it is not an uobject** we should not try to write it!
137 if (FNYReflectionHelper::SmartCastProperty<FNYObjectProperty>(ComplexPropBase) == nullptr)
138 {
139 return false;
140 }
141
142 auto* ObjectPtrPtr = static_cast<UObject**>(ComplexPropBase->template ContainerPtrToValuePtr<void>(TargetObject));
143 *ObjectPtrPtr = nullptr; // reset first
144 if (!VariableName.TrimStartAndEnd().IsEmpty()) // null reference?
145 {
146 *ObjectPtrPtr = StaticLoadObject(UObject::StaticClass(), DefaultObjectOuter, *VariableName);
147 }
148 FindNextWord();
149 return true;
150 }
151
152 // UObject is in the format:
153 // - not nullptr - UObjectType PropertyName
154 // - nullptr - PropertyName ""
155 if (bHasNullptr)
156 {
157 ComplexPropBase = ReferenceClass->FindPropertyByName(*PropertyName);
158 }
159 else
160 {
161 ComplexPropBase = ReferenceClass->FindPropertyByName(*VariableName);
162 }
163 if (auto* ObjectProperty = FNYReflectionHelper::SmartCastProperty<FNYObjectProperty>(ComplexPropBase))
164 {
165 const UClass* Class = SmartGetPropertyClass(ComplexPropBase, TypeName);
166 if (Class == nullptr)
167 {
168 return false;
169 }
170 auto ObjectInitializer = std::bind(&FDlgConfigParser::OnInitObject, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
171 return ReadComplexProperty<FNYObjectProperty>(TargetObject, ComplexPropBase, Class, ObjectInitializer, DefaultObjectOuter);
172 }
173
174 UE_LOG(LogDlgConfigParser, Warning, TEXT("Invalid token `%s` in script `%s` (line: %d) (Property expected for PropertyName = `%s`)"),
175 *GetActiveWord(), *FileName, GetActiveLineNumber(), *PropertyName);
176 FindNextWord();
177 return false;
178}
179
181bool FDlgConfigParser::ReadPurePropertyBlock(void* TargetObject, const UStruct* ReferenceClass, bool bBlockStartAlreadyRead, UObject* Outer)
182{
183 if (!bBlockStartAlreadyRead && !FindNextWordAndCheckIfBlockStart(ReferenceClass->GetName()))
184 {
185 return false;
186 }
187
188 // parse precondition properties
189 FindNextWord();
190 while (!CheckIfBlockEnd(ReferenceClass->GetName()))
191 {
192 if (!bHasValidWord)
193 {
194 return false;
195 }
196
197 ReadProperty(ReferenceClass, TargetObject, Outer);
198 }
199
200 FindNextWord();
201 return true;
202}
203
206{
207 if (!HasValidWord())
208 {
209 return false;
210 }
211
212 const FString FloatString = String.Mid(From, Len);
213 if (FloatString.Len() == 0 || !FloatString.IsNumeric())
214 {
215 return false;
216 }
217
218 FloatValue = FCString::Atof(*FloatString);
219 return true;
220}
221
223FString FDlgConfigParser::ConstructConfigFile(const UStruct* ReferenceType, void* SourceObject)
224{
225 FString String;
226 ConstructConfigFileInternal(ReferenceType, 0, SourceObject, String);
227 return String;
228}
229
232{
233 if (bHasNullptr)
234 {
235 return true;
236 }
237
238 int32 Index = From + Len;
239 // Skip whitespaces
240 while (Index < String.Len() && FChar::IsWhitespace(String[Index]))
241 {
242 Index++;
243 }
244
245 return Index < String.Len() && String[Index] == '"';
246}
247
250{
251 const int32 Index = From - 1;
252 return String.IsValidIndex(Index) && String[Index] == '"';
253}
254
257{
258 bHasNullptr = false;
259 From += Len;
260
261 // Skip " (aka the open of string)
262 if (bActiveIsString)
263 {
264 From++;
265 }
266 bActiveIsString = false;
267
268 // Skip whitespaces
269 while (From < String.Len() && FChar::IsWhitespace(String[From]))
270 {
271 From++;
272 }
273
274 // Oh noeeeees
275 if (From >= String.Len())
276 {
277 bHasValidWord = false;
278 return false;
279 }
280
281 // Handle "" as special empty string
282 if (From + 1 < String.Len() && String[From] == '"' && String[From + 1] == '"')
283 {
284 From += 2; // skip both characters for the next string
285 Len = 0;
286 bHasValidWord = true;
287 bHasNullptr = true;
288 return true;
289 }
290
291 // Handle special string case - read everything between two "
292 if (String[From] == '"')
293 {
294 Len = 1;
295 bActiveIsString = true;
296 // Find the closing "
297 while (From + Len < String.Len() && String[From + Len] != '"')
298 {
299 Len++;
300 }
301
302 // Do not include the "" in the range
303 From += 1;
304 Len -= 1;
305
306 // Something very bad happened
307 if (Len <= 0)
308 {
309 bHasValidWord = false;
310 return false;
311 }
312
313 bHasValidWord = true;
314 return true;
315 }
316
317 Len = 0;
318 // Is block begin/end
319 if (String[From] == '{' || String[From] == '}')
320 {
321 Len = 1;
322 }
323 else
324 {
325 // Count until we reach a whitespace char OR EOF
326 while (From + Len < String.Len() && !FChar::IsWhitespace(String[From + Len]))
327 {
328 Len++;
329 }
330 }
331
332 // Skip comments //
333 if (Len > 1 && String[From] == '/' && String[From + 1] == '/')
334 {
335 // Advance past this line
336 while (From < String.Len() && String[From] != '\n' && String[From] != '\r')
337 {
338 From++;
339 }
340
341 // Use recursion to go to the next line
342 Len = 0;
343 return FindNextWord();
344 }
345
346 // Phew, valid word
347 bHasValidWord = true;
348 return true;
349}
350
352bool FDlgConfigParser::FindNextWord(const FString& ExpectedStuff)
353{
354 const bool bNotEof = FindNextWord();
355 if (!bNotEof)
356 {
357 UE_LOG(LogDlgConfigParser, Warning, TEXT("Unexpected end of file while reading %s (expected: %s)"), *FileName, *ExpectedStuff);
358 }
359
360 return bNotEof;
361}
362
365{
366 if (!FindNextWord() || !CompareToActiveWord("{"))
367 {
368 UE_LOG(LogDlgConfigParser, Warning, TEXT("Block start signal expected but not found for %s block in script %s (line: %d)"),
369 *BlockName, *FileName, GetActiveLineNumber());
370 return false;
371 }
372 return true;
373}
374
377{
378 if (!FindNextWord())
379 {
380 UE_LOG(LogDlgConfigParser, Warning, TEXT("End of file found but block %s is not yet closed in script %s (line: %d)"),
381 *BlockName, *FileName, GetActiveLineNumber());
382 return false;
383 }
384 return Len == 1 && String[From] == '}';
385}
386
388bool FDlgConfigParser::CheckIfBlockEnd(const FString& BlockName)
389{
390 if (!bHasValidWord)
391 {
392 UE_LOG(LogDlgConfigParser, Warning, TEXT("End of file found but block %s is not yet closed in script %s (line: %d)"),
393 *BlockName, *FileName, GetActiveLineNumber());
394 return false;
395 }
396 return Len == 1 && String[From] == '}';
397}
398
400bool FDlgConfigParser::CompareToActiveWord(const FString& StringToCompare) const
401{
402 // Length differs?
403 if (!bHasValidWord || StringToCompare.Len() != Len)
404 {
405 return false;
406 }
407
408 // Content differs?
409 const TCHAR* SubStr = &String[From];
410 for (int32 i = 0; i < Len; ++i)
411 {
412 if (SubStr[i] != StringToCompare[i])
413 {
414 return false;
415 }
416 }
417
418 return true;
419}
420
423{
424 if (!bHasValidWord)
425 {
426 return INDEX_NONE;
427 }
428
429 int32 LineCount = 1;
430 for (int32 i = 0; i < String.Len() && i < From; ++i)
431 {
432 switch (String[i])
433 {
434 case '\r':
435 // let's handle '\r\n too
436 if (i + 1 < String.Len() && String[i + 1] == '\n')
437 ++i;
438 case '\n':
439 ++LineCount;
440 break;
441
442 default:
443 break;
444 }
445 }
446
447 return LineCount;
448}
449
451void FDlgConfigParser::ConstructConfigFileInternal(const UStruct* ReferenceType, int32 TabCount, void* SourceObject, FString& OutString)
452{
453 for (auto* Field = FNYReflectionHelper::GetStructChildren(ReferenceType); Field != nullptr; Field = Field->Next)
454 {
455 auto* BoolProp = FNYReflectionHelper::CastProperty<FNYBoolProperty>(Field);
456 if (BoolProp != nullptr)
457 {
458 OutString += BoolProp->GetName() + " " + (BoolProp->GetPropertyValue_InContainer(SourceObject) ? "True\n" : "False\n");
459 }
460 }
461}
462
464bool FDlgConfigParser::TryToReadPrimitiveProperty(void* TargetObject, FNYProperty* PropertyBase)
465{
466 if (ReadPrimitiveProperty<bool, FNYBoolProperty>(TargetObject, PropertyBase, std::bind(&FDlgConfigParser::GetAsBool, this), "Bool", false))
467 {
468 return true;
469 }
470 if (ReadPrimitiveProperty<float, FNYFloatProperty>(TargetObject, PropertyBase, std::bind(&FDlgConfigParser::GetAsFloat, this), "float", false))
471 {
472 return true;
473 }
474 if (ReadPrimitiveProperty<int32, FNYIntProperty>(TargetObject, PropertyBase, std::bind(&FDlgConfigParser::GetAsInt32, this), "int32", false))
475 {
476 return true;
477 }
478 if (ReadPrimitiveProperty<int64, FNYInt64Property>(TargetObject, PropertyBase, std::bind(&FDlgConfigParser::GetAsInt64, this), "int64", false))
479 {
480 return true;
481 }
482 if (ReadPrimitiveProperty<FName, FNYNameProperty>(TargetObject, PropertyBase, std::bind(&FDlgConfigParser::GetAsName, this), "FName", false))
483 {
484 return true;
485 }
486 if (ReadPrimitiveProperty<FString, FNYStrProperty>(TargetObject, PropertyBase, std::bind(&FDlgConfigParser::GetAsString, this), "FString", true))
487 {
488 return true;
489 }
490 if (ReadPrimitiveProperty<FText, FNYTextProperty>(TargetObject, PropertyBase, std::bind(&FDlgConfigParser::GetAsText, this), "FText", true))
491 {
492 return true;
493 }
494
495 return false;
496}
497
499bool FDlgConfigParser::TryToReadEnum(void* Target, FNYProperty* PropertyBase)
500{
501 auto OnGetAsEnum = [this, &PropertyBase]() -> uint8
502 {
503 FName Value = NAME_None;
504 if (Len <= 0)
505 {
506 OnInvalidValue("FName");
507 }
508 else
509 {
510 Value = FName(*String.Mid(From, Len));
511 }
512
513 auto* Prop = FNYReflectionHelper::SmartCastProperty<FNYEnumProperty>(PropertyBase);
514 if (Prop == nullptr || Prop->GetEnum() == nullptr)
515 {
516 return 0;
517 }
518
519 check(FNYReflectionHelper::CastProperty<FNYByteProperty>(Prop->GetUnderlyingProperty()));
520 return uint8(Prop->GetEnum()->GetIndexByName(Value));
521 };
522
523 // enum can't be pure array atm!!!
524 auto* EnumProp = FNYReflectionHelper::CastProperty<FNYEnumProperty>(PropertyBase);
525 if (EnumProp != nullptr)
526 {
527 FindNextWord();
528 if (bHasValidWord)
529 {
530 // ContainerPtrToValuePtr has to be called on the enum, not on the underlying prop!!!
531 void* Value = EnumProp->ContainerPtrToValuePtr<uint8>(Target);
532 EnumProp->GetUnderlyingProperty()->SetIntPropertyValue(Value, static_cast<int64>(OnGetAsEnum()));
533 }
534 else
535 {
536 UE_LOG(LogDlgConfigParser, Warning, TEXT("Unexpected end of file while enum value was expected (config %s)"), *FileName);
537 }
538
539 FindNextWord();
540 return true;
541 }
542
543 return false;
544}
545
547bool FDlgConfigParser::ReadSet(void* TargetObject, FNYSetProperty& Property, UObject* DefaultObjectOuter)
548{
549 FScriptSetHelper Helper(&Property, Property.ContainerPtrToValuePtr<uint8>(TargetObject));
550 Helper.EmptyElements();
551
552 if (!FindNextWordAndCheckIfBlockStart("Set block"))
553 {
554 return false;
555 }
556
557 while (!FindNextWordAndCheckIfBlockEnd("Set block"))
558 {
559 const int32 Index = Helper.AddDefaultValue_Invalid_NeedsRehash();
560 bool bDone = false;
561 uint8* ElementPtr = Helper.GetElementPtr(Index);
562 if (FNYReflectionHelper::CastProperty<FNYBoolProperty>(Helper.ElementProp)) { *(bool*)ElementPtr = GetAsBool(); bDone = true; }
563 else if (FNYReflectionHelper::CastProperty<FNYFloatProperty>(Helper.ElementProp)) { *(float*)ElementPtr = GetAsFloat(); bDone = true; }
564 else if (FNYReflectionHelper::CastProperty<FNYIntProperty>(Helper.ElementProp)) { *(int32*)ElementPtr = GetAsInt32(); bDone = true; }
565 else if (FNYReflectionHelper::CastProperty<FNYInt64Property>(Helper.ElementProp)) { *(int64*)ElementPtr = GetAsInt64(); bDone = true; }
566 else if (FNYReflectionHelper::CastProperty<FNYNameProperty>(Helper.ElementProp)) { *(FName*)ElementPtr = GetAsName(); bDone = true; }
567 else if (FNYReflectionHelper::CastProperty<FNYStrProperty>(Helper.ElementProp)) { *(FString*)ElementPtr = GetAsString(); bDone = true; }
568 else if (FNYReflectionHelper::CastProperty<FNYTextProperty>(Helper.ElementProp)) { *(FText*)ElementPtr = GetAsText(); bDone = true; }
569 // else if (Cast<FNYReflectionHelper::CastProperty>(Helper.ElementProp)) { *(uint8*)ElementPtr = OnGetAsEnum(); bDone = true; } // would not work, check enum above
570
571 if (!bDone)
572 {
573 UE_LOG(LogDlgConfigParser, Warning, TEXT("Unsupported set element type %s in script %s(:%d)"),
574 *Helper.ElementProp->GetName(), *FileName, GetActiveLineNumber());
575 return false;
576 }
577 Helper.Rehash();
578 }
579 FindNextWord();
580 return true;
581}
582
584bool FDlgConfigParser::ReadMap(void* TargetObject, FNYMapProperty& Property, UObject* DefaultObjectOuter)
585{
586 FScriptMapHelper Helper(&Property, Property.ContainerPtrToValuePtr<uint8>(TargetObject));
587 Helper.EmptyValues();
588
589 if (!FindNextWordAndCheckIfBlockStart("Map block") || !FindNextWord("map entry"))
590 {
591 return false;
592 }
593
594 while (!CheckIfBlockEnd("Map block"))
595 {
596 const int32 Index = Helper.AddDefaultValue_Invalid_NeedsRehash();
597 void* Ptrs[] = { Helper.GetKeyPtr(Index), Helper.GetValuePtr(Index) };
598 FNYProperty* Props[] = { Helper.KeyProp, Helper.ValueProp };
599 bool bDone = false;
600
601 for (int32 i = 0; i < 2; ++i)
602 {
603 if (FNYReflectionHelper::CastProperty<FNYBoolProperty>(Props[i])) { *(bool*)Ptrs[i] = GetAsBool(); bDone = true; }
604 else if (FNYReflectionHelper::CastProperty<FNYFloatProperty>(Props[i])) { *(float*)Ptrs[i] = GetAsFloat(); bDone = true; }
605 else if (FNYReflectionHelper::CastProperty<FNYIntProperty>(Props[i])) { *(int32*)Ptrs[i] = GetAsInt32(); bDone = true; }
606 else if (FNYReflectionHelper::CastProperty<FNYInt64Property>(Props[i])) { *(int64*)Ptrs[i] = GetAsInt64(); bDone = true; }
607 else if (FNYReflectionHelper::CastProperty<FNYNameProperty>(Props[i])) { *(FName*)Ptrs[i] = GetAsName(); bDone = true; }
608 else if (FNYReflectionHelper::CastProperty<FNYStrProperty>(Props[i])) { *(FString*)Ptrs[i] = GetAsString(); bDone = true; }
609 else if (FNYReflectionHelper::CastProperty<FNYTextProperty>(Props[i])) { *(FText*)Ptrs[i] = GetAsText(); bDone = true; }
610 else if (i == 1 && bHasNullptr) { bDone = true; } // Value is nullptr, ignore
611 // else if (FNYReflectionHelper::CastProperty<FNYByteProperty>(Props[i])) { *(uint8*)Ptrs[i] = OnGetAsEnum(); bDone = true; } // would not work, check enum above
612
613 auto* StructVal = FNYReflectionHelper::CastProperty<FNYStructProperty>(Props[i]);
614 if (StructVal != nullptr)
615 {
616 if (!CompareToActiveWord("{"))
617 {
618 UE_LOG(LogDlgConfigParser, Warning, TEXT("Syntax error: missing struct block start '{' in script %s(:%d)"),
620 return false;
621 }
622 if (!ReadPurePropertyBlock(Ptrs[i], StructVal->Struct, true, DefaultObjectOuter))
623 {
624 return false;
625 }
626 }
627 else
628 {
629 if (!bDone)
630 {
631 UE_LOG(LogDlgConfigParser, Warning, TEXT("Invalid map type %s in script `%s` (:%d)"), *Helper.KeyProp->GetName(), *FileName, GetActiveLineNumber());
632 return false;
633 }
634 bDone = false;
635 if (!FindNextWord("Map Key or Value or End"))
636 {
637 return false;
638 }
639 }
640 }
641 Helper.Rehash();
642 } // while (!CheckIfBlockEnd("Map block"))
643
644 FindNextWord();
645 return true;
646}
647
648void* FDlgConfigParser::OnInitObject(void* ValuePtr, const UClass* ChildClass, UObject* OuterInit)
649{
650 if (ChildClass != nullptr)
651 {
652 UObject** Value = (UObject**)ValuePtr;
653 *Value = nullptr;
654 *Value = CreateNewUObject(ChildClass, OuterInit);
655 return *Value;
656 }
657 UE_LOG(LogDlgConfigParser, Warning, TEXT("OnInitValue called without class!"));
658 return nullptr;
659}
660
662const UClass* FDlgConfigParser::SmartGetPropertyClass(FNYProperty* Property, const FString& TypeName)
663{
664 auto* ObjectProperty = FNYReflectionHelper::SmartCastProperty<FNYObjectProperty>(Property);
665 check(ObjectProperty != nullptr);
666
667 const UClass* Class = nullptr;
668 if (FNYReflectionHelper::CastProperty<FNYArrayProperty>(Property) != nullptr)
669 {
670 Class = ObjectProperty->PropertyClass;
671 }
672 else
673 {
674 Class = GetChildClassFromName(ObjectProperty->PropertyClass, TypeName);
675 }
676
677 if (Class == nullptr)
678 {
679 UE_LOG(LogDlgConfigParser, Warning, TEXT("Could not find class `%s` for `%s` in config `%s` (Line=%d)"),
680 *TypeName, *ObjectProperty->GetName(), *FileName, GetActiveLineNumber());
681 }
682
683 return Class;
684}
685
687void FDlgConfigParser::OnInvalidValue(const FString& PropType) const
688{
689 if (bHasValidWord)
690 {
691 const int32 LineNumber = GetActiveLineNumber();
692 UE_LOG(LogDlgConfigParser, Warning, TEXT("Invalid %s property value %s in script %s (line %d)"),
693 *PropType, *String.Mid(From, Len), *FileName, LineNumber);
694 }
695 else
696 UE_LOG(LogDlgConfigParser, Warning, TEXT("Unexepcted end of file while expecting %s value in script %s"), *PropType, *FileName);
697}
698
701{
702 bool bValue = false;
703 if (CompareToActiveWord("True"))
704 bValue = true;
705 else if (!CompareToActiveWord("False"))
706 OnInvalidValue("Bool");
707 return bValue;
708}
709
712{
713 float Value = 0.0f;
714 if (!GetActiveWordAsFloat(Value))
715 OnInvalidValue("Float");
716 return Value;
717}
720{
721 int32 Value = 0;
722 const FString IntString = String.Mid(From, Len);
723 if (IntString.Len() == 0 || (!IntString.IsNumeric()))
724 OnInvalidValue("int32");
725 else
726 Value = FCString::Atoi(*IntString);
727 return Value;
728}
729
732{
733 int64 Value = 0;
734 const FString IntString = String.Mid(From, Len);
735 if (IntString.Len() == 0 || (!IntString.IsNumeric()))
736 OnInvalidValue("int64");
737 else
738 Value = FCString::Atoi64(*IntString);
739 return Value;
740}
741
744{
745 FName Value = NAME_None;
746 if (Len <= 0)
747 OnInvalidValue("FName");
748 else
749 Value = FName(*String.Mid(From, Len));
750 return Value;
751}
752
755{
756 if (Len > 0)
757 return String.Mid(From, Len);
758
759 return "";
760}
761
764{
765 FString Input;
766 if (Len > 0)
767 Input = String.Mid(From, Len);
768
769 return FText::FromString(Input);
770}
DEFINE_LOG_CATEGORY(LogDlgConfigParser)
UProperty FNYProperty
UMapProperty FNYMapProperty
USetProperty FNYSetProperty
int32 GetAsInt32() const
float GetAsFloat() const
static void ConstructConfigFileInternal(const UStruct *ReferenceType, int32 TabCount, void *SourceObject, FString &OutString)
bool IsActualWordString() const
bool GetActiveWordAsFloat(float &FloatValue) const
bool CompareToActiveWord(const FString &StringToCompare) const
FString GetActiveWord() const
static FString ConstructConfigFile(const UStruct *ReferenceType, void *SourceObject)
bool IsNextWordString() const
void InitializeParser(const FString &FilePath) override
bool FindNextWordAndCheckIfBlockEnd(const FString &BlockName)
bool CheckIfBlockEnd(const FString &BlockName)
bool ReadPurePropertyBlock(void *TargetObject, const UStruct *ReferenceClass, bool bBlockStartAlreadyRead=false, UObject *DefaultObjectOuter=nullptr)
FName GetAsName() const
void ReadAllProperty(const UStruct *ReferenceClass, void *TargetObject, UObject *DefaultObjectOuter=nullptr) override
void * OnInitObject(void *ValuePtr, const UClass *ChildClass, UObject *OuterInit)
bool ReadProperty(const UStruct *ReferenceClass, void *TargetObject, UObject *DefaultObjectOuter=nullptr)
FString GetAsString() const
FText GetAsText() const
bool TryToReadPrimitiveProperty(void *Target, FNYProperty *PropertyBase)
bool FindNextWordAndCheckIfBlockStart(const FString &BlockName)
const FString PreTag
bool ReadMap(void *TargetObject, FNYMapProperty &Property, UObject *DefaultObjectOuter)
void InitializeParserFromString(const FString &Text) override
FDlgConfigParser(const FString InPreTag="")
const UClass * SmartGetPropertyClass(FNYProperty *Property, const FString &TypeName)
bool ReadSet(void *TargetObject, FNYSetProperty &Property, UObject *DefaultObjectOuter)
bool TryToReadEnum(void *TargetObject, FNYProperty *PropertyBase)
int32 GetActiveLineNumber() const
int64 GetAsInt64() const
void OnInvalidValue(const FString &PropType) const
bool HasValidWord() const
static FORCEINLINE UField * GetStructChildren(const UStruct *Struct)
const UClass * GetChildClassFromName(const UClass *ParentClass, const FString &Name)
Definition IDlgParser.h:45
static UObject * CreateNewUObject(const UClass *StructDefinition, UObject *ObjectOuter)
Definition IDlgParser.h:70