Goran Lazarevski 669cf5383b Lucky World source code
2025-03-18 19:25:25 +01:00

1285 lines
37 KiB
C++

// Copyright 2023 RLoris
#include "FileHelperBPLibrary.h"
#include "HAL/PlatformFileManager.h"
#include "HAL/FileManager.h"
#include "Misc/FileHelper.h"
#include "Misc/Base64.h"
#include "Math/Color.h"
#include "Misc/ConfigCacheIni.h"
#include "Engine/DataTable.h"
#include "Internationalization/Regex.h"
#include "Serialization/Csv/CsvParser.h"
#include "UObject/TextProperty.h"
class FCustomFileVisitor : public IPlatformFile::FDirectoryVisitor
{
public:
FString BasePath;
TArray<FString>& Nodes;
FString Filter;
FRegexPattern CustomPattern;
bool bFile = true;
bool bDirectory = true;
FCustomFileVisitor(FString& Path, TArray<FString>& Paths, const FString& Pattern, bool File, bool Directory) : BasePath(Path), Nodes(Paths), Filter(Pattern), CustomPattern(Pattern), bFile(File), bDirectory(Directory) {};
virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory);
};
FEnginePath UFileHelperBPLibrary::GetEngineDirectories()
{
FEnginePath P;
P.Directory = FPaths::ConvertRelativePathToFull(FPaths::EngineDir());
P.Config = FPaths::ConvertRelativePathToFull(FPaths::EngineConfigDir());
P.Content = FPaths::ConvertRelativePathToFull(FPaths::EngineContentDir());
P.Intermediate = FPaths::ConvertRelativePathToFull(FPaths::EngineIntermediateDir());
P.Plugins = FPaths::ConvertRelativePathToFull(FPaths::EnginePluginsDir());
P.Saved =FPaths::ConvertRelativePathToFull( FPaths::EngineSavedDir());
P.User = FPaths::ConvertRelativePathToFull(FPaths::EngineUserDir());
P.DefaultLayout = FPaths::ConvertRelativePathToFull(FPaths::EngineDefaultLayoutDir());
P.PlatformExtensions = FPaths::ConvertRelativePathToFull(FPaths::EnginePlatformExtensionsDir());
P.UserLayout = FPaths::ConvertRelativePathToFull(FPaths::EngineUserLayoutDir());
return P;
}
FProjectPath UFileHelperBPLibrary::GetProjectDirectories()
{
FProjectPath P;
P.Directory = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir());
P.Config = FPaths::ConvertRelativePathToFull(FPaths::ProjectConfigDir());
P.Content = FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir());
P.Intermediate = FPaths::ConvertRelativePathToFull(FPaths::ProjectIntermediateDir());
P.Log = FPaths::ConvertRelativePathToFull(FPaths::ProjectLogDir());
P.Mods = FPaths::ConvertRelativePathToFull(FPaths::ProjectModsDir());
P.Plugins = FPaths::ConvertRelativePathToFull(FPaths::ProjectPluginsDir());
P.Saved = FPaths::ConvertRelativePathToFull(FPaths::ProjectSavedDir());
P.User = FPaths::ConvertRelativePathToFull(FPaths::ProjectUserDir());
P.PersistentDownload = FPaths::ConvertRelativePathToFull(FPaths::ProjectPersistentDownloadDir());
P.PlatformExtensions = FPaths::ConvertRelativePathToFull(FPaths::ProjectPlatformExtensionsDir());
return P;
}
bool UFileHelperBPLibrary::ReadText(FString Path, FString& Output)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (FileManager.FileExists(*Path))
{
return FFileHelper::LoadFileToString(Output, *Path);
}
return false;
}
bool UFileHelperBPLibrary::SaveText(FString Path, FString Text, FString& Error, bool Append, bool Force)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
FText ErrorFilename;
if (!FFileHelper::IsFilenameValidForSaving(Path, ErrorFilename))
{
Error = FString("Filename is not valid");
return false;
}
if (!FileManager.FileExists(*Path) || Append || Force)
{
return FFileHelper::SaveStringToFile(Text, *Path, FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), Append ? FILEWRITE_Append : FILEWRITE_None);
}
else
{
Error = FString("File already exists");
}
return false;
}
bool UFileHelperBPLibrary::SaveCSV(FString Path, TArray<FString> Headers, TArray<FString> Data, int32& Total, bool Force)
{
FString Output;
if (!UFileHelperBPLibrary::CSVToString(Output, Headers, Data, Total))
{
return false;
}
FString Error;
return UFileHelperBPLibrary::SaveText(Path, Output, Error, false, Force);
}
bool UFileHelperBPLibrary::ReadCSV(FString Path, TArray<FString>& Headers, TArray<FString>& Data, int32& Total, bool HeaderFirst)
{
Total = 0;
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.FileExists(*Path))
{
return false;
}
FString Result;
if (!FFileHelper::LoadFileToString(Result, *Path))
{
return false;
}
return UFileHelperBPLibrary::StringToCSV(Result, Headers, Data, Total, HeaderFirst);
// return UFileHelperBPLibrary::StringArrayToCSV(Result, Headers, Data, Total, ",", HeaderFirst);
}
bool UFileHelperBPLibrary::ReadLine(FString Path, FString Pattern, TArray<FString>& Lines)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.FileExists(*Path))
{
return false;
}
if (!Pattern.IsEmpty())
{
FRegexPattern CustomPattern(Pattern);
return FFileHelper::LoadFileToStringArrayWithPredicate(Lines, *Path, [CustomPattern](const FString& Line) {
FRegexMatcher CustomMatcher(CustomPattern, Line);
return CustomMatcher.FindNext();
});
}
return FFileHelper::LoadFileToStringArray(Lines, *Path);
}
bool UFileHelperBPLibrary::ReadLineRange(FString Path, TArray<FString>& Lines, int32 StartIdx, int32 EndIdx)
{
if (EndIdx != INDEX_NONE && EndIdx < StartIdx)
{
return false;
}
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.FileExists(*Path))
{
return false;
}
int32 LineCount = 0;
return FFileHelper::LoadFileToStringArrayWithPredicate(Lines, *Path, [&LineCount, StartIdx, EndIdx](const FString& Line)->bool{
const bool bRangeStart = LineCount >= StartIdx;
const bool bRangeEnd = EndIdx == INDEX_NONE || LineCount < EndIdx;
LineCount++;
return bRangeStart && bRangeEnd;
});
}
bool UFileHelperBPLibrary::SaveLine(FString Path, const TArray<FString>& Text, FString& Error, bool Append, bool Force)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
FText ErrorFilename;
if (!FFileHelper::IsFilenameValidForSaving(Path, ErrorFilename))
{
Error = FString("Filename is not valid");
return false;
}
if (!FileManager.FileExists(*Path) || Append || Force)
{
return FFileHelper::SaveStringArrayToFile(Text, *Path, FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), Append ? FILEWRITE_Append : FILEWRITE_None);
}
else
{
Error = FString("File already exists");
}
return false;
}
bool UFileHelperBPLibrary::ReadByte(FString Path, TArray<uint8>& Bytes)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.FileExists(*Path))
{
return false;
}
return FFileHelper::LoadFileToArray(Bytes, *Path);
}
FString UFileHelperBPLibrary::BytesToBase64(const TArray<uint8> Bytes)
{
return FBase64::Encode(Bytes);
}
bool UFileHelperBPLibrary::BytesFromBase64(const FString Source, TArray<uint8>& Out)
{
return FBase64::Decode(Source, Out);
}
bool UFileHelperBPLibrary::SaveByte(FString Path, const TArray<uint8>& Bytes, FString& Error, bool Append, bool Force)
{
IPlatformFile& file = FPlatformFileManager::Get().GetPlatformFile();
FText ErrorFilename;
if (!FFileHelper::IsFilenameValidForSaving(Path, ErrorFilename))
{
Error = FString("Filename is not valid");
return false;
}
if (!file.FileExists(*Path) || Append || Force)
{
return FFileHelper::SaveArrayToFile(Bytes, *Path, &IFileManager::Get(), Append ? FILEWRITE_Append : FILEWRITE_None);
}
else
{
Error = FString("File already exists");
}
return false;
}
bool UFileHelperBPLibrary::StringToCSV(FString Content, TArray<FString>& Headers, TArray<FString>& Data, int32& Total, bool HeaderFirst)
{
const FCsvParser Parser(Content);
TArray<TArray<const TCHAR*>> Rows = Parser.GetRows();
for (TArray<const TCHAR*> Row : Rows)
{
Total++;
for (FString Col : Row)
{
if (Total == 1 && HeaderFirst)
{
Headers.Add(Col);
}
else
{
Data.Add(Col);
}
}
}
return true;
// auto Result = SplitString(Content, LINE_TERMINATOR, ESearchCase::Type::IgnoreCase);
// return UFileHelperBPLibrary::StringArrayToCSV(Result, Headers, Data, Total, HeaderFirst);
}
bool UFileHelperBPLibrary::CSVToString(FString& Output, TArray<FString> Headers, TArray<FString> Data, int32& Total)
{
Total = 0;
FString Delimiter = ",";
if (Headers.Num() == 0)
{
return false;
}
if (Data.Num() % Headers.Num() != 0)
{
return false;
}
Output = TEXT("");
// Header row
for (FString Col : Headers)
{
if (Output.Len() > 0)
{
Output += Delimiter;
}
Output += (TEXT("\"") + Col.Replace(TEXT("\""), TEXT("\"\"")) + TEXT("\""));
}
Output += LINE_TERMINATOR;
FString Row = TEXT("");
int32 Count = 0;
// Data row
for (FString Col : Data)
{
Count++;
if (Row.Len() > 0)
{
Row += Delimiter;
}
Row += (TEXT("\"") + Col.Replace(TEXT("\""), TEXT("\"\"")) + TEXT("\""));
if (Count % Headers.Num() == 0)
{
Row += LINE_TERMINATOR;
Output += Row;
Row = "";
}
}
Total = (Data.Num() / Headers.Num()) + 1;
return true;
}
bool UFileHelperBPLibrary::StringArrayToCSV(TArray<FString> Lines, TArray<FString>& Headers, TArray<FString>& Data, int32& Total, FString Delimiter, bool HeaderFirst)
{
for (auto Line : Lines)
{
Total++;
if (!Line.Contains(TEXT("\"") + Delimiter + TEXT("\"")))
{
continue;
}
if (Total == 1 && HeaderFirst)
{
for (FString Col : UFileHelperBPLibrary::SplitString(Line, TEXT("\"") + Delimiter + TEXT("\""), ESearchCase::CaseSensitive))
{
Col.TrimQuotesInline();
Col.ReplaceInline(TEXT("\"\""), TEXT("\""));
Headers.Add(Col);
}
}
else
{
for (FString Col : UFileHelperBPLibrary::SplitString(Line, TEXT("\"") + Delimiter + TEXT("\""), ESearchCase::CaseSensitive))
{
Col.TrimQuotesInline();
Col.ReplaceInline(TEXT("\"\""), TEXT("\""));
Data.Add(Col);
}
}
}
return true;
}
bool UFileHelperBPLibrary::IsFile(FString Path)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
return FileManager.FileExists(*Path);
}
bool UFileHelperBPLibrary::IsDirectory(FString Path)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
return FileManager.DirectoryExists(*Path);
}
bool UFileHelperBPLibrary::IsValidFilename(FString Filename)
{
FText Error;
return FFileHelper::IsFilenameValidForSaving(*Filename, Error);
}
bool UFileHelperBPLibrary::IsValidPath(FString Path)
{
return FPaths::ValidatePath(Path);
}
bool UFileHelperBPLibrary::ValidateFilename(FString Filename, FString& ValidName)
{
ValidName = FPaths::MakeValidFileName(Filename);
return IsValidFilename(ValidName);
}
bool UFileHelperBPLibrary::SetReadOnlyFlag(FString FilePath, bool Flag)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
return FileManager.SetReadOnly(*FilePath, Flag);
}
bool UFileHelperBPLibrary::GetReadOnlyFlag(FString FilePath)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
return FileManager.IsReadOnly(*FilePath);
}
int64 UFileHelperBPLibrary::GetFileSize(FString FilePath)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
return FileManager.FileSize(*FilePath);
}
bool FCustomFileVisitor::Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory)
{
if ((bFile && !bIsDirectory) || (bDirectory && bIsDirectory))
{
FString RelativePath = FString(FilenameOrDirectory);
FPaths::MakePathRelativeTo(RelativePath, *BasePath);
if (!Filter.IsEmpty())
{
FRegexMatcher CustomMatcher(CustomPattern, RelativePath);
if (CustomMatcher.FindNext())
{
Nodes.Add(RelativePath);
}
}
else
{
Nodes.Add(RelativePath);
}
}
return true;
}
bool UFileHelperBPLibrary::ListDirectory(FString Path, FString Pattern, TArray<FString>& Nodes, bool ShowFile, bool ShowDirectory, bool Recursive)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.DirectoryExists(*Path))
{
return false;
}
if (!ShowDirectory && !ShowFile)
{
return true;
}
FString BasePath = FPaths::Combine(Path, TEXT("/"));
FCustomFileVisitor CustomFileVisitor(BasePath, Nodes, Pattern, ShowFile, ShowDirectory);
if (Recursive)
{
return FileManager.IterateDirectoryRecursively(*Path, CustomFileVisitor);
}
else
{
return FileManager.IterateDirectory(*Path, CustomFileVisitor);
}
}
bool UFileHelperBPLibrary::MakeDirectory(FString Path, bool Recursive)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (FileManager.DirectoryExists(*Path))
{
return true;
}
if (Recursive)
{
return FileManager.CreateDirectoryTree(*Path);
}
else
{
return FileManager.CreateDirectory(*Path);
}
}
bool UFileHelperBPLibrary::RemoveDirectory(FString Path, bool Recursive)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.DirectoryExists(*Path))
{
return true;
}
if (Recursive)
{
return FileManager.DeleteDirectoryRecursively(*Path);
}
else
{
return FileManager.DeleteDirectory(*Path);
}
}
bool UFileHelperBPLibrary::CopyDirectory(FString Source, FString Dest) // bool Force = false
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
FPaths::NormalizeDirectoryName(Dest);
if (!FileManager.DirectoryExists(*Source) && !FileManager.FileExists(*Source))
{
return false;
}
if (!FileManager.DirectoryExists(*Dest))
{
return false;
}
return FileManager.CopyDirectoryTree(*Dest, *Source, true);
}
bool UFileHelperBPLibrary::MoveDirectory(FString Source, FString Dest) // bool Force = false
{
FPaths::NormalizeDirectoryName(Source);
FPaths::NormalizeDirectoryName(Dest);
if (Dest.Equals(Source))
{
return true;
}
if (!UFileHelperBPLibrary::CopyDirectory(Source, Dest))
{
return false;
}
return UFileHelperBPLibrary::RemoveDirectory(Source, true);
}
bool UFileHelperBPLibrary::NodeStats(FString Path, FCustomNodeStat& Stats)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.DirectoryExists(*Path) && !FileManager.FileExists(*Path))
{
return false;
}
const FFileStatData Data = FileManager.GetStatData(*Path);
if (!Data.bIsValid)
{
return false;
}
Stats.CreationTime = Data.CreationTime;
Stats.FileSize = Data.FileSize;
Stats.IsDirectory = Data.bIsDirectory;
Stats.IsReadOnly = Data.bIsReadOnly;
Stats.LastAccessTime = Data.AccessTime;
Stats.ModificationTime = Data.ModificationTime;
return true;
}
bool UFileHelperBPLibrary::RemoveFile(FString Path)
{
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (FileManager.DirectoryExists(*Path))
{
return false;
}
if (!FileManager.FileExists(*Path))
{
return true;
}
return FileManager.DeleteFile(*Path);
}
bool UFileHelperBPLibrary::CopyFile(FString Source, FString Dest, bool Force)
{
FPaths::NormalizeFilename(Source);
FPaths::NormalizeFilename(Dest);
if (Dest.Equals(Source))
{
return true;
}
FText Error;
if (!FFileHelper::IsFilenameValidForSaving(*Dest, Error))
{
return false;
}
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.FileExists(*Source))
{
return false;
}
if (!Force && FileManager.FileExists(*Dest))
{
return false;
}
UFileHelperBPLibrary::RemoveFile(Dest);
return FileManager.CopyFile(*Dest, *Source);
}
bool UFileHelperBPLibrary::MoveFile(FString Source, FString Dest, bool Force)
{
FPaths::NormalizeFilename(Source);
FPaths::NormalizeFilename(Dest);
if (Dest.Equals(Source))
{
return true;
}
FText Error;
if (!FFileHelper::IsFilenameValidForSaving(*Dest, Error))
{
return false;
}
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.FileExists(*Source))
{
return false;
}
if (!Force && FileManager.FileExists(*Dest))
{
return false;
}
UFileHelperBPLibrary::RemoveFile(Dest);
return FileManager.MoveFile(*Dest, *Source);
}
bool UFileHelperBPLibrary::RenameFile(FString Path, FString NewName)
{
FText Error;
if (!FFileHelper::IsFilenameValidForSaving(*NewName, Error))
{
return false;
}
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
if (!FileManager.FileExists(*Path))
{
return false;
}
FString Clean = FPaths::GetCleanFilename(NewName);
FString Base = FPaths::GetPath(Path);
FString Output = FPaths::Combine(*Base, *Clean);
if (FileManager.FileExists(*Output) || FileManager.DirectoryExists(*Output))
{
return false;
}
return FileManager.MoveFile(*Output, *Path);
}
void UFileHelperBPLibrary::GetPathParts(FString Path, FString& PathPart, FString& BasePart, FString& ExtensionPart, FString& FileName)
{
PathPart = FPaths::GetPath(Path);
BasePart = FPaths::GetBaseFilename(Path);
ExtensionPart = FPaths::GetExtension(Path);
FileName = FPaths::GetCleanFilename(Path);
}
bool UFileHelperBPLibrary::DatatableToCSV(UDataTable* Table, FString& Output)
{
if (Table == nullptr || !Table->RowStruct)
{
return false;
}
// See Table->GetTableAsCSV
return UFileHelperBPLibrary::WriteTableToCSV(*Table, Output);
}
bool UFileHelperBPLibrary::DataTableToJSON(UDataTable* Table, FString& Output)
{
if (Table == nullptr || !Table->RowStruct)
{
return false;
}
// See Table->GetTableAsJSON
return UFileHelperBPLibrary::WriteTableToJSON(*Table, Output);
}
UDataTable* UFileHelperBPLibrary::CSVToDataTable(FString CSV, UScriptStruct* Struct, bool& Success)
{
Success = false;
if (Struct == nullptr)
{
return nullptr;
}
UDataTable* DataTable = NewObject<UDataTable>();
DataTable->RowStruct = Struct;
auto Result = DataTable->CreateTableFromCSVString(CSV);
if (Result.Num() == 0)
{
Success = true;
}
return DataTable;
}
UDataTable* UFileHelperBPLibrary::JSONToDataTable(FString JSON, UScriptStruct* Struct, bool& Success)
{
Success = false;
if (Struct == nullptr)
{
return nullptr;
}
UDataTable* DataTable = NewObject<UDataTable>();
DataTable->RowStruct = Struct;
auto Result = DataTable->CreateTableFromJSONString(JSON);
if (Result.Num() == 0)
{
Success = true;
}
return DataTable;
}
void UFileHelperBPLibrary::ReadConfig(FString FilePath, FString Section, FString Key, bool& Success, bool SingleLineArrayRead, UStruct*& OutValue, bool bLoadFromDisk)
{
checkNoEntry();
}
TArray<FString> UFileHelperBPLibrary::SplitString(FString String, FString Separator, ESearchCase::Type SearchCase)
{
FString LeftString;
FString RightString;
TArray<FString> Array;
bool Split = false;
do
{
Split = String.Split(Separator, &LeftString, &RightString, SearchCase);
if (Split)
{
Array.Add(LeftString);
}
else
{
Array.Add(String);
}
String = RightString;
} while (Split);
return Array;
}
bool UFileHelperBPLibrary::WriteConfigFile(FString Filename, FString Section, FString Key, FProperty* Type, void* Value, bool SingleLineArray, bool bWriteToDisk)
{
if (!GConfig)
{
return false;
}
if (FBoolProperty* BoolProperty = CastField<FBoolProperty>(Type))
{
GConfig->SetBool(*Section, *Key, *(static_cast<bool*>(Value)), Filename);
}
else if (FIntProperty* IntProperty = CastField<FIntProperty>(Type))
{
GConfig->SetInt(*Section, *Key, *(static_cast<int32*>(Value)), Filename);
}
else if (FStrProperty* StrProperty = CastField<FStrProperty>(Type))
{
GConfig->SetString(*Section, *Key, **(static_cast<FString*>(Value)), Filename);
}
else if (FFloatProperty* FloatProperty = CastField<FFloatProperty>(Type))
{
GConfig->SetFloat(*Section, *Key, *(static_cast<float*>(Value)), Filename);
}
else if (FDoubleProperty* DoubleProperty = CastField<FDoubleProperty>(Type))
{
GConfig->SetDouble(*Section, *Key, *(static_cast<double*>(Value)), Filename);
}
else if (FArrayProperty* ArrayProperty = CastField<FArrayProperty>(Type))
{
if (FStrProperty* ArrayInnerProperty = CastField<FStrProperty>(ArrayProperty->Inner))
{
TArray<FString>* Arr = (static_cast<TArray<FString>*>(Value));
if (SingleLineArray)
{
GConfig->SetSingleLineArray(*Section, *Key, *Arr, Filename);
}
else
{
GConfig->SetArray(*Section, *Key, *Arr, Filename);
}
}
else
{
return false;
}
}
else if (FTextProperty* TextProperty = CastField<FTextProperty>(Type))
{
GConfig->SetText(*Section, *Key, *(static_cast<FText*>(Value)), Filename);
}
else if (FStructProperty* StructProperty = CastField<FStructProperty>(Type))
{
if (StructProperty->Struct->IsNative())
{
static const FName RotatorType = TEXT("Rotator");
static const FName VectorType = TEXT("Vector");
static const FName LinearColorType = TEXT("LinearColor");
static const FName Vector4Type = TEXT("Vector4");
static const FName Vector2DType = TEXT("Vector2D");
const FName TypeName = StructProperty->Struct->GetFName();
if (TypeName == RotatorType)
{
GConfig->SetRotator(*Section, *Key, *(static_cast<FRotator*>(Value)), *Filename);
}
else if (TypeName == VectorType)
{
GConfig->SetVector(*Section, *Key, *(static_cast<FVector*>(Value)), *Filename);
}
else if (TypeName == LinearColorType)
{
GConfig->SetColor(*Section, *Key, *(static_cast<FColor*>(Value)), *Filename);
}
else if (TypeName == Vector4Type)
{
GConfig->SetVector4(*Section, *Key, *(static_cast<FVector4*>(Value)), *Filename);
}
else if (TypeName == Vector2DType)
{
GConfig->SetVector2D(*Section, *Key, *(static_cast<FVector2D*>(Value)), *Filename);
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
if (bWriteToDisk)
{
GConfig->Flush(false, Filename);
}
return true;
}
bool UFileHelperBPLibrary::ReadConfigFile(FString Filename, FString Section, FString Key, FProperty* Type, void* Value, bool SingleLineArray, bool bLoadFromDisk)
{
if (!GConfig)
{
return false;
}
if (bLoadFromDisk)
{
FConfigFile* ConfigFile = GConfig->FindConfigFile(Filename);
if (!ConfigFile)
{
return false;
}
ConfigFile->Read(Filename);
}
bool Success = false;
if (FBoolProperty* BoolProperty = CastField<FBoolProperty>(Type))
{
Success = GConfig->GetBool(*Section, *Key, *(static_cast<bool*>(Value)), Filename);
}
else if (FIntProperty* IntProperty = CastField<FIntProperty>(Type))
{
Success = GConfig->GetInt(*Section, *Key, *(static_cast<int32*>(Value)), Filename);
}
else if (FStrProperty* StrProperty = CastField<FStrProperty>(Type))
{
Success = GConfig->GetString(*Section, *Key, *(static_cast<FString*>(Value)), Filename);
}
else if (FFloatProperty* FloatProperty = CastField<FFloatProperty>(Type))
{
Success = GConfig->GetFloat(*Section, *Key, *(static_cast<float*>(Value)), Filename);
}
else if (FDoubleProperty* DoubleProperty = CastField<FDoubleProperty>(Type))
{
Success = GConfig->GetDouble(*Section, *Key, *(static_cast<double*>(Value)), Filename);
}
else if (FArrayProperty* ArrayProperty = CastField<FArrayProperty>(Type))
{
if (FStrProperty* ArrayInnerProperty = CastField<FStrProperty>(ArrayProperty->Inner))
{
TArray<FString>* Arr = (static_cast<TArray<FString>*>(Value));
if (SingleLineArray)
{
Success = (GConfig->GetSingleLineArray(*Section, *Key, *Arr, Filename) != 0);
}
else
{
Success = (GConfig->GetArray(*Section, *Key, *Arr, Filename) != 0);
}
}
}
else if (FTextProperty* TextProperty = CastField<FTextProperty>(Type))
{
Success = GConfig->GetText(*Section, *Key, *(static_cast<FText*>(Value)), Filename);
}
else if (FStructProperty* StructProperty = CastField<FStructProperty>(Type))
{
if (StructProperty->Struct->IsNative())
{
static const FName RotatorType = TEXT("Rotator");
static const FName VectorType = TEXT("Vector");
static const FName LinearColorType = TEXT("LinearColor");
static const FName Vector4Type = TEXT("Vector4");
static const FName Vector2DType = TEXT("Vector2D");
const FName TypeName = StructProperty->Struct->GetFName();
if (TypeName == RotatorType)
{
Success = GConfig->GetRotator(*Section, *Key, *(static_cast<FRotator*>(Value)), *Filename);
}
else if (TypeName == VectorType)
{
Success = GConfig->GetVector(*Section, *Key, *(static_cast<FVector*>(Value)), *Filename);
}
else if (TypeName == LinearColorType)
{
Success = GConfig->GetColor(*Section, *Key, *(static_cast<FColor*>(Value)), *Filename);
}
else if (TypeName == Vector4Type)
{
Success = GConfig->GetVector4(*Section, *Key, *(static_cast<FVector4*>(Value)), *Filename);
}
else if (TypeName == Vector2DType)
{
Success = GConfig->GetVector2D(*Section, *Key, *(static_cast<FVector2D*>(Value)), *Filename);
}
}
}
return Success;
}
void UFileHelperBPLibrary::WriteConfig(FString FilePath, FString Section, FString Key, bool& Success, bool SingleLineArrayWrite, const UStruct* Value, bool bWriteToDisk)
{
checkNoEntry();
}
bool UFileHelperBPLibrary::RemoveConfig(FString FilePath, FString Section, FString Key, bool bWriteToDisk)
{
if (!GConfig)
{
return false;
}
if (!GConfig->RemoveKey(*Section, *Key, *FilePath))
{
return false;
}
if (bWriteToDisk)
{
GConfig->Flush(false, FilePath);
}
return true;
}
// equivalent GetTableAsCSV()
bool UFileHelperBPLibrary::WriteTableToCSV(const UDataTable& InDataTable, FString& ExportedText)
{
if (!InDataTable.RowStruct)
{
return false;
}
// Write the header (column titles)
FString ImportKeyField;
if (!InDataTable.ImportKeyField.IsEmpty())
{
// Write actual name if we have it
ImportKeyField = InDataTable.ImportKeyField;
ExportedText += ImportKeyField;
}
else
{
ExportedText += TEXT("---");
}
FProperty* SkipProperty = nullptr;
for (TFieldIterator<FProperty> It(InDataTable.RowStruct); It; ++It)
{
FProperty* BaseProp = *It;
check(BaseProp);
FString ColumnHeader = DataTableUtils::GetPropertyExportName(BaseProp, EDataTableExportFlags::None);
if (ColumnHeader == ImportKeyField)
{
// Don't write header again if this is the name field, and save for skipping later
SkipProperty = BaseProp;
continue;
}
ExportedText += TEXT(",");
ExportedText += ColumnHeader;
}
ExportedText += TEXT("\n");
// Write each row
for (auto RowIt = InDataTable.GetRowMap().CreateConstIterator(); RowIt; ++RowIt)
{
FName RowName = RowIt.Key();
ExportedText += RowName.ToString();
uint8* RowData = RowIt.Value();
UFileHelperBPLibrary::WriteRowToCSV(InDataTable.RowStruct, RowData, ExportedText);
ExportedText += TEXT("\n");
}
return true;
}
bool UFileHelperBPLibrary::WriteRowToCSV(const UScriptStruct* InRowStruct, const void* InRowData, FString& ExportedText)
{
if (!InRowStruct)
{
return false;
}
for (TFieldIterator<FProperty> It(InRowStruct); It; ++It)
{
FProperty* BaseProp = *It;
check(BaseProp);
const void* Data = BaseProp->ContainerPtrToValuePtr<void>(InRowData, 0);
UFileHelperBPLibrary::WriteStructEntryToCSV(InRowData, BaseProp, Data, ExportedText);
}
return true;
}
bool UFileHelperBPLibrary::WriteStructEntryToCSV(const void* InRowData, FProperty* InProperty, const void* InPropertyData, FString& ExportedText)
{
ExportedText += TEXT(",");
const FString PropertyValue = DataTableUtils::GetPropertyValueAsString(InProperty, (uint8*)InRowData, EDataTableExportFlags::None);
ExportedText += TEXT("\"");
ExportedText += PropertyValue.Replace(TEXT("\""), TEXT("\"\""));
ExportedText += TEXT("\"");
return true;
}
// equivalent GetTableAsJSON()
FString UFileHelperBPLibrary::GetKeyFieldName(const UDataTable& InDataTable)
{
FString ExplicitString = InDataTable.ImportKeyField;
if (ExplicitString.IsEmpty())
{
return TEXT("Name");
}
else
{
return ExplicitString;
}
}
bool UFileHelperBPLibrary::WriteTableToJSON(const UDataTable& InDataTable, FString& OutExportText)
{
if (!InDataTable.RowStruct)
{
return false;
}
TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter = TJsonWriterFactory<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>::Create(&OutExportText);
FString KeyField = UFileHelperBPLibrary::GetKeyFieldName(InDataTable);
JsonWriter->WriteArrayStart();
// Iterate over rows
for (auto RowIt = InDataTable.GetRowMap().CreateConstIterator(); RowIt; ++RowIt)
{
JsonWriter->WriteObjectStart();
{
// RowName
const FName RowName = RowIt.Key();
JsonWriter->WriteValue(KeyField, RowName.ToString());
// Now the values
uint8* RowData = RowIt.Value();
UFileHelperBPLibrary::WriteRowToJSON(InDataTable.RowStruct, RowData, JsonWriter);
}
JsonWriter->WriteObjectEnd();
}
JsonWriter->WriteArrayEnd();
JsonWriter->Close();
return true;
}
bool UFileHelperBPLibrary::WriteTableAsObjectToJSON(const UDataTable& InDataTable, TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter)
{
if (!InDataTable.RowStruct)
{
return false;
}
JsonWriter->WriteObjectStart(InDataTable.GetName());
// Iterate over rows
for (auto RowIt = InDataTable.GetRowMap().CreateConstIterator(); RowIt; ++RowIt)
{
// RowName
const FName RowName = RowIt.Key();
JsonWriter->WriteObjectStart(RowName.ToString());
{
// Now the values
uint8* RowData = RowIt.Value();
UFileHelperBPLibrary::WriteRowToJSON(InDataTable.RowStruct, RowData, JsonWriter);
}
JsonWriter->WriteObjectEnd();
}
JsonWriter->WriteObjectEnd();
return true;
}
bool UFileHelperBPLibrary::WriteRowToJSON(const UScriptStruct* InRowStruct, const void* InRowData, TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter)
{
if (!InRowStruct)
{
return false;
}
return UFileHelperBPLibrary::WriteStructToJSON(InRowStruct, InRowData, JsonWriter);
}
bool UFileHelperBPLibrary::WriteStructToJSON(const UScriptStruct* InStruct, const void* InStructData, TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter)
{
for (TFieldIterator<const FProperty> It(InStruct); It; ++It)
{
const FProperty* BaseProp = *It;
check(BaseProp);
const FString Identifier = DataTableUtils::GetPropertyExportName(BaseProp, EDataTableExportFlags::UseJsonObjectsForStructs);
if (BaseProp->ArrayDim == 1)
{
const void* Data = BaseProp->ContainerPtrToValuePtr<void>(InStructData, 0);
UFileHelperBPLibrary::WriteStructEntryToJSON(InStructData, BaseProp, Data, JsonWriter);
}
else
{
JsonWriter->WriteArrayStart(Identifier);
for (int32 ArrayEntryIndex = 0; ArrayEntryIndex < BaseProp->ArrayDim; ++ArrayEntryIndex)
{
const void* Data = BaseProp->ContainerPtrToValuePtr<void>(InStructData, ArrayEntryIndex);
UFileHelperBPLibrary::WriteContainerEntryToJSON(BaseProp, Data, &Identifier, JsonWriter);
}
JsonWriter->WriteArrayEnd();
}
}
return true;
}
bool UFileHelperBPLibrary::WriteStructEntryToJSON(const void* InRowData, const FProperty* InProperty, const void* InPropertyData, TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter)
{
const FString Identifier = DataTableUtils::GetPropertyExportName(InProperty, EDataTableExportFlags::UseJsonObjectsForStructs);
if (const FEnumProperty* EnumProp = CastField<const FEnumProperty>(InProperty))
{
const FString PropertyValue = DataTableUtils::GetPropertyValueAsString(EnumProp, (uint8*)InRowData, EDataTableExportFlags::UseJsonObjectsForStructs);
JsonWriter->WriteValue(Identifier, PropertyValue);
}
else if (const FNumericProperty* NumProp = CastField<const FNumericProperty>(InProperty))
{
if (NumProp->IsEnum())
{
const FString PropertyValue = DataTableUtils::GetPropertyValueAsString(InProperty, (uint8*)InRowData, EDataTableExportFlags::UseJsonObjectsForStructs);
JsonWriter->WriteValue(Identifier, PropertyValue);
}
else if (NumProp->IsInteger())
{
const int64 PropertyValue = NumProp->GetSignedIntPropertyValue(InPropertyData);
JsonWriter->WriteValue(Identifier, PropertyValue);
}
else
{
const double PropertyValue = NumProp->GetFloatingPointPropertyValue(InPropertyData);
JsonWriter->WriteValue(Identifier, PropertyValue);
}
}
else if (const FBoolProperty* BoolProp = CastField<const FBoolProperty>(InProperty))
{
const bool PropertyValue = BoolProp->GetPropertyValue(InPropertyData);
JsonWriter->WriteValue(Identifier, PropertyValue);
}
else if (const FArrayProperty* ArrayProp = CastField<const FArrayProperty>(InProperty))
{
JsonWriter->WriteArrayStart(Identifier);
FScriptArrayHelper ArrayHelper(ArrayProp, InPropertyData);
for (int32 ArrayEntryIndex = 0; ArrayEntryIndex < ArrayHelper.Num(); ++ArrayEntryIndex)
{
const uint8* ArrayEntryData = ArrayHelper.GetRawPtr(ArrayEntryIndex);
UFileHelperBPLibrary::WriteContainerEntryToJSON(ArrayProp->Inner, ArrayEntryData, &Identifier, JsonWriter);
}
JsonWriter->WriteArrayEnd();
}
else if (const FSetProperty* SetProp = CastField<const FSetProperty>(InProperty))
{
JsonWriter->WriteArrayStart(Identifier);
FScriptSetHelper SetHelper(SetProp, InPropertyData);
for (int32 SetSparseIndex = 0; SetSparseIndex < SetHelper.GetMaxIndex(); ++SetSparseIndex)
{
if (SetHelper.IsValidIndex(SetSparseIndex))
{
const uint8* SetEntryData = SetHelper.GetElementPtr(SetSparseIndex);
UFileHelperBPLibrary::WriteContainerEntryToJSON(SetHelper.GetElementProperty(), SetEntryData, &Identifier, JsonWriter);
}
}
JsonWriter->WriteArrayEnd();
}
else if (const FMapProperty* MapProp = CastField<const FMapProperty>(InProperty))
{
JsonWriter->WriteObjectStart(Identifier);
FScriptMapHelper MapHelper(MapProp, InPropertyData);
for (int32 MapSparseIndex = 0; MapSparseIndex < MapHelper.GetMaxIndex(); ++MapSparseIndex)
{
if (MapHelper.IsValidIndex(MapSparseIndex))
{
const uint8* MapKeyData = MapHelper.GetKeyPtr(MapSparseIndex);
const uint8* MapValueData = MapHelper.GetValuePtr(MapSparseIndex);
// JSON object keys must always be strings
const FString KeyValue = DataTableUtils::GetPropertyValueAsStringDirect(MapHelper.GetKeyProperty(), (uint8*)MapKeyData, EDataTableExportFlags::UseJsonObjectsForStructs);
UFileHelperBPLibrary::WriteContainerEntryToJSON(MapHelper.GetValueProperty(), MapValueData, &KeyValue, JsonWriter);
}
}
JsonWriter->WriteObjectEnd();
}
else if (const FStructProperty* StructProp = CastField<const FStructProperty>(InProperty))
{
JsonWriter->WriteObjectStart(Identifier);
UFileHelperBPLibrary::WriteStructToJSON(StructProp->Struct, InPropertyData, JsonWriter);
JsonWriter->WriteObjectEnd();
}
else
{
const FString PropertyValue = DataTableUtils::GetPropertyValueAsString(InProperty, (uint8*)InRowData, EDataTableExportFlags::UseJsonObjectsForStructs);
JsonWriter->WriteValue(Identifier, PropertyValue);
}
return true;
}
bool UFileHelperBPLibrary::WriteContainerEntryToJSON(const FProperty* InProperty, const void* InPropertyData, const FString* InIdentifier, TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter)
{
if (const FEnumProperty* EnumProp = CastField<const FEnumProperty>(InProperty))
{
const FString PropertyValue = DataTableUtils::GetPropertyValueAsStringDirect(InProperty, (uint8*)InPropertyData, EDataTableExportFlags::UseJsonObjectsForStructs);
UFileHelperBPLibrary::WriteJSONValueWithOptionalIdentifier(JsonWriter, InIdentifier, *PropertyValue);
}
else if (const FNumericProperty* NumProp = CastField<const FNumericProperty>(InProperty))
{
if (NumProp->IsEnum())
{
const FString PropertyValue = DataTableUtils::GetPropertyValueAsStringDirect(InProperty, (uint8*)InPropertyData, EDataTableExportFlags::UseJsonObjectsForStructs);
UFileHelperBPLibrary::WriteJSONValueWithOptionalIdentifier(JsonWriter, InIdentifier, *PropertyValue);
}
else if (NumProp->IsInteger())
{
const int64 PropertyValue = NumProp->GetSignedIntPropertyValue(InPropertyData);
UFileHelperBPLibrary::WriteJSONValueWithOptionalIdentifier(JsonWriter, InIdentifier, *FString::FromInt(PropertyValue));
}
else
{
const double PropertyValue = NumProp->GetFloatingPointPropertyValue(InPropertyData);
UFileHelperBPLibrary::WriteJSONValueWithOptionalIdentifier(JsonWriter, InIdentifier, *FString::SanitizeFloat(PropertyValue));
}
}
else if (const FBoolProperty* BoolProp = CastField<const FBoolProperty>(InProperty))
{
const bool PropertyValue = BoolProp->GetPropertyValue(InPropertyData);
UFileHelperBPLibrary::WriteJSONValueWithOptionalIdentifier(JsonWriter, InIdentifier, *(PropertyValue ? FString("true") : FString("false")));
}
else if (const FStructProperty* StructProp = CastField<const FStructProperty>(InProperty))
{
UFileHelperBPLibrary::WriteJSONObjectStartWithOptionalIdentifier(JsonWriter, InIdentifier);
UFileHelperBPLibrary::WriteStructToJSON(StructProp->Struct, InPropertyData, JsonWriter);
JsonWriter->WriteObjectEnd();
}
else if (const FArrayProperty* ArrayProp = CastField<const FArrayProperty>(InProperty))
{
// Cannot nest arrays
return false;
}
else if (const FSetProperty* SetProp = CastField<const FSetProperty>(InProperty))
{
// Cannot nest sets
return false;
}
else if (const FMapProperty* MapProp = CastField<const FMapProperty>(InProperty))
{
// Cannot nest maps
return false;
}
else
{
const FString PropertyValue = DataTableUtils::GetPropertyValueAsStringDirect(InProperty, (uint8*)InPropertyData, EDataTableExportFlags::UseJsonObjectsForStructs);
UFileHelperBPLibrary::WriteJSONValueWithOptionalIdentifier(JsonWriter, InIdentifier, *PropertyValue);
}
return true;
}
void UFileHelperBPLibrary::WriteJSONObjectStartWithOptionalIdentifier(TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter, const FString* InIdentifier)
{
if (InIdentifier)
{
JsonWriter->WriteObjectStart(*InIdentifier);
}
else
{
JsonWriter->WriteObjectStart();
}
}
void UFileHelperBPLibrary::WriteJSONValueWithOptionalIdentifier(TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter, const FString* InIdentifier, const TCHAR* InValue)
{
if (InIdentifier)
{
JsonWriter->WriteValue(*InIdentifier, InValue);
}
else
{
JsonWriter->WriteValue(InValue);
}
}