/// @brief Calls Visitor(root, meta) for each GC root on the stack. /// root and meta are exactly the values passed to /// @llvm.gcroot. /// /// Visitor could be a function to recursively mark live objects. Or it /// might copy them to another heap or generation. /// /// @param Visitor A function to invoke for every GC root on the stack. void visitGCRoots(void (*Visitor)(void **Root, const void *Meta)) { for (struct StackEntry *R = llvm_gc_root_chain; R; R = R->Next) { unsigned i = 0; // For roots [0, NumMeta), the metadata pointer is in the FrameMap. for (unsigned e = R->Map->NumMeta; i != e; ++i) Visitor(&R->Roots[i], R->Map->Meta[i]); // For roots [NumMeta, NumRoots), the metadata pointer is null. for (unsigned e = R->Map->NumRoots; i != e; ++i) Visitor(&R->Roots[i], NULL); } }
void ExecuteScalarSubqueriesMatcher::visit(const ASTFunction & func, ASTPtr & ast, Data & data) { /// Don't descend into subqueries in arguments of IN operator. /// But if an argument is not subquery, than deeper may be scalar subqueries and we need to descend in them. std::vector<ASTPtr *> out; if (functionIsInOrGlobalInOperator(func.name)) { for (auto & child : ast->children) { if (child != func.arguments) out.push_back(&child); else for (size_t i = 0, size = func.arguments->children.size(); i < size; ++i) if (i != 1 || !typeid_cast<ASTSubquery *>(func.arguments->children[i].get())) out.push_back(&func.arguments->children[i]); } } else for (auto & child : ast->children) out.push_back(&child); for (ASTPtr * add_node : out) Visitor(data).visit(*add_node); }
void RequiredSourceColumnsMatcher::visit(const ASTArrayJoin & node, const ASTPtr &, Data & data) { ASTPtr expression_list = node.expression_list; if (!expression_list || expression_list->children.empty()) throw Exception("Expected not empty expression_list", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); std::vector<ASTPtr *> out; /// Tech debt. Ignore ARRAY JOIN top-level identifiers and aliases. There's its own logic for them. for (auto & expr : expression_list->children) { data.addArrayJoinAliasIfAny(*expr); if (const auto * identifier = expr->as<ASTIdentifier>()) { data.addArrayJoinIdentifier(*identifier); continue; } out.push_back(&expr); } for (ASTPtr * add_node : out) Visitor(data).visit(*add_node); }
const NamedDecl *getNamedDeclFor(const ASTContext &Context, const std::string &Name) { NamedDeclFindingASTVisitor Visitor(Name, Context); Visitor.TraverseDecl(Context.getTranslationUnitDecl()); return Visitor.getNamedDecl(); }
void TeslaConsumer::HandleTranslationUnit(ASTContext &Context) { TeslaVisitor Visitor(InFile, &Context); if (!Visitor.TraverseDecl(Context.getTranslationUnitDecl())) panic("error analysing '" + InFile + "'"); string ErrorInfo; llvm::raw_fd_ostream Out(OutFile.str().c_str(), ErrorInfo); if (Out.has_error()) panic("unable to open '" + OutFile + "': " + ErrorInfo); ManifestFile Result; for (const AutomatonDescription *A : Visitor.GetAutomata()) *Result.add_automaton() = *A; for (const Usage *U : Visitor.RootAutomata()) *Result.add_root() = *U; string ProtobufText; if (UseTextFormat) google::protobuf::TextFormat::PrintToString(Result, &ProtobufText); else Result.SerializeToString(&ProtobufText); Out << ProtobufText; }
void ActorAnimationOverrider::ApplyOverrides( TESNPC* NPC, AnimationFileListT& Files ) const { SME_ASSERT(NPC); TESAnimation* AnimData = &NPC->animation; for (AnimationFileListT::iterator Itr = Files.begin(); Itr != Files.end(); Itr++) { AnimationVisitor Visitor(&AnimData->data); char* Path = const_cast<char*>(Itr->c_str()); if (!Visitor.FindString(Path)) { UInt32 Len = strlen(Path); TESAnimation::AnimationNode* NewNode = (TESAnimation::AnimationNode*)FormHeap_Allocate(sizeof(TESAnimation::AnimationNode)); NewNode->animationName = (char*)FormHeap_Allocate(Len + 1); strcpy_s(NewNode->animationName, Len + 1, Path); NewNode->next = NULL; Visitor.Append(NewNode); #ifndef NDEBUG _MESSAGE("Override Enabled - %s", Path); #endif // !NDEBUG } } }
void ActorAnimationOverrider::ClearOverrides( TESNPC* NPC ) const { SME_ASSERT(NPC); TESAnimation* AnimData = &NPC->animation; if (AnimData->data.animationName || AnimData->data.next) { std::vector<const char*> Delinquents; for (TESAnimation::AnimationNode* Itr = &AnimData->data; Itr && Itr->Info(); Itr = Itr->Next()) { std::string File(Itr->Info()), Comparand(kOverrideFileTag); SME::StringHelpers::MakeLower(File); SME::StringHelpers::MakeLower(Comparand); if (File.find(Comparand) != std::string::npos) { // our override animation, queue it for removal Delinquents.push_back(Itr->Info()); } } for (std::vector<const char*>::iterator Itr = Delinquents.begin(); Itr != Delinquents.end(); Itr++) { #ifndef NDEBUG _MESSAGE("Override Disabled - %s", *Itr); #endif // !NDEBUG AnimationVisitor Visitor(&AnimData->data); Visitor.RemoveString(*Itr); } } }
static void visitGraph( Graph const& graph, Graph::Vertex const& start) { boost::breadth_first_search( graph.getGraph(), start, boost::visitor(Visitor())); }
FSequencerSnapField::FSequencerSnapField(const ISequencer& InSequencer, ISequencerSnapCandidate& Candidate, uint32 EntityMask) { TSharedPtr<SSequencerTreeView> TreeView = StaticCastSharedRef<SSequencer>(InSequencer.GetSequencerWidget())->GetTreeView(); TArray<TSharedRef<FSequencerDisplayNode>> VisibleNodes; for (const SSequencerTreeView::FCachedGeometry& Geometry : TreeView->GetAllVisibleNodes()) { VisibleNodes.Add(Geometry.Node); } auto ViewRange = InSequencer.GetViewRange(); FSequencerEntityWalker Walker(ViewRange); // Traverse the visible space, collecting snapping times as we go FSnapGridVisitor Visitor(Candidate, EntityMask); Walker.Traverse(Visitor, VisibleNodes); // Add the playback range start/end bounds as potential snap candidates TRange<float> PlaybackRange = InSequencer.GetFocusedMovieSceneSequence()->GetMovieScene()->GetPlaybackRange(); Visitor.Snaps.Add(FSequencerSnapPoint{ FSequencerSnapPoint::PlaybackRange, PlaybackRange.GetLowerBoundValue() }); Visitor.Snaps.Add(FSequencerSnapPoint{ FSequencerSnapPoint::PlaybackRange, PlaybackRange.GetUpperBoundValue() }); // Add the current time as a potential snap candidate Visitor.Snaps.Add(FSequencerSnapPoint{ FSequencerSnapPoint::CurrentTime, InSequencer.GetGlobalTime() }); // Add the selection range bounds as a potential snap candidate TRange<float> SelectionRange = InSequencer.GetFocusedMovieSceneSequence()->GetMovieScene()->GetSelectionRange(); Visitor.Snaps.Add(FSequencerSnapPoint{ FSequencerSnapPoint::InOutRange, SelectionRange.GetLowerBoundValue() }); Visitor.Snaps.Add(FSequencerSnapPoint{ FSequencerSnapPoint::InOutRange, SelectionRange.GetUpperBoundValue() }); // Sort Visitor.Snaps.Sort([](const FSequencerSnapPoint& A, const FSequencerSnapPoint& B){ return A.Time < B.Time; }); // Remove duplicates for (int32 Index = 0; Index < Visitor.Snaps.Num(); ++Index) { const float CurrentTime = Visitor.Snaps[Index].Time; int32 NumToMerge = 0; for (int32 DuplIndex = Index + 1; DuplIndex < Visitor.Snaps.Num(); ++DuplIndex) { if (!FMath::IsNearlyEqual(CurrentTime, Visitor.Snaps[DuplIndex].Time)) { break; } ++NumToMerge; } if (NumToMerge) { Visitor.Snaps.RemoveAt(Index + 1, NumToMerge, false); } } SortedSnaps = MoveTemp(Visitor.Snaps); }
void UploadManagerImpl::ModifyUpload( UploadHandle upload_handle, ::mf::uploader::UploadModification upload_modification ) { class Visitor : public boost::static_visitor<> { public: Visitor( UploadManagerImpl * um, UploadHandle upload_handle ) : this_(um), upload_handle_(upload_handle) {} void operator()(modification::Cancel) const { mf::utils::unique_lock<mf::utils::mutex> lock(this_->mutex_); for (auto & request : this_->requests_) { if (request->Handle().id == upload_handle_.id) { lock.unlock(); request->ProcessEvent(event::Error{ make_error_code(mf::uploader::errc::Cancelled), "Cancellation requested" }); return; } } } void operator()(modification::Pause) const { mf::utils::unique_lock<mf::utils::mutex> lock(this_->mutex_); for (auto & request : this_->requests_) { if (request->Handle().id == upload_handle_.id) { lock.unlock(); request->ProcessEvent(event::Error{ make_error_code(mf::uploader::errc::Paused), "Pause requested." }); return; } } } private: UploadManagerImpl * this_; const UploadHandle & upload_handle_; }; boost::apply_visitor(Visitor(this, upload_handle), upload_modification); }
double total(const Host& h) { double total = 0; h.accept(Visitor() .onEnter([&](const Employee& e){ total += e.getSalary(); })); return total; }
void RequiredSourceColumnsMatcher::visit(ASTSelectQuery & select, const ASTPtr &, Data & data) { /// special case for top-level SELECT items: they are publics for (auto & node : select.select()->children) { if (const auto * identifier = node->as<ASTIdentifier>()) data.addColumnIdentifier(*identifier); else data.addColumnAliasIfAny(*node); } std::vector<ASTPtr *> out; for (auto & node : select.children) if (node != select.select()) Visitor(data).visit(node); /// revisit select_expression_list (with children) when all the aliases are set Visitor(data).visit(select.refSelect()); }
void ClangDocCommentVisitor::parseComment(const comments::Comment *C) { CurrentCI.Kind = C->getCommentKindName(); ConstCommentVisitor<ClangDocCommentVisitor>::visit(C); for (comments::Comment *Child : llvm::make_range(C->child_begin(), C->child_end())) { CurrentCI.Children.emplace_back(llvm::make_unique<CommentInfo>()); ClangDocCommentVisitor Visitor(*CurrentCI.Children.back()); Visitor.parseComment(Child); } }
/** * Compare the output results from 2 lighting results * * @param Dir1 First directory of mapping file dumps to compare * @param Dir2 Seconds directory of mapping file dumps to compare * @param ErrorThreshold Any error less than this is ignored */ void CompareLightingResults(const TCHAR* Dir1, const TCHAR* Dir2, float ErrorThreshold) { UE_LOG(LogLightmass, Display, TEXT("")); UE_LOG(LogLightmass, Display, TEXT("Comparing '%s' vs '%s'"), Dir1, Dir2); FLocalCompareLightingResultsVisitor Visitor(Dir1, Dir2, ErrorThreshold); IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); PlatformFile.IterateDirectory(Dir1, Visitor); UE_LOG(LogLightmass, Display, TEXT("\nFound %d issues (out of %d mappings)..."), Visitor.NumDifferentFiles, Visitor.TotalFiles); }
std::vector<SourceLocation> getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName, Decl *Decl) { USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext()); Visitor.TraverseDecl(Decl); NestedNameSpecifierLocFinder Finder(Decl->getASTContext()); for (const auto &Location : Finder.getNestedNameSpecifierLocations()) Visitor.handleNestedNameSpecifierLoc(Location); return Visitor.getLocationsFound(); }
double median(const Host& h) { double total = 0; unsigned int empls = 0; h.accept(Visitor() .onEnter([&](const Employee& e){ total += e.getSalary(); ++empls; })); return empls ? total / empls : 0; }
void MappingContextTraits<CVType, pdb::yaml::SerializationContext>::mapping( IO &IO, CVType &Record, pdb::yaml::SerializationContext &Context) { if (IO.outputting()) { codeview::TypeDeserializer Deserializer; codeview::TypeVisitorCallbackPipeline Pipeline; Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Context.Dumper); codeview::CVTypeVisitor Visitor(Pipeline); consumeError(Visitor.visitTypeRecord(Record)); } }
bool InterpreterEmulator::Execute(Expression const& rExpr) { InterpreterExpressionVisitor Visitor(m_Hooks, m_pCpuCtxt, m_pMemCtxt); if (rExpr.Visit(&Visitor) == nullptr) return false; auto RegPc = m_pCpuInfo->GetRegisterByType(CpuInformation::ProgramPointerRegister); auto RegSz = m_pCpuInfo->GetSizeOfRegisterInBit(RegPc) / 8; u64 CurPc = 0; m_pCpuCtxt->ReadRegister(RegPc, &CurPc, RegSz); TestHook(Address(CurPc), Emulator::HookOnExecute); return true; }
unsigned int depth(const Host& h) { unsigned int max = 0, cur = 0; h.accept(Visitor() .onEnter([&](const Department&){ ++cur; }) .onExit ([&](const Department&){ if (cur > max) max = cur; --cur; })); return max; }
void FPakPlatformFile::FindPakFilesInDirectory(IPlatformFile* LowLevelFile, const TCHAR* Directory, TArray<FString>& OutPakFiles) { // Helper class to find all pak files. class FPakSearchVisitor : public IPlatformFile::FDirectoryVisitor { TArray<FString>& FoundPakFiles; IPlatformChunkInstall* ChunkInstall; public: FPakSearchVisitor(TArray<FString>& InFoundPakFiles, IPlatformChunkInstall* InChunkInstall) : FoundPakFiles(InFoundPakFiles) , ChunkInstall(InChunkInstall) {} virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) { if (bIsDirectory == false) { FString Filename(FilenameOrDirectory); if (FPaths::GetExtension(Filename) == TEXT("pak")) { // if a platform supports chunk style installs, make sure that the chunk a pak file resides in is actually fully installed before accepting pak files from it if (ChunkInstall) { FString ChunkIdentifier(TEXT("pakchunk")); FString BaseFilename = FPaths::GetBaseFilename(Filename); if (BaseFilename.StartsWith(ChunkIdentifier)) { int32 DelimiterIndex = 0; int32 StartOfChunkIndex = ChunkIdentifier.Len(); BaseFilename.FindChar(TEXT('-'), DelimiterIndex); FString ChunkNumberString = BaseFilename.Mid(StartOfChunkIndex, DelimiterIndex-StartOfChunkIndex); int32 ChunkNumber = 0; TTypeFromString<int32>::FromString(ChunkNumber, *ChunkNumberString); if (ChunkInstall->GetChunkLocation(ChunkNumber) == EChunkLocation::NotAvailable) { return true; } } } FoundPakFiles.Add(Filename); } } return true; } }; // Find all pak files. FPakSearchVisitor Visitor(OutPakFiles, FPlatformMisc::GetPlatformChunkInstall()); LowLevelFile->IterateDirectoryRecursively(Directory, Visitor); }
static void mapping(IO &IO, pdb::yaml::PdbTpiFieldListRecord &Obj, pdb::yaml::SerializationContext &Context) { assert(IO.outputting()); codeview::TypeVisitorCallbackPipeline Pipeline; BinaryByteStream Data(Obj.Record.Data, llvm::support::little); BinaryStreamReader FieldReader(Data); codeview::FieldListDeserializer Deserializer(FieldReader); // For PDB to Yaml, deserialize into a high level record type, then dump // it. Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Context.Dumper); codeview::CVTypeVisitor Visitor(Pipeline); consumeError(Visitor.visitMemberRecord(Obj.Record)); }
bool InterpreterEmulator::Execute(Expression::List const& rExprList) { InterpreterExpressionVisitor Visitor(m_Hooks, m_pCpuCtxt, m_pMemCtxt); for (auto itExpr = std::begin(rExprList); itExpr != std::end(rExprList); ++itExpr) { //Log::Write("interpreter") << "* exec: " << (*itExpr)->ToString() << LogEnd; if ((*itExpr)->Visit(&Visitor) == false) return false; auto RegPc = m_pCpuInfo->GetRegisterByType(CpuInformation::ProgramPointerRegister); auto RegSz = m_pCpuInfo->GetSizeOfRegisterInBit(RegPc) / 8; u64 CurPc = 0; m_pCpuCtxt->ReadRegister(RegPc, &CurPc, RegSz); TestHook(Address(CurPc), Emulator::HookOnExecute); } return true; }
Item(OtherClass const& item) : _fields(OtherClass::__fields__) { # ifdef ZHTTP_DEBUG assert(::strcmp(SelfClass::__name__, OtherClass::__name__) == 0 && "Wrong item copy"); # endif LOG_DEBUG("Copy " + std::string(SelfClass::__name__)); OtherClass& self = dynamic_cast<OtherClass&>(*this); struct Visitor : public db::IVisitor { OtherClass& self; Visitor(OtherClass& self, IAttribute& self_attr) : self(self) {} void visitInt(db::AttributeInt const& attr, db::IItem const& i) { attr.setValue(self, attr.getValue(i)); } void visitInt64(db::AttributeInt64 const& attr, db::IItem const& i) { attr.setValue(self, attr.getValue(i)); } void visitUint64(db::AttributeUint64 const& attr, db::IItem const& i) { attr.setValue(self, attr.getValue(i)); } void visitDouble(db::AttributeDouble const& attr, db::IItem const& i) { attr.setValue(self, attr.getValue(i)); } void visitFloat(db::AttributeFloat const& attr, db::IItem const& i) { attr.setValue(self, attr.getValue(i)); } void visitString(db::AttributeString const& attr, db::IItem const& i) { attr.setValue(self, attr.getValue(i)); } void visitBool(db::AttributeBool const& attr, db::IItem const& i) { attr.setValue(self, attr.getValue(i)); } }; item.visitAll(Visitor(self)); }
bool InterpreterEmulator::Execute(Address const& rAddress, Expression::List const& rExprList) { InterpreterExpressionVisitor Visitor(m_Hooks, m_pCpuCtxt, m_pMemCtxt, m_pVarCtxt); for (Expression* pExpr : rExprList) { auto pCurExpr = pExpr->Visit(&Visitor); if (pCurExpr == nullptr) return false; auto RegPc = m_pCpuInfo->GetRegisterByType(CpuInformation::ProgramPointerRegister, m_pCpuCtxt->GetMode()); auto RegSz = m_pCpuInfo->GetSizeOfRegisterInBit(RegPc) / 8; u64 CurPc = 0; m_pCpuCtxt->ReadRegister(RegPc, &CurPc, RegSz); TestHook(Address(CurPc), Emulator::HookOnExecute); delete pCurExpr; } return true; }
void print(const Host& h, unsigned int i) { h.accept(Visitor() .onEnter([&](const Company & c){ std::fill_n(std::ostream_iterator<char>(std::cout), i++, '\t'); std::cout << c.getName() << "\n"; }) .onEnter([&](const Department& d){ std::fill_n(std::ostream_iterator<char>(std::cout), i++, '\t'); std::cout << d.getName() << "\n"; }) .onEnter([&](const Employee & e){ std::fill_n(std::ostream_iterator<char>(std::cout), i, '\t'); std::cout << e.getName () << ", " << e.getAddress() << ", " << e.getSalary () << '\n'; }) .onExit ([&](const Company &){ --i; }) .onExit ([&](const Department&){ --i; })); }
const NamedDecl *getNamedDeclAt(const ASTContext &Context, const SourceLocation Point) { StringRef SearchFile = Context.getSourceManager().getFilename(Point); NamedDeclFindingASTVisitor Visitor(Point, Context); // We only want to search the decls that exist in the same file as the point. for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) { const SourceLocation FileLoc = CurrDecl->getLocStart(); StringRef FileName = Context.getSourceManager().getFilename(FileLoc); // FIXME: Add test. if (FileName == SearchFile) { Visitor.TraverseDecl(CurrDecl); } } NestedNameSpecifierLocFinder Finder(const_cast<ASTContext &>(Context)); for (const auto &Location : Finder.getNestedNameSpecifierLocations()) { Visitor.handleNestedNameSpecifierLoc(Location); } return Visitor.getNamedDecl(); }
const NamedDecl *getNamedDeclAt(const ASTContext &Context, const SourceLocation Point) { const SourceManager &SM = Context.getSourceManager(); NamedDeclFindingASTVisitor Visitor(Point, Context); // Try to be clever about pruning down the number of top-level declarations we // see. If both start and end is either before or after the point we're // looking for the point cannot be inside of this decl. Don't even look at it. for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) { SourceLocation StartLoc = CurrDecl->getLocStart(); SourceLocation EndLoc = CurrDecl->getLocEnd(); if (StartLoc.isValid() && EndLoc.isValid() && SM.isBeforeInTranslationUnit(StartLoc, Point) != SM.isBeforeInTranslationUnit(EndLoc, Point)) Visitor.TraverseDecl(CurrDecl); } NestedNameSpecifierLocFinder Finder(const_cast<ASTContext &>(Context)); for (const auto &Location : Finder.getNestedNameSpecifierLocations()) Visitor.handleNestedNameSpecifierLoc(Location); return Visitor.getNamedDecl(); }
static void mapping(IO &IO, pdb::yaml::PdbTpiFieldListRecord &Obj, pdb::yaml::SerializationContext &Context) { codeview::TypeVisitorCallbackPipeline Pipeline; codeview::TypeDeserializer Deserializer; codeview::TypeSerializationVisitor Serializer(Context.FieldListBuilder, Context.TypeTableBuilder); pdb::TpiHashUpdater Hasher; if (IO.outputting()) { // For PDB to Yaml, deserialize into a high level record type, then dump // it. Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Context.Dumper); } else { // For Yaml to PDB, extract from the high level record type, then write it // to bytes. Pipeline.addCallbackToPipeline(Context.Dumper); Pipeline.addCallbackToPipeline(Serializer); Pipeline.addCallbackToPipeline(Hasher); } codeview::CVTypeVisitor Visitor(Pipeline); consumeError(Visitor.visitMemberRecord(Obj.Record)); }
template <class Visitor> void visit(Visitor v = Visitor()) { m_impl.visit(v); }
bool FNetworkFileServerClientConnection::ProcessGetFileList( FArchive& In, FArchive& Out ) { // get the list of directories to process TArray<FString> TargetPlatformNames; FString GameName; FString EngineRelativePath; FString GameRelativePath; TArray<FString> RootDirectories; bool bIsStreamingRequest = false; In << TargetPlatformNames; In << GameName; In << EngineRelativePath; In << GameRelativePath; In << RootDirectories; In << bIsStreamingRequest; ConnectedPlatformName = TEXT(""); bool bSendLowerCase = false; // if we didn't find one (and this is a dumb server - no active platforms), then just use what was sent if (ActiveTargetPlatforms.Num() == 0) { ConnectedPlatformName = TargetPlatformNames[0]; } // we only need to care about validating the connected platform if there are active targetplatforms else { // figure out the best matching target platform for the set of valid ones for (int32 TPIndex = 0; TPIndex < TargetPlatformNames.Num() && ConnectedPlatformName == TEXT(""); TPIndex++) { UE_LOG(LogFileServer, Display, TEXT(" Possible Target Platform from client: %s"), *TargetPlatformNames[TPIndex]); // look for a matching target platform for (int32 ActiveTPIndex = 0; ActiveTPIndex < ActiveTargetPlatforms.Num(); ActiveTPIndex++) { UE_LOG(LogFileServer, Display, TEXT(" Checking against: %s"), *ActiveTargetPlatforms[ActiveTPIndex]->PlatformName()); if (ActiveTargetPlatforms[ActiveTPIndex]->PlatformName() == TargetPlatformNames[TPIndex]) { bSendLowerCase = ActiveTargetPlatforms[ActiveTPIndex]->SendLowerCaseFilePaths(); ConnectedPlatformName = ActiveTargetPlatforms[ActiveTPIndex]->PlatformName(); break; } } } // if we didn't find one, reject client and also print some warnings if (ConnectedPlatformName == TEXT("")) { // reject client we can't cook/compile shaders for you! UE_LOG(LogFileServer, Warning, TEXT("Unable to find target platform for client, terminating client connection!")); for (int32 TPIndex = 0; TPIndex < TargetPlatformNames.Num() && ConnectedPlatformName == TEXT(""); TPIndex++) { UE_LOG(LogFileServer, Warning, TEXT(" Target platforms from client: %s"), *TargetPlatformNames[TPIndex]); } for (int32 ActiveTPIndex = 0; ActiveTPIndex < ActiveTargetPlatforms.Num(); ActiveTPIndex++) { UE_LOG(LogFileServer, Warning, TEXT(" Active target platforms on server: %s"), *ActiveTargetPlatforms[ActiveTPIndex]->PlatformName()); } return false; } } ConnectedEngineDir = EngineRelativePath; ConnectedGameDir = GameRelativePath; FString LocalEngineDir = FPaths::EngineDir(); FString LocalGameDir = FPaths::GameDir(); if ( FPaths::IsProjectFilePathSet() ) { LocalGameDir = FPaths::GetPath(FPaths::GetProjectFilePath()) + TEXT("/"); } UE_LOG(LogFileServer, Display, TEXT(" Connected EngineDir = %s"), *ConnectedEngineDir); UE_LOG(LogFileServer, Display, TEXT(" Local EngineDir = %s"), *LocalEngineDir); UE_LOG(LogFileServer, Display, TEXT(" Connected GameDir = %s"), *ConnectedGameDir); UE_LOG(LogFileServer, Display, TEXT(" Local GameDir = %s"), *LocalGameDir); // Remap the root directories requested... for (int32 RootDirIdx = 0; RootDirIdx < RootDirectories.Num(); RootDirIdx++) { FString CheckRootDir = RootDirectories[RootDirIdx]; ConvertClientFilenameToServerFilename(CheckRootDir); RootDirectories[RootDirIdx] = CheckRootDir; } // figure out the sandbox directory // @todo: This should use FPlatformMisc::SavedDirectory(GameName) FString SandboxDirectory; if ( FPaths::IsProjectFilePathSet() ) { FString ProjectDir = FPaths::GetPath(FPaths::GetProjectFilePath()); SandboxDirectory = FPaths::Combine(*ProjectDir, TEXT("Saved"), TEXT("Cooked"), *ConnectedPlatformName); if( bIsStreamingRequest ) { RootDirectories.Add(ProjectDir); } } else { if (FPaths::GetExtension(GameName) == FProjectDescriptor::GetExtension()) { SandboxDirectory = FPaths::Combine(*FPaths::GetPath(GameName), TEXT("Saved"), TEXT("Cooked"), *ConnectedPlatformName); } else { //@todo: This assumes the game is located in the UE4 Root directory SandboxDirectory = FPaths::Combine(*FPaths::GetRelativePathToRoot(), *GameName, TEXT("Saved"), TEXT("Cooked"), *ConnectedPlatformName); } } // Convert to full path so that the sandbox wrapper doesn't re-base to Saved/Sandboxes SandboxDirectory = FPaths::ConvertRelativePathToFull(SandboxDirectory); // delete any existing one first, in case game name somehow changed and client is re-asking for files (highly unlikely) delete Sandbox; Sandbox = new FSandboxPlatformFile(false); Sandbox->Initialize(&FPlatformFileManager::Get().GetPlatformFile(), *FString::Printf(TEXT("-sandbox=\"%s\""), *SandboxDirectory)); // make sure the global shaders are up to date before letting the client read any shaders // @todo: This will probably add about 1/2 second to the boot-up time of the client while the server does this // @note: We assume the delegate will write to the proper sandbox directory, should we pass in SandboxDirectory, or Sandbox? FShaderRecompileData RecompileData; RecompileData.PlatformName = ConnectedPlatformName; // All target platforms RecompileData.ShaderPlatform = -1; RecompileData.ModifiedFiles = NULL; RecompileData.MeshMaterialMaps = NULL; RecompileShadersDelegate.ExecuteIfBound(RecompileData); UE_LOG(LogFileServer, Display, TEXT("Getting files for %d directories, game = %s, platform = %s"), RootDirectories.Num(), *GameName, *ConnectedPlatformName); UE_LOG(LogFileServer, Display, TEXT(" Sandbox dir = %s"), *SandboxDirectory); for (int32 DumpIdx = 0; DumpIdx < RootDirectories.Num(); DumpIdx++) { UE_LOG(LogFileServer, Display, TEXT("\t%s"), *(RootDirectories[DumpIdx])); } TArray<FString> DirectoriesToAlwaysStageAsUFS; if ( GConfig->GetArray(TEXT("/Script/UnrealEd.ProjectPackagingSettings"), TEXT("DirectoriesToAlwaysStageAsUFS"), DirectoriesToAlwaysStageAsUFS, GGameIni) ) { for ( const auto& DirectoryToAlwaysStage : DirectoriesToAlwaysStageAsUFS ) { RootDirectories.Add( DirectoryToAlwaysStage ); } } // list of directories to skip TArray<FString> DirectoriesToSkip; TArray<FString> DirectoriesToNotRecurse; // @todo: This should really be FPlatformMisc::GetSavedDirForGame(ClientGameName), etc for (int32 DirIndex = 0; DirIndex < RootDirectories.Num(); DirIndex++) { DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Saved/Backup"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Saved/Config"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Saved/Logs"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Saved/Sandboxes"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Saved/Cooked"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Saved/ShaderDebugInfo"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Saved/StagedBuilds"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Intermediate"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Documentation"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Extras"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Binaries"))); DirectoriesToSkip.Add(FString(RootDirectories[DirIndex] / TEXT("Source"))); DirectoriesToNotRecurse.Add(FString(RootDirectories[DirIndex] / TEXT("DerivedDataCache"))); } // use the timestamp grabbing visitor (include directories) FLocalTimestampDirectoryVisitor Visitor(*Sandbox, DirectoriesToSkip, DirectoriesToNotRecurse, true); for (int32 DirIndex = 0; DirIndex < RootDirectories.Num(); DirIndex++) { Sandbox->IterateDirectory(*RootDirectories[DirIndex], Visitor); } // report the package version information // The downside of this is that ALL cooked data will get tossed on package version changes Out << GPackageFileUE4Version; Out << GPackageFileLicenseeUE4Version; // Send *our* engine and game dirs Out << LocalEngineDir; Out << LocalGameDir; // return the files and their timestamps TMap<FString, FDateTime> FixedTimes = FixupSandboxPathsForClient(Sandbox, Visitor.FileTimes, LocalEngineDir, LocalGameDir, bSendLowerCase); Out << FixedTimes; // Do it again, preventing access to non-cooked files if( bIsStreamingRequest == false ) { // Do it again, preventing access to non-cooked files const int32 NUM_EXCLUSION_WILDCARDS = 2; FString ExclusionWildcard[NUM_EXCLUSION_WILDCARDS]; ExclusionWildcard[0] = FString(TEXT("*")) + FPackageName::GetAssetPackageExtension(); ExclusionWildcard[1] = FString(TEXT("*")) + FPackageName::GetMapPackageExtension(); for (int32 i=0; i < NUM_EXCLUSION_WILDCARDS; ++i) { Sandbox->AddExclusion(*ExclusionWildcard[i]); UE_LOG(LogFileServer, Display, TEXT("Excluding %s from non-sandboxed directories"), *ExclusionWildcard[i]); } FLocalTimestampDirectoryVisitor VisitorForCacheDates(*Sandbox, DirectoriesToSkip, DirectoriesToNotRecurse, true); for (int32 DirIndex = 0; DirIndex < RootDirectories.Num(); DirIndex++) { Sandbox->IterateDirectory(*RootDirectories[DirIndex], VisitorForCacheDates); } // return the cached files and their timestamps FixedTimes = FixupSandboxPathsForClient(Sandbox, VisitorForCacheDates.FileTimes, LocalEngineDir, LocalGameDir, bSendLowerCase); Out << FixedTimes; } return true; }