// Copyright Epic Games, Inc. All Rights Reserved. #include "oplogreferencedset.h" #include "projectstore.h" #include #include #include namespace zen { std::optional OplogReferencedSet::LoadFromChunk(const IoBuffer& ChunkData) { using namespace std::literals; if (!ChunkData || ChunkData.Size() == 0) { return std::optional(); } std::string_view ChunkText(reinterpret_cast(ChunkData.Data()), ChunkData.Size()); AsciiSet TrimWhitespace(" \t\r\n"); const char* FirstNonComment = nullptr; uint64_t Version = 0; // Parse the initial comment block: the leading block of empty or comment lines. ForEachStrTok(ChunkText, '\n', [&Version, &FirstNonComment, &TrimWhitespace](std::string_view Line) { Line = AsciiSet::TrimSuffixWith(AsciiSet::TrimPrefixWith(Line, TrimWhitespace), TrimWhitespace); if (Line.empty()) { return true; // empty line, keep reading } if (!Line.starts_with('#')) { FirstNonComment = Line.data(); return false; // non-comment line, stop } // Comment line in the header block of comments in the file. Interpret it if it is a version line. // Skip past the '#' and whitespace. Line.remove_prefix(1); Line = AsciiSet::TrimPrefixWith(Line, TrimWhitespace); // Parse "# Version ". constexpr std::string_view VersionStr("Version "sv); if (Line.starts_with(VersionStr)) { std::string_view VersionToken = Line; VersionToken.remove_prefix(VersionStr.length()); VersionToken.remove_suffix(AsciiSet::TrimPrefixWithout(VersionToken, TrimWhitespace).length()); std::optional ParsedVersion = ParseInt(VersionToken); if (ParsedVersion) { Version = *ParsedVersion; } } return true; }); // Report no referencedset if the version is below our minimum version. constexpr uint64_t MinSupportedVersion = 1; if (Version < MinSupportedVersion) { ZEN_INFO("ReferencedSet is below the minimum supported version, ignoring it. Version: {}, minimum version: {}.", Version, MinSupportedVersion); return std::optional(); } // Parse the remaining lines after the leading comment block. ChunkText.remove_prefix(FirstNonComment ? FirstNonComment - ChunkText.data() : ChunkText.length()); OplogReferencedSet Result; ForEachStrTok(ChunkText, '\n', [&Result, &TrimWhitespace](std::string_view Line) { Line = AsciiSet::TrimSuffixWith(AsciiSet::TrimPrefixWith(Line, TrimWhitespace), TrimWhitespace); if (!Line.empty() && !Line.starts_with('#')) { Result.Emplace(OpKeyStringAsOid(Line)); } return true; }); return std::optional(std::move(Result)); } void OplogReferencedSet::Emplace(Oid OplogId) { Set.emplace(OplogId); } void OplogReferencedSet::Clear() { Set.clear(); } bool OplogReferencedSet::Contains(Oid OplogId, std::string_view OplogKey) { // A referencedset always includes all non-package keys if (OplogKey.empty() || !OplogKey.starts_with("/")) { return true; } return Set.contains(OplogId); } } // namespace zen